any.h 30.8 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
21

22 23
#ifndef CAPNP_ANY_H_
#define CAPNP_ANY_H_
24

25 26 27 28
#if defined(__GNUC__) && !CAPNP_HEADER_WARNINGS
#pragma GCC system_header
#endif

29 30
#include "layout.h"
#include "pointer-helpers.h"
31
#include "orphan.h"
32
#include "list.h"
33 34 35 36 37

namespace capnp {

class StructSchema;
class ListSchema;
38
class InterfaceSchema;
39
class Orphanage;
Kenton Varda's avatar
Kenton Varda committed
40
class ClientHook;
41
class PipelineHook;
42
struct PipelineOp;
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
struct AnyPointer;

struct AnyList {
  AnyList() = delete;

  class Reader;
  class Builder;
};

struct AnyStruct {
  AnyStruct() = delete;

  class Reader;
  class Builder;
  class Pipeline;
};

template<>
struct List<AnyStruct, Kind::OTHER> {
  List() = delete;

  class Reader;
  class Builder;
};

namespace _ {  // private
template <> struct Kind_<AnyPointer> { static constexpr Kind kind = Kind::OTHER; };
template <> struct Kind_<AnyStruct> { static constexpr Kind kind = Kind::OTHER; };
template <> struct Kind_<AnyList> { static constexpr Kind kind = Kind::OTHER; };
}  // namespace _ (private)
73 74

// =======================================================================================
75
// AnyPointer!
76

77
enum class Equality {
78 79 80 81 82
  NOT_EQUAL,
  EQUAL,
  UNKNOWN_CONTAINS_CAPS
};

83
kj::StringPtr KJ_STRINGIFY(Equality res);
84

85 86
struct AnyPointer {
  // Reader/Builder for the `AnyPointer` field type, i.e. a pointer that can point to an arbitrary
87 88
  // object.

89 90
  AnyPointer() = delete;

91 92
  class Reader {
  public:
93
    typedef AnyPointer Reads;
94

95 96 97
    Reader() = default;
    inline Reader(_::PointerReader reader): reader(reader) {}

98 99
    inline MessageSize targetSize() const;
    // Get the total size of the target object and all its children.
Kenton Varda's avatar
Kenton Varda committed
100

101 102 103 104 105 106
    inline PointerType getPointerType() const;

    inline bool isNull() const { return getPointerType() == PointerType::NULL_; }
    inline bool isStruct() const { return getPointerType() == PointerType::STRUCT; }
    inline bool isList() const { return getPointerType() == PointerType::LIST; }
    inline bool isCapability() const { return getPointerType() == PointerType::CAPABILITY; }
107

108
    Equality equals(AnyPointer::Reader right);
109 110
    bool operator==(AnyPointer::Reader right);
    inline bool operator!=(AnyPointer::Reader right) {
111
      return !(*this == right);
112
    }
113 114

    template <typename T>
115 116
    inline ReaderFor<T> getAs() const;
    // Valid for T = any generated struct type, interface type, List<U>, Text, or Data.
117 118

    template <typename T>
119
    inline ReaderFor<T> getAs(StructSchema schema) const;
120 121 122
    // Only valid for T = DynamicStruct.  Requires `#include <capnp/dynamic.h>`.

    template <typename T>
123
    inline ReaderFor<T> getAs(ListSchema schema) const;
124 125
    // Only valid for T = DynamicList.  Requires `#include <capnp/dynamic.h>`.

126 127 128 129
    template <typename T>
    inline ReaderFor<T> getAs(InterfaceSchema schema) const;
    // Only valid for T = DynamicCapability.  Requires `#include <capnp/dynamic.h>`.

130
#if !CAPNP_LITE
131
    kj::Own<ClientHook> getPipelinedCap(kj::ArrayPtr<const PipelineOp> ops) const;
Kenton Varda's avatar
Kenton Varda committed
132 133
    // Used by RPC system to implement pipelining.  Applications generally shouldn't use this
    // directly.
134
#endif  // !CAPNP_LITE
Kenton Varda's avatar
Kenton Varda committed
135

136 137
  private:
    _::PointerReader reader;
138
    friend struct AnyPointer;
139
    friend class Orphanage;
140
    friend class CapReaderContext;
141 142 143 144
  };

  class Builder {
  public:
145
    typedef AnyPointer Builds;
146

147 148 149 150
    Builder() = delete;
    inline Builder(decltype(nullptr)) {}
    inline Builder(_::PointerBuilder builder): builder(builder) {}

151 152
    inline MessageSize targetSize() const;
    // Get the total size of the target object and all its children.
Kenton Varda's avatar
Kenton Varda committed
153

154 155 156 157 158 159
    inline PointerType getPointerType();

    inline bool isNull() { return getPointerType() == PointerType::NULL_; }
    inline bool isStruct() { return getPointerType() == PointerType::STRUCT; }
    inline bool isList() { return getPointerType() == PointerType::LIST; }
    inline bool isCapability() { return getPointerType() == PointerType::CAPABILITY; }
160

161
    inline Equality equals(AnyPointer::Reader right) {
162 163
      return asReader().equals(right);
    }
164
    inline bool operator==(AnyPointer::Reader right) {
165
      return asReader() == right;
166
    }
167
    inline bool operator!=(AnyPointer::Reader right) {
168
      return !(*this == right);
169
    }
170 171 172 173 174

    inline void clear();
    // Set to null.

    template <typename T>
175
    inline BuilderFor<T> getAs();
176 177 178
    // Valid for T = any generated struct type, List<U>, Text, or Data.

    template <typename T>
179
    inline BuilderFor<T> getAs(StructSchema schema);
180 181 182
    // Only valid for T = DynamicStruct.  Requires `#include <capnp/dynamic.h>`.

    template <typename T>
183
    inline BuilderFor<T> getAs(ListSchema schema);
184 185 186
    // Only valid for T = DynamicList.  Requires `#include <capnp/dynamic.h>`.

    template <typename T>
187 188 189 190 191
    inline BuilderFor<T> getAs(InterfaceSchema schema);
    // Only valid for T = DynamicCapability.  Requires `#include <capnp/dynamic.h>`.

    template <typename T>
    inline BuilderFor<T> initAs();
192 193 194
    // Valid for T = any generated struct type.

    template <typename T>
195
    inline BuilderFor<T> initAs(uint elementCount);
196 197 198
    // Valid for T = List<U>, Text, or Data.

    template <typename T>
199
    inline BuilderFor<T> initAs(StructSchema schema);
200 201 202
    // Only valid for T = DynamicStruct.  Requires `#include <capnp/dynamic.h>`.

    template <typename T>
203
    inline BuilderFor<T> initAs(ListSchema schema, uint elementCount);
204 205
    // Only valid for T = DynamicList.  Requires `#include <capnp/dynamic.h>`.

206
    inline AnyList::Builder initAsAnyList(ElementSize elementSize, uint elementCount);
207 208
    // Note: Does not accept INLINE_COMPOSITE for elementSize.

209 210
    inline List<AnyStruct>::Builder initAsListOfAnyStruct(
        uint dataWordCount, uint pointerCount, uint elementCount);
211 212 213

    inline AnyStruct::Builder initAsAnyStruct(uint dataWordCount, uint pointerCount);

214
    template <typename T>
215
    inline void setAs(ReaderFor<T> value);
216 217 218 219 220 221 222
    // Valid for ReaderType = T::Reader for T = any generated struct type, List<U>, Text, Data,
    // DynamicStruct, or DynamicList (the dynamic types require `#include <capnp/dynamic.h>`).

    template <typename T>
    inline void setAs(std::initializer_list<ReaderFor<ListElementType<T>>> list);
    // Valid for T = List<?>.

223
    inline void set(Reader value) { builder.copyFrom(value.reader); }
224
    // Set to a copy of another AnyPointer.
225

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
    template <typename T>
    inline void adopt(Orphan<T>&& orphan);
    // Valid for T = any generated struct type, List<U>, Text, Data, DynamicList, DynamicStruct,
    // or DynamicValue (the dynamic types require `#include <capnp/dynamic.h>`).

    template <typename T>
    inline Orphan<T> disownAs();
    // Valid for T = any generated struct type, List<U>, Text, Data.

    template <typename T>
    inline Orphan<T> disownAs(StructSchema schema);
    // Only valid for T = DynamicStruct.  Requires `#include <capnp/dynamic.h>`.

    template <typename T>
    inline Orphan<T> disownAs(ListSchema schema);
    // Only valid for T = DynamicList.  Requires `#include <capnp/dynamic.h>`.

243 244 245 246
    template <typename T>
    inline Orphan<T> disownAs(InterfaceSchema schema);
    // Only valid for T = DynamicCapability.  Requires `#include <capnp/dynamic.h>`.

247
    inline Orphan<AnyPointer> disown();
248 249 250 251 252
    // Disown without a type.

    inline Reader asReader() const { return Reader(builder.asReader()); }
    inline operator Reader() const { return Reader(builder.asReader()); }

253 254
  private:
    _::PointerBuilder builder;
255
    friend class Orphanage;
256
    friend class CapBuilderContext;
257
  };
258

259
#if !CAPNP_LITE
260 261
  class Pipeline {
  public:
262 263
    typedef AnyPointer Pipelines;

264
    inline Pipeline(decltype(nullptr)) {}
265
    inline explicit Pipeline(kj::Own<PipelineHook>&& hook): hook(kj::mv(hook)) {}
266

267
    Pipeline noop();
268 269
    // Just make a copy.

270
    Pipeline getPointerField(uint16_t pointerIndex);
271 272 273
    // Deprecated. In the future, we should use .asAnyStruct.getPointerField.

    inline AnyStruct::Pipeline asAnyStruct();
274

275
    kj::Own<ClientHook> asCap();
276 277
    // Expect that the result is a capability and construct a pipelined version of it now.

278
    inline kj::Own<PipelineHook> releasePipelineHook() { return kj::mv(hook); }
Kenton Varda's avatar
Kenton Varda committed
279 280
    // For use by RPC implementations.

281 282 283
    template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromClient<T>) == Kind::INTERFACE>>
    inline operator T() { return T(asCap()); }

284
  private:
285
    kj::Own<PipelineHook> hook;
286 287
    kj::Array<PipelineOp> ops;

288
    inline Pipeline(kj::Own<PipelineHook>&& hook, kj::Array<PipelineOp>&& ops)
289
        : hook(kj::mv(hook)), ops(kj::mv(ops)) {}
290 291

    friend class LocalClient;
292
    friend class PipelineHook;
293
    friend class AnyStruct::Pipeline;
294
  };
295
#endif  // !CAPNP_LITE
296 297
};

298
template <>
299
class Orphan<AnyPointer> {
300 301 302 303 304 305 306 307
  // An orphaned object of unknown type.

public:
  Orphan() = default;
  KJ_DISALLOW_COPY(Orphan);
  Orphan(Orphan&&) = default;
  Orphan& operator=(Orphan&&) = default;

308 309 310
  template <typename T>
  inline Orphan(Orphan<T>&& other): builder(kj::mv(other.builder)) {}
  template <typename T>
311
  inline Orphan& operator=(Orphan<T>&& other) { builder = kj::mv(other.builder); return *this; }
312 313
  // Cast from typed orphan.

314
  // It's not possible to get an AnyPointer::{Reader,Builder} directly since there is no
315
  // underlying pointer (the pointer would normally live in the parent, but this object is
316
  // orphaned).  It is possible, however, to request typed readers/builders.
317 318

  template <typename T>
319
  inline BuilderFor<T> getAs();
320
  template <typename T>
321
  inline BuilderFor<T> getAs(StructSchema schema);
322
  template <typename T>
323
  inline BuilderFor<T> getAs(ListSchema schema);
324
  template <typename T>
325
  inline typename T::Client getAs(InterfaceSchema schema);
326
  template <typename T>
327
  inline ReaderFor<T> getAsReader() const;
328
  template <typename T>
329 330 331 332 333
  inline ReaderFor<T> getAsReader(StructSchema schema) const;
  template <typename T>
  inline ReaderFor<T> getAsReader(ListSchema schema) const;
  template <typename T>
  inline typename T::Client getAsReader(InterfaceSchema schema) const;
334 335 336 337 338 339 340

  template <typename T>
  inline Orphan<T> releaseAs();
  template <typename T>
  inline Orphan<T> releaseAs(StructSchema schema);
  template <typename T>
  inline Orphan<T> releaseAs(ListSchema schema);
341 342
  template <typename T>
  inline Orphan<T> releaseAs(InterfaceSchema schema);
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
  // Down-cast the orphan to a specific type.

  inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
  inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }

private:
  _::OrphanBuilder builder;

  inline Orphan(_::OrphanBuilder&& builder)
      : builder(kj::mv(builder)) {}

  template <typename, Kind>
  friend struct _::PointerHelpers;
  friend class Orphanage;
  template <typename U>
  friend class Orphan;
359
  friend class AnyPointer::Builder;
360 361
};

362 363 364 365 366
template <Kind k> struct AnyTypeFor_;
template <> struct AnyTypeFor_<Kind::STRUCT> { typedef AnyStruct Type; };
template <> struct AnyTypeFor_<Kind::LIST> { typedef AnyList Type; };

template <typename T>
Kenton Varda's avatar
Kenton Varda committed
367
using AnyTypeFor = typename AnyTypeFor_<CAPNP_KIND(T)>::Type;
368 369 370

template <typename T>
inline ReaderFor<AnyTypeFor<FromReader<T>>> toAny(T&& value) {
371
  return ReaderFor<AnyTypeFor<FromReader<T>>>(
372 373 374 375
      _::PointerHelpers<FromReader<T>>::getInternalReader(value));
}
template <typename T>
inline BuilderFor<AnyTypeFor<FromBuilder<T>>> toAny(T&& value) {
376
  return BuilderFor<AnyTypeFor<FromBuilder<T>>>(
377 378 379 380 381
      _::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(value)));
}

template <>
struct List<AnyPointer, Kind::OTHER> {
382 383 384
  // Note: This cannot be used for a list of structs, since such lists are not encoded as pointer
  //   lists! Use List<AnyStruct>.

385 386 387 388 389 390 391 392 393 394
  List() = delete;

  class Reader {
  public:
    typedef List<AnyPointer> Reads;

    Reader() = default;
    inline explicit Reader(_::ListReader reader): reader(reader) {}

    inline uint size() const { return reader.size() / ELEMENTS; }
395
    inline AnyPointer::Reader operator[](uint index) const {
396
      KJ_IREQUIRE(index < size());
397
      return AnyPointer::Reader(reader.getPointerElement(index * ELEMENTS));
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
    }

    typedef _::IndexingIterator<const Reader, typename AnyPointer::Reader> Iterator;
    inline Iterator begin() const { return Iterator(this, 0); }
    inline Iterator end() const { return Iterator(this, size()); }

  private:
    _::ListReader reader;
    template <typename U, Kind K>
    friend struct _::PointerHelpers;
    template <typename U, Kind K>
    friend struct List;
    friend class Orphanage;
    template <typename U, Kind K>
    friend struct ToDynamic_;
  };

  class Builder {
  public:
    typedef List<AnyPointer> Builds;

    Builder() = delete;
    inline Builder(decltype(nullptr)) {}
    inline explicit Builder(_::ListBuilder builder): builder(builder) {}

    inline operator Reader() { return Reader(builder.asReader()); }
    inline Reader asReader() { return Reader(builder.asReader()); }

    inline uint size() const { return builder.size() / ELEMENTS; }
427
    inline AnyPointer::Builder operator[](uint index) {
428
      KJ_IREQUIRE(index < size());
429
      return AnyPointer::Builder(builder.getPointerElement(index * ELEMENTS));
430 431 432 433 434 435 436 437
    }

    typedef _::IndexingIterator<Builder, typename AnyPointer::Builder> Iterator;
    inline Iterator begin() { return Iterator(this, 0); }
    inline Iterator end() { return Iterator(this, size()); }

  private:
    _::ListBuilder builder;
438
    template <typename, Kind>
439 440
    friend struct _::PointerHelpers;
    friend class Orphanage;
441
    template <typename, Kind>
442 443 444 445 446 447 448 449 450
    friend struct ToDynamic_;
  };
};

class AnyStruct::Reader {
public:
  Reader() = default;
  inline Reader(_::StructReader reader): _reader(reader) {}

451
#if !_MSC_VER  // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves.
Kenton Varda's avatar
Kenton Varda committed
452
  template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromReader<T>) == Kind::STRUCT>>
453 454
  inline Reader(T&& value)
      : _reader(_::PointerHelpers<FromReader<T>>::getInternalReader(kj::fwd<T>(value))) {}
455
#endif
456

457
  kj::ArrayPtr<const byte> getDataSection() {
458 459 460 461 462 463
    return _reader.getDataSectionAsBlob();
  }
  List<AnyPointer>::Reader getPointerSection() {
    return List<AnyPointer>::Reader(_reader.getPointerSectionAsList());
  }

464
  Equality equals(AnyStruct::Reader right);
465 466
  bool operator==(AnyStruct::Reader right);
  inline bool operator!=(AnyStruct::Reader right) {
467 468 469
    return !(*this == right);
  }

470
  template <typename T>
471
  ReaderFor<T> as() const {
472
    // T must be a struct type.
473 474
    return typename T::Reader(_reader);
  }
475 476
private:
  _::StructReader _reader;
477 478 479

  template <typename, Kind>
  friend struct _::PointerHelpers;
480 481 482 483 484 485 486
};

class AnyStruct::Builder {
public:
  inline Builder(decltype(nullptr)) {}
  inline Builder(_::StructBuilder builder): _builder(builder) {}

487
#if !_MSC_VER  // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves.
Kenton Varda's avatar
Kenton Varda committed
488
  template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromBuilder<T>) == Kind::STRUCT>>
489 490
  inline Builder(T&& value)
      : _builder(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::fwd<T>(value))) {}
491
#endif
492

493
  inline kj::ArrayPtr<byte> getDataSection() {
494 495 496 497 498 499
    return _builder.getDataSectionAsBlob();
  }
  List<AnyPointer>::Builder getPointerSection() {
    return List<AnyPointer>::Builder(_builder.getPointerSectionAsList());
  }

500
  inline Equality equals(AnyStruct::Reader right) {
501 502
    return asReader().equals(right);
  }
503
  inline bool operator==(AnyStruct::Reader right) {
504 505
    return asReader() == right;
  }
506
  inline bool operator!=(AnyStruct::Reader right) {
507 508 509
    return !(*this == right);
  }

510 511
  inline operator Reader() const { return Reader(_builder.asReader()); }
  inline Reader asReader() const { return Reader(_builder.asReader()); }
512 513 514

  template <typename T>
  BuilderFor<T> as() {
515
    // T must be a struct type.
516 517
    return typename T::Builder(_builder);
  }
518 519 520 521 522 523
private:
  _::StructBuilder _builder;
  friend class Orphanage;
  friend class CapBuilderContext;
};

Kenton Varda's avatar
Kenton Varda committed
524
#if !CAPNP_LITE
525 526
class AnyStruct::Pipeline {
public:
527 528 529 530 531 532 533 534 535 536 537 538
  inline Pipeline(decltype(nullptr)): typeless(nullptr) {}
  inline explicit Pipeline(AnyPointer::Pipeline&& typeless)
      : typeless(kj::mv(typeless)) {}

  inline AnyPointer::Pipeline getPointerField(uint16_t pointerIndex) {
    // Return a new Promise representing a sub-object of the result.  `pointerIndex` is the index
    // of the sub-object within the pointer section of the result (the result must be a struct).
    //
    // TODO(perf):  On GCC 4.8 / Clang 3.3, use rvalue qualifiers to avoid the need for copies.
    //   Also make `ops` into a Vector to optimize this.
    return typeless.getPointerField(pointerIndex);
  }
539 540

private:
541
  AnyPointer::Pipeline typeless;
542
};
Kenton Varda's avatar
Kenton Varda committed
543
#endif  // !CAPNP_LITE
544 545 546 547 548 549 550 551 552

class List<AnyStruct, Kind::OTHER>::Reader {
public:
  typedef List<AnyStruct> Reads;

  Reader() = default;
  inline explicit Reader(_::ListReader reader): reader(reader) {}

  inline uint size() const { return reader.size() / ELEMENTS; }
553
  inline AnyStruct::Reader operator[](uint index) const {
554
    KJ_IREQUIRE(index < size());
555
    return AnyStruct::Reader(reader.getStructElement(index * ELEMENTS));
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
  }

  typedef _::IndexingIterator<const Reader, typename AnyStruct::Reader> Iterator;
  inline Iterator begin() const { return Iterator(this, 0); }
  inline Iterator end() const { return Iterator(this, size()); }

private:
  _::ListReader reader;
  template <typename U, Kind K>
  friend struct _::PointerHelpers;
  template <typename U, Kind K>
  friend struct List;
  friend class Orphanage;
  template <typename U, Kind K>
  friend struct ToDynamic_;
};

class List<AnyStruct, Kind::OTHER>::Builder {
public:
  typedef List<AnyStruct> Builds;

  Builder() = delete;
  inline Builder(decltype(nullptr)) {}
  inline explicit Builder(_::ListBuilder builder): builder(builder) {}

  inline operator Reader() { return Reader(builder.asReader()); }
  inline Reader asReader() { return Reader(builder.asReader()); }

  inline uint size() const { return builder.size() / ELEMENTS; }
585
  inline AnyStruct::Builder operator[](uint index) {
586
    KJ_IREQUIRE(index < size());
587
    return AnyStruct::Builder(builder.getStructElement(index * ELEMENTS));
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
  }

  typedef _::IndexingIterator<Builder, typename AnyStruct::Builder> Iterator;
  inline Iterator begin() { return Iterator(this, 0); }
  inline Iterator end() { return Iterator(this, size()); }

private:
  _::ListBuilder builder;
  template <typename U, Kind K>
  friend struct _::PointerHelpers;
  friend class Orphanage;
  template <typename U, Kind K>
  friend struct ToDynamic_;
};

class AnyList::Reader {
public:
  Reader() = default;
  inline Reader(_::ListReader reader): _reader(reader) {}

608
#if !_MSC_VER  // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves.
Kenton Varda's avatar
Kenton Varda committed
609
  template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromReader<T>) == Kind::LIST>>
610 611
  inline Reader(T&& value)
      : _reader(_::PointerHelpers<FromReader<T>>::getInternalReader(kj::fwd<T>(value))) {}
612
#endif
613

614 615
  inline ElementSize getElementSize() { return _reader.getElementSize(); }
  inline uint size() { return _reader.size() / ELEMENTS; }
616

617
  inline kj::ArrayPtr<const byte> getRawBytes() { return _reader.asRawBytes(); }
618

619
  Equality equals(AnyList::Reader right);
620 621
  bool operator==(AnyList::Reader right);
  inline bool operator!=(AnyList::Reader right) {
622 623 624
    return !(*this == right);
  }

625
  template <typename T> ReaderFor<T> as() {
626
    // T must be List<U>.
627 628 629 630
    return ReaderFor<T>(_reader);
  }
private:
  _::ListReader _reader;
631 632 633

  template <typename, Kind>
  friend struct _::PointerHelpers;
634 635 636 637 638 639 640
};

class AnyList::Builder {
public:
  inline Builder(decltype(nullptr)) {}
  inline Builder(_::ListBuilder builder): _builder(builder) {}

641
#if !_MSC_VER  // TODO(msvc): MSVC ICEs on this. Try restoring when compiler improves.
Kenton Varda's avatar
Kenton Varda committed
642
  template <typename T, typename = kj::EnableIf<CAPNP_KIND(FromBuilder<T>) == Kind::LIST>>
643 644
  inline Builder(T&& value)
      : _builder(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::fwd<T>(value))) {}
645
#endif
646

647 648
  inline ElementSize getElementSize() { return _builder.getElementSize(); }
  inline uint size() { return _builder.size() / ELEMENTS; }
649

650
  Equality equals(AnyList::Reader right);
651
  inline bool operator==(AnyList::Reader right) {
652 653
    return asReader() == right;
  }
654
  inline bool operator!=(AnyList::Reader right) {
655 656 657
    return !(*this == right);
  }

658
  template <typename T> BuilderFor<T> as() {
659
    // T must be List<U>.
660 661 662 663 664 665 666 667 668 669
    return BuilderFor<T>(_builder);
  }

  inline operator Reader() const { return Reader(_builder.asReader()); }
  inline Reader asReader() const { return Reader(_builder.asReader()); }

private:
  _::ListBuilder _builder;
};

670 671 672 673 674 675
// =======================================================================================
// Pipeline helpers
//
// These relate to capabilities, but we don't declare them in capability.h because generated code
// for structs needs to know about these, even in files that contain no interfaces.

676 677
#if !CAPNP_LITE

678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
struct PipelineOp {
  // Corresponds to rpc.capnp's PromisedAnswer.Op.

  enum Type {
    NOOP,  // for convenience

    GET_POINTER_FIELD

    // There may be other types in the future...
  };

  Type type;
  union {
    uint16_t pointerIndex;  // for GET_POINTER_FIELD
  };
};

class PipelineHook {
  // Represents a currently-running call, and implements pipelined requests on its result.

public:
699
  virtual kj::Own<PipelineHook> addRef() = 0;
700 701
  // Increment this object's reference count.

702
  virtual kj::Own<ClientHook> getPipelinedCap(kj::ArrayPtr<const PipelineOp> ops) = 0;
703 704
  // Extract a promised Capability from the results.

705
  virtual kj::Own<ClientHook> getPipelinedCap(kj::Array<PipelineOp>&& ops);
706 707 708
  // Version of getPipelinedCap() passing the array by move.  May avoid a copy in some cases.
  // Default implementation just calls the other version.

709 710 711 712 713
  template <typename Pipeline, typename = FromPipeline<Pipeline>>
  static inline kj::Own<PipelineHook> from(Pipeline&& pipeline);

private:
  template <typename T> struct FromImpl;
714 715
};

716 717
#endif  // !CAPNP_LITE

718 719 720
// =======================================================================================
// Inline implementation details

721 722
inline MessageSize AnyPointer::Reader::targetSize() const {
  return reader.targetSize().asPublic();
Kenton Varda's avatar
Kenton Varda committed
723 724
}

725 726
inline PointerType AnyPointer::Reader::getPointerType() const {
  return reader.getPointerType();
727 728 729
}

template <typename T>
730
inline ReaderFor<T> AnyPointer::Reader::getAs() const {
731 732 733
  return _::PointerHelpers<T>::get(reader);
}

734 735
inline MessageSize AnyPointer::Builder::targetSize() const {
  return asReader().targetSize();
Kenton Varda's avatar
Kenton Varda committed
736 737
}

738 739
inline PointerType AnyPointer::Builder::getPointerType() {
  return builder.getPointerType();
740 741
}

742
inline void AnyPointer::Builder::clear() {
743 744 745 746
  return builder.clear();
}

template <typename T>
747
inline BuilderFor<T> AnyPointer::Builder::getAs() {
748 749 750 751
  return _::PointerHelpers<T>::get(builder);
}

template <typename T>
752
inline BuilderFor<T> AnyPointer::Builder::initAs() {
753 754 755 756
  return _::PointerHelpers<T>::init(builder);
}

template <typename T>
757
inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) {
758 759 760
  return _::PointerHelpers<T>::init(builder, elementCount);
}

761 762 763
inline AnyList::Builder AnyPointer::Builder::initAsAnyList(
    ElementSize elementSize, uint elementCount) {
  return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
764 765
}

766 767 768 769 770
inline List<AnyStruct>::Builder AnyPointer::Builder::initAsListOfAnyStruct(
    uint dataWordCount, uint pointerCount, uint elementCount) {
  return List<AnyStruct>::Builder(builder.initStructList(elementCount * ELEMENTS,
      _::StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
}
771 772

inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(uint dataWordCount, uint pointerCount) {
773 774
  return AnyStruct::Builder(builder.initStruct(
      _::StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
775 776
}

777
template <typename T>
778
inline void AnyPointer::Builder::setAs(ReaderFor<T> value) {
779 780 781 782
  return _::PointerHelpers<T>::set(builder, value);
}

template <typename T>
783
inline void AnyPointer::Builder::setAs(
784 785 786 787 788
    std::initializer_list<ReaderFor<ListElementType<T>>> list) {
  return _::PointerHelpers<T>::set(builder, list);
}

template <typename T>
789
inline void AnyPointer::Builder::adopt(Orphan<T>&& orphan) {
790 791 792 793
  _::PointerHelpers<T>::adopt(builder, kj::mv(orphan));
}

template <typename T>
794
inline Orphan<T> AnyPointer::Builder::disownAs() {
795 796 797
  return _::PointerHelpers<T>::disown(builder);
}

798 799
inline Orphan<AnyPointer> AnyPointer::Builder::disown() {
  return Orphan<AnyPointer>(builder.disown());
800 801
}

802 803
template <> struct ReaderFor_ <AnyPointer, Kind::OTHER> { typedef AnyPointer::Reader Type; };
template <> struct BuilderFor_<AnyPointer, Kind::OTHER> { typedef AnyPointer::Builder Type; };
804 805
template <> struct ReaderFor_ <AnyStruct, Kind::OTHER> { typedef AnyStruct::Reader Type; };
template <> struct BuilderFor_<AnyStruct, Kind::OTHER> { typedef AnyStruct::Builder Type; };
806 807

template <>
808
struct Orphanage::GetInnerReader<AnyPointer, Kind::OTHER> {
809
  static inline _::PointerReader apply(const AnyPointer::Reader& t) {
810 811 812 813
    return t.reader;
  }
};

814
template <>
815
struct Orphanage::GetInnerBuilder<AnyPointer, Kind::OTHER> {
816
  static inline _::PointerBuilder apply(AnyPointer::Builder& t) {
817 818 819 820
    return t.builder;
  }
};

821
template <typename T>
822
inline BuilderFor<T> Orphan<AnyPointer>::getAs() {
823 824 825
  return _::OrphanGetImpl<T>::apply(builder);
}
template <typename T>
826
inline ReaderFor<T> Orphan<AnyPointer>::getAsReader() const {
827 828 829
  return _::OrphanGetImpl<T>::applyReader(builder);
}
template <typename T>
830
inline Orphan<T> Orphan<AnyPointer>::releaseAs() {
831 832 833
  return Orphan<T>(kj::mv(builder));
}

834
// Using AnyPointer as the template type should work...
835 836

template <>
837
inline typename AnyPointer::Reader AnyPointer::Reader::getAs<AnyPointer>() const {
838 839 840
  return *this;
}
template <>
841
inline typename AnyPointer::Builder AnyPointer::Builder::getAs<AnyPointer>() {
842 843 844
  return *this;
}
template <>
845
inline typename AnyPointer::Builder AnyPointer::Builder::initAs<AnyPointer>() {
846 847 848 849
  clear();
  return *this;
}
template <>
850
inline void AnyPointer::Builder::setAs<AnyPointer>(AnyPointer::Reader value) {
851 852 853
  return builder.copyFrom(value.reader);
}
template <>
854
inline void AnyPointer::Builder::adopt<AnyPointer>(Orphan<AnyPointer>&& orphan) {
855 856 857
  builder.adopt(kj::mv(orphan.builder));
}
template <>
858 859
inline Orphan<AnyPointer> AnyPointer::Builder::disownAs<AnyPointer>() {
  return Orphan<AnyPointer>(builder.disown());
860 861
}
template <>
862
inline Orphan<AnyPointer> Orphan<AnyPointer>::releaseAs() {
863 864 865
  return kj::mv(*this);
}

866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892
namespace _ {  // private

// Specialize PointerHelpers for AnyPointer.

template <>
struct PointerHelpers<AnyPointer, Kind::OTHER> {
  static inline AnyPointer::Reader get(PointerReader reader,
                                       const void* defaultValue = nullptr,
                                       uint defaultBytes = 0) {
    return AnyPointer::Reader(reader);
  }
  static inline AnyPointer::Builder get(PointerBuilder builder,
                                        const void* defaultValue = nullptr,
                                        uint defaultBytes = 0) {
    return AnyPointer::Builder(builder);
  }
  static inline void set(PointerBuilder builder, AnyPointer::Reader value) {
    AnyPointer::Builder(builder).set(value);
  }
  static inline void adopt(PointerBuilder builder, Orphan<AnyPointer>&& value) {
    builder.adopt(kj::mv(value.builder));
  }
  static inline Orphan<AnyPointer> disown(PointerBuilder builder) {
    return Orphan<AnyPointer>(builder.disown());
  }
};

893 894
template <>
struct PointerHelpers<AnyStruct, Kind::OTHER> {
895
  static inline AnyStruct::Reader get(
896 897 898
      PointerReader reader, const word* defaultValue = nullptr) {
    return AnyStruct::Reader(reader.getStruct(defaultValue));
  }
899
  static inline AnyStruct::Builder get(
900 901 902 903 904 905 906 907
      PointerBuilder builder, const word* defaultValue = nullptr) {
    // TODO(someday): Allow specifying the size somehow?
    return AnyStruct::Builder(builder.getStruct(
        _::StructSize(0 * WORDS, 0 * POINTERS), defaultValue));
  }
  static inline void set(PointerBuilder builder, AnyStruct::Reader value) {
    builder.setStruct(value._reader);
  }
908
  static inline AnyStruct::Builder init(
909
      PointerBuilder builder, uint dataWordCount, uint pointerCount) {
910
    return AnyStruct::Builder(builder.initStruct(
911 912
        StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
  }
913 914 915 916

  // TODO(soon): implement these
  static void adopt(PointerBuilder builder, Orphan<AnyStruct>&& value);
  static Orphan<AnyStruct> disown(PointerBuilder builder);
917 918 919 920
};

template <>
struct PointerHelpers<AnyList, Kind::OTHER> {
921
  static inline AnyList::Reader get(
922 923 924
      PointerReader reader, const word* defaultValue = nullptr) {
    return AnyList::Reader(reader.getListAnySize(defaultValue));
  }
925
  static inline AnyList::Builder get(
926 927 928 929 930 931
      PointerBuilder builder, const word* defaultValue = nullptr) {
    return AnyList::Builder(builder.getListAnySize(defaultValue));
  }
  static inline void set(PointerBuilder builder, AnyList::Reader value) {
    builder.setList(value._reader);
  }
932
  static inline AnyList::Builder init(
933 934 935
      PointerBuilder builder, ElementSize elementSize, uint elementCount) {
    return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
  }
936
  static inline AnyList::Builder init(
937 938 939 940
      PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) {
    return AnyList::Builder(builder.initStructList(
        elementCount * ELEMENTS, StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
  }
941 942 943 944

  // TODO(soon): implement these
  static void adopt(PointerBuilder builder, Orphan<AnyList>&& value);
  static Orphan<AnyList> disown(PointerBuilder builder);
945 946
};

947 948
}  // namespace _ (private)

Kenton Varda's avatar
Kenton Varda committed
949 950
#if !CAPNP_LITE

951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
template <typename T>
struct PipelineHook::FromImpl {
  static inline kj::Own<PipelineHook> apply(typename T::Pipeline&& pipeline) {
    return from(kj::mv(pipeline._typeless));
  }
};

template <>
struct PipelineHook::FromImpl<AnyPointer> {
  static inline kj::Own<PipelineHook> apply(AnyPointer::Pipeline&& pipeline) {
    return kj::mv(pipeline.hook);
  }
};

template <typename Pipeline, typename T>
inline kj::Own<PipelineHook> PipelineHook::from(Pipeline&& pipeline) {
  return FromImpl<T>::apply(kj::fwd<Pipeline>(pipeline));
}

Kenton Varda's avatar
Kenton Varda committed
970 971
#endif  // !CAPNP_LITE

972 973
}  // namespace capnp

974
#endif  // CAPNP_ANY_H_