any.h 32.7 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
    friend class _::PointerHelpers<AnyPointer>;
142 143 144 145
  };

  class Builder {
  public:
146
    typedef AnyPointer Builds;
147

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

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

155 156 157 158 159 160
    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; }
161

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

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

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

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

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

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

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

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

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

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

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

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

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

215
    template <typename T>
216
    inline void setAs(ReaderFor<T> value);
217 218 219 220 221 222 223
    // 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<?>.

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

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
    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>`.

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

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

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

254 255
  private:
    _::PointerBuilder builder;
256
    friend class Orphanage;
257
    friend class CapBuilderContext;
258
    friend class _::PointerHelpers<AnyPointer>;
259
  };
260

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

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

269
    Pipeline noop();
270 271
    // Just make a copy.

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

    inline AnyStruct::Pipeline asAnyStruct();
276

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

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

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

286
  private:
287
    kj::Own<PipelineHook> hook;
288 289
    kj::Array<PipelineOp> ops;

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

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

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

public:
  Orphan() = default;
  KJ_DISALLOW_COPY(Orphan);
  Orphan(Orphan&&) = default;
308 309 310
  inline Orphan(_::OrphanBuilder&& builder)
      : builder(kj::mv(builder)) {}

311 312
  Orphan& operator=(Orphan&&) = default;

313 314 315
  template <typename T>
  inline Orphan(Orphan<T>&& other): builder(kj::mv(other.builder)) {}
  template <typename T>
316
  inline Orphan& operator=(Orphan<T>&& other) { builder = kj::mv(other.builder); return *this; }
317 318
  // Cast from typed orphan.

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

  template <typename T>
324
  inline BuilderFor<T> getAs();
325
  template <typename T>
326
  inline BuilderFor<T> getAs(StructSchema schema);
327
  template <typename T>
328
  inline BuilderFor<T> getAs(ListSchema schema);
329
  template <typename T>
330
  inline typename T::Client getAs(InterfaceSchema schema);
331
  template <typename T>
332
  inline ReaderFor<T> getAsReader() const;
333
  template <typename T>
334 335 336 337 338
  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;
339 340 341 342 343 344 345

  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);
346 347
  template <typename T>
  inline Orphan<T> releaseAs(InterfaceSchema schema);
348 349 350 351 352 353 354 355 356 357 358 359 360
  // 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;

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

364 365 366 367 368
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
369
using AnyTypeFor = typename AnyTypeFor_<CAPNP_KIND(T)>::Type;
370 371 372

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

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

387 388 389 390 391 392
  List() = delete;

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

393
    inline Reader(): reader(ElementSize::POINTER) {}
394 395 396
    inline explicit Reader(_::ListReader reader): reader(reader) {}

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

    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;
422
    inline Builder(decltype(nullptr)): builder(ElementSize::POINTER) {}
423 424 425 426 427 428
    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; }
429
    inline AnyPointer::Builder operator[](uint index) {
430
      KJ_IREQUIRE(index < size());
431
      return AnyPointer::Builder(builder.getPointerElement(index * ELEMENTS));
432 433 434 435 436 437 438 439
    }

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

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

class AnyStruct::Reader {
public:
Kenton Varda's avatar
Kenton Varda committed
450 451
  typedef AnyStruct Reads;

452 453 454
  Reader() = default;
  inline Reader(_::StructReader reader): _reader(reader) {}

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

461
  kj::ArrayPtr<const byte> getDataSection() {
462 463 464 465 466 467
    return _reader.getDataSectionAsBlob();
  }
  List<AnyPointer>::Reader getPointerSection() {
    return List<AnyPointer>::Reader(_reader.getPointerSectionAsList());
  }

468
  Equality equals(AnyStruct::Reader right);
469 470
  bool operator==(AnyStruct::Reader right);
  inline bool operator!=(AnyStruct::Reader right) {
471 472 473
    return !(*this == right);
  }

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

  template <typename, Kind>
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
484
  friend class Orphanage;
485 486 487 488
};

class AnyStruct::Builder {
public:
Kenton Varda's avatar
Kenton Varda committed
489 490
  typedef AnyStruct Builds;

491 492 493
  inline Builder(decltype(nullptr)) {}
  inline Builder(_::StructBuilder builder): _builder(builder) {}

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

500
  inline kj::ArrayPtr<byte> getDataSection() {
501 502 503 504 505 506
    return _builder.getDataSectionAsBlob();
  }
  List<AnyPointer>::Builder getPointerSection() {
    return List<AnyPointer>::Builder(_builder.getPointerSectionAsList());
  }

507
  inline Equality equals(AnyStruct::Reader right) {
508 509
    return asReader().equals(right);
  }
510
  inline bool operator==(AnyStruct::Reader right) {
511 512
    return asReader() == right;
  }
513
  inline bool operator!=(AnyStruct::Reader right) {
514 515 516
    return !(*this == right);
  }

517 518
  inline operator Reader() const { return Reader(_builder.asReader()); }
  inline Reader asReader() const { return Reader(_builder.asReader()); }
519 520 521

  template <typename T>
  BuilderFor<T> as() {
522
    // T must be a struct type.
523 524
    return typename T::Builder(_builder);
  }
525 526 527 528 529 530
private:
  _::StructBuilder _builder;
  friend class Orphanage;
  friend class CapBuilderContext;
};

Kenton Varda's avatar
Kenton Varda committed
531
#if !CAPNP_LITE
532 533
class AnyStruct::Pipeline {
public:
534 535 536 537 538 539 540 541 542 543 544 545
  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);
  }
546 547

private:
548
  AnyPointer::Pipeline typeless;
549
};
Kenton Varda's avatar
Kenton Varda committed
550
#endif  // !CAPNP_LITE
551 552 553 554 555

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

556
  inline Reader(): reader(ElementSize::INLINE_COMPOSITE) {}
557 558 559
  inline explicit Reader(_::ListReader reader): reader(reader) {}

  inline uint size() const { return reader.size() / ELEMENTS; }
560
  inline AnyStruct::Reader operator[](uint index) const {
561
    KJ_IREQUIRE(index < size());
562
    return AnyStruct::Reader(reader.getStructElement(index * ELEMENTS));
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;
585
  inline Builder(decltype(nullptr)): builder(ElementSize::INLINE_COMPOSITE) {}
586 587 588 589 590 591
  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; }
592
  inline AnyStruct::Builder operator[](uint index) {
593
    KJ_IREQUIRE(index < size());
594
    return AnyStruct::Builder(builder.getStructElement(index * ELEMENTS));
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
  }

  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:
Kenton Varda's avatar
Kenton Varda committed
612 613
  typedef AnyList Reads;

614
  inline Reader(): _reader(ElementSize::VOID) {}
615 616
  inline Reader(_::ListReader reader): _reader(reader) {}

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

623 624
  inline ElementSize getElementSize() { return _reader.getElementSize(); }
  inline uint size() { return _reader.size() / ELEMENTS; }
625

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

628
  Equality equals(AnyList::Reader right);
629 630
  bool operator==(AnyList::Reader right);
  inline bool operator!=(AnyList::Reader right) {
631 632 633
    return !(*this == right);
  }

634
  template <typename T> ReaderFor<T> as() {
635
    // T must be List<U>.
636 637 638 639
    return ReaderFor<T>(_reader);
  }
private:
  _::ListReader _reader;
640 641 642

  template <typename, Kind>
  friend struct _::PointerHelpers;
Kenton Varda's avatar
Kenton Varda committed
643
  friend class Orphanage;
644 645 646 647
};

class AnyList::Builder {
public:
Kenton Varda's avatar
Kenton Varda committed
648 649
  typedef AnyList Builds;

650
  inline Builder(decltype(nullptr)): _builder(ElementSize::VOID) {}
651 652
  inline Builder(_::ListBuilder builder): _builder(builder) {}

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

659 660
  inline ElementSize getElementSize() { return _builder.getElementSize(); }
  inline uint size() { return _builder.size() / ELEMENTS; }
661

662
  Equality equals(AnyList::Reader right);
663
  inline bool operator==(AnyList::Reader right) {
664 665
    return asReader() == right;
  }
666
  inline bool operator!=(AnyList::Reader right) {
667 668 669
    return !(*this == right);
  }

670
  template <typename T> BuilderFor<T> as() {
671
    // T must be List<U>.
672 673 674 675 676 677 678 679
    return BuilderFor<T>(_builder);
  }

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

private:
  _::ListBuilder _builder;
Kenton Varda's avatar
Kenton Varda committed
680 681

  friend class Orphanage;
682 683
};

684 685 686 687 688 689
// =======================================================================================
// 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.

690 691
#if !CAPNP_LITE

692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
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:
713
  virtual kj::Own<PipelineHook> addRef() = 0;
714 715
  // Increment this object's reference count.

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

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

723 724 725 726 727
  template <typename Pipeline, typename = FromPipeline<Pipeline>>
  static inline kj::Own<PipelineHook> from(Pipeline&& pipeline);

private:
  template <typename T> struct FromImpl;
728 729
};

730 731
#endif  // !CAPNP_LITE

732 733 734
// =======================================================================================
// Inline implementation details

735 736
inline MessageSize AnyPointer::Reader::targetSize() const {
  return reader.targetSize().asPublic();
Kenton Varda's avatar
Kenton Varda committed
737 738
}

739 740
inline PointerType AnyPointer::Reader::getPointerType() const {
  return reader.getPointerType();
741 742 743
}

template <typename T>
744
inline ReaderFor<T> AnyPointer::Reader::getAs() const {
745 746 747
  return _::PointerHelpers<T>::get(reader);
}

748 749
inline MessageSize AnyPointer::Builder::targetSize() const {
  return asReader().targetSize();
Kenton Varda's avatar
Kenton Varda committed
750 751
}

752 753
inline PointerType AnyPointer::Builder::getPointerType() {
  return builder.getPointerType();
754 755
}

756
inline void AnyPointer::Builder::clear() {
757 758 759 760
  return builder.clear();
}

template <typename T>
761
inline BuilderFor<T> AnyPointer::Builder::getAs() {
762 763 764 765
  return _::PointerHelpers<T>::get(builder);
}

template <typename T>
766
inline BuilderFor<T> AnyPointer::Builder::initAs() {
767 768 769 770
  return _::PointerHelpers<T>::init(builder);
}

template <typename T>
771
inline BuilderFor<T> AnyPointer::Builder::initAs(uint elementCount) {
772 773 774
  return _::PointerHelpers<T>::init(builder, elementCount);
}

775 776 777
inline AnyList::Builder AnyPointer::Builder::initAsAnyList(
    ElementSize elementSize, uint elementCount) {
  return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
778 779
}

780 781 782 783 784
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)));
}
785 786

inline AnyStruct::Builder AnyPointer::Builder::initAsAnyStruct(uint dataWordCount, uint pointerCount) {
787 788
  return AnyStruct::Builder(builder.initStruct(
      _::StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
789 790
}

791
template <typename T>
792
inline void AnyPointer::Builder::setAs(ReaderFor<T> value) {
793 794 795 796
  return _::PointerHelpers<T>::set(builder, value);
}

template <typename T>
797
inline void AnyPointer::Builder::setAs(
798 799 800 801 802
    std::initializer_list<ReaderFor<ListElementType<T>>> list) {
  return _::PointerHelpers<T>::set(builder, list);
}

template <typename T>
803
inline void AnyPointer::Builder::adopt(Orphan<T>&& orphan) {
804 805 806 807
  _::PointerHelpers<T>::adopt(builder, kj::mv(orphan));
}

template <typename T>
808
inline Orphan<T> AnyPointer::Builder::disownAs() {
809 810 811
  return _::PointerHelpers<T>::disown(builder);
}

812 813
inline Orphan<AnyPointer> AnyPointer::Builder::disown() {
  return Orphan<AnyPointer>(builder.disown());
814 815
}

816 817
template <> struct ReaderFor_ <AnyPointer, Kind::OTHER> { typedef AnyPointer::Reader Type; };
template <> struct BuilderFor_<AnyPointer, Kind::OTHER> { typedef AnyPointer::Builder Type; };
818 819
template <> struct ReaderFor_ <AnyStruct, Kind::OTHER> { typedef AnyStruct::Reader Type; };
template <> struct BuilderFor_<AnyStruct, Kind::OTHER> { typedef AnyStruct::Builder Type; };
820 821

template <>
822
struct Orphanage::GetInnerReader<AnyPointer, Kind::OTHER> {
823
  static inline _::PointerReader apply(const AnyPointer::Reader& t) {
824 825 826 827
    return t.reader;
  }
};

828
template <>
829
struct Orphanage::GetInnerBuilder<AnyPointer, Kind::OTHER> {
830
  static inline _::PointerBuilder apply(AnyPointer::Builder& t) {
831 832 833 834
    return t.builder;
  }
};

Kenton Varda's avatar
Kenton Varda committed
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862
template <>
struct Orphanage::GetInnerReader<AnyStruct, Kind::OTHER> {
  static inline _::StructReader apply(const AnyStruct::Reader& t) {
    return t._reader;
  }
};

template <>
struct Orphanage::GetInnerBuilder<AnyStruct, Kind::OTHER> {
  static inline _::StructBuilder apply(AnyStruct::Builder& t) {
    return t._builder;
  }
};

template <>
struct Orphanage::GetInnerReader<AnyList, Kind::OTHER> {
  static inline _::ListReader apply(const AnyList::Reader& t) {
    return t._reader;
  }
};

template <>
struct Orphanage::GetInnerBuilder<AnyList, Kind::OTHER> {
  static inline _::ListBuilder apply(AnyList::Builder& t) {
    return t._builder;
  }
};

863
template <typename T>
864
inline BuilderFor<T> Orphan<AnyPointer>::getAs() {
865 866 867
  return _::OrphanGetImpl<T>::apply(builder);
}
template <typename T>
868
inline ReaderFor<T> Orphan<AnyPointer>::getAsReader() const {
869 870 871
  return _::OrphanGetImpl<T>::applyReader(builder);
}
template <typename T>
872
inline Orphan<T> Orphan<AnyPointer>::releaseAs() {
873 874 875
  return Orphan<T>(kj::mv(builder));
}

876
// Using AnyPointer as the template type should work...
877 878

template <>
879
inline typename AnyPointer::Reader AnyPointer::Reader::getAs<AnyPointer>() const {
880 881 882
  return *this;
}
template <>
883
inline typename AnyPointer::Builder AnyPointer::Builder::getAs<AnyPointer>() {
884 885 886
  return *this;
}
template <>
887
inline typename AnyPointer::Builder AnyPointer::Builder::initAs<AnyPointer>() {
888 889 890 891
  clear();
  return *this;
}
template <>
892
inline void AnyPointer::Builder::setAs<AnyPointer>(AnyPointer::Reader value) {
893 894 895
  return builder.copyFrom(value.reader);
}
template <>
896
inline void AnyPointer::Builder::adopt<AnyPointer>(Orphan<AnyPointer>&& orphan) {
897 898 899
  builder.adopt(kj::mv(orphan.builder));
}
template <>
900 901
inline Orphan<AnyPointer> AnyPointer::Builder::disownAs<AnyPointer>() {
  return Orphan<AnyPointer>(builder.disown());
902 903
}
template <>
904
inline Orphan<AnyPointer> Orphan<AnyPointer>::releaseAs() {
905 906 907
  return kj::mv(*this);
}

908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
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());
  }
933 934 935 936 937 938
  static inline _::PointerReader getInternalReader(const AnyPointer::Reader& reader) {
    return reader.reader;
  }
  static inline _::PointerBuilder getInternalBuilder(AnyPointer::Builder&& builder) {
    return builder.builder;
  }
939 940
};

941 942
template <>
struct PointerHelpers<AnyStruct, Kind::OTHER> {
943
  static inline AnyStruct::Reader get(
944 945 946
      PointerReader reader, const word* defaultValue = nullptr) {
    return AnyStruct::Reader(reader.getStruct(defaultValue));
  }
947
  static inline AnyStruct::Builder get(
948 949 950 951 952 953 954 955
      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);
  }
956
  static inline AnyStruct::Builder init(
957
      PointerBuilder builder, uint dataWordCount, uint pointerCount) {
958
    return AnyStruct::Builder(builder.initStruct(
959 960
        StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
  }
961 962 963 964

  // TODO(soon): implement these
  static void adopt(PointerBuilder builder, Orphan<AnyStruct>&& value);
  static Orphan<AnyStruct> disown(PointerBuilder builder);
965 966 967 968
};

template <>
struct PointerHelpers<AnyList, Kind::OTHER> {
969
  static inline AnyList::Reader get(
970 971 972
      PointerReader reader, const word* defaultValue = nullptr) {
    return AnyList::Reader(reader.getListAnySize(defaultValue));
  }
973
  static inline AnyList::Builder get(
974 975 976 977 978 979
      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);
  }
980
  static inline AnyList::Builder init(
981 982 983
      PointerBuilder builder, ElementSize elementSize, uint elementCount) {
    return AnyList::Builder(builder.initList(elementSize, elementCount * ELEMENTS));
  }
984
  static inline AnyList::Builder init(
985 986 987 988
      PointerBuilder builder, uint dataWordCount, uint pointerCount, uint elementCount) {
    return AnyList::Builder(builder.initStructList(
        elementCount * ELEMENTS, StructSize(dataWordCount * WORDS, pointerCount * POINTERS)));
  }
989 990 991 992

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

Kenton Varda's avatar
Kenton Varda committed
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
template <>
struct OrphanGetImpl<AnyStruct, Kind::OTHER> {
  static inline AnyStruct::Builder apply(_::OrphanBuilder& builder) {
    return AnyStruct::Builder(builder.asStruct(_::StructSize(0 * WORDS, 0 * POINTERS)));
  }
  static inline AnyStruct::Reader applyReader(const _::OrphanBuilder& builder) {
    return AnyStruct::Reader(builder.asStructReader(_::StructSize(0 * WORDS, 0 * POINTERS)));
  }
  static inline void truncateListOf(_::OrphanBuilder& builder, ElementCount size) {
    builder.truncate(size, _::StructSize(0 * WORDS, 0 * POINTERS));
  }
};

1008 1009
}  // namespace _ (private)

Kenton Varda's avatar
Kenton Varda committed
1010 1011
#if !CAPNP_LITE

1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
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
1031 1032
#endif  // !CAPNP_LITE

1033 1034
}  // namespace capnp

1035
#endif  // CAPNP_ANY_H_