capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

dynamic.h (61638B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 // This file defines classes that can be used to manipulate messages based on schemas that are not
     23 // known until runtime.  This is also useful for writing generic code that uses schemas to handle
     24 // arbitrary types in a generic way.
     25 //
     26 // Each of the classes defined here has a to() template method which converts an instance back to a
     27 // native type.  This method will throw an exception if the requested type does not match the
     28 // schema.  To convert native types to dynamic, use DynamicFactory.
     29 //
     30 // As always, underlying data is validated lazily, so you have to actually traverse the whole
     31 // message if you want to validate all content.
     32 
     33 #pragma once
     34 
     35 #include "schema.h"
     36 #include "layout.h"
     37 #include "message.h"
     38 #include "any.h"
     39 #include "capability.h"
     40 #include <kj/windows-sanity.h>  // work-around macro conflict with `VOID`
     41 
     42 CAPNP_BEGIN_HEADER
     43 
     44 namespace capnp {
     45 
     46 class MessageReader;
     47 class MessageBuilder;
     48 
     49 struct DynamicValue {
     50   DynamicValue() = delete;
     51 
     52   enum Type {
     53     UNKNOWN,
     54     // Means that the value has unknown type and content because it comes from a newer version of
     55     // the schema, or from a newer version of Cap'n Proto that has new features that this version
     56     // doesn't understand.
     57 
     58     VOID,
     59     BOOL,
     60     INT,
     61     UINT,
     62     FLOAT,
     63     TEXT,
     64     DATA,
     65     LIST,
     66     ENUM,
     67     STRUCT,
     68     CAPABILITY,
     69     ANY_POINTER
     70   };
     71 
     72   class Reader;
     73   class Builder;
     74   class Pipeline;
     75 };
     76 class DynamicEnum;
     77 struct DynamicStruct {
     78   DynamicStruct() = delete;
     79   class Reader;
     80   class Builder;
     81   class Pipeline;
     82 };
     83 struct DynamicList {
     84   DynamicList() = delete;
     85   class Reader;
     86   class Builder;
     87 };
     88 struct DynamicCapability {
     89   DynamicCapability() = delete;
     90   class Client;
     91   class Server;
     92 };
     93 template <> class Orphan<DynamicValue>;
     94 
     95 template <Kind k> struct DynamicTypeFor_;
     96 template <> struct DynamicTypeFor_<Kind::ENUM> { typedef DynamicEnum Type; };
     97 template <> struct DynamicTypeFor_<Kind::STRUCT> { typedef DynamicStruct Type; };
     98 template <> struct DynamicTypeFor_<Kind::LIST> { typedef DynamicList Type; };
     99 template <> struct DynamicTypeFor_<Kind::INTERFACE> { typedef DynamicCapability Type; };
    100 
    101 template <typename T>
    102 using DynamicTypeFor = typename DynamicTypeFor_<kind<T>()>::Type;
    103 
    104 template <typename T>
    105 ReaderFor<DynamicTypeFor<FromReader<T>>> toDynamic(T&& value);
    106 template <typename T>
    107 BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value);
    108 template <typename T>
    109 DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value);
    110 template <typename T>
    111 typename DynamicTypeFor<FromServer<T>>::Client toDynamic(kj::Own<T>&& value);
    112 
    113 namespace _ {  // private
    114 
    115 template <> struct Kind_<DynamicValue     > { static constexpr Kind kind = Kind::OTHER; };
    116 template <> struct Kind_<DynamicEnum      > { static constexpr Kind kind = Kind::OTHER; };
    117 template <> struct Kind_<DynamicStruct    > { static constexpr Kind kind = Kind::OTHER; };
    118 template <> struct Kind_<DynamicList      > { static constexpr Kind kind = Kind::OTHER; };
    119 template <> struct Kind_<DynamicCapability> { static constexpr Kind kind = Kind::OTHER; };
    120 
    121 }  // namespace _ (private)
    122 
    123 template <> inline constexpr Style style<DynamicValue     >() { return Style::POINTER;    }
    124 template <> inline constexpr Style style<DynamicEnum      >() { return Style::PRIMITIVE;  }
    125 template <> inline constexpr Style style<DynamicStruct    >() { return Style::STRUCT;     }
    126 template <> inline constexpr Style style<DynamicList      >() { return Style::POINTER;    }
    127 template <> inline constexpr Style style<DynamicCapability>() { return Style::CAPABILITY; }
    128 
    129 // -------------------------------------------------------------------
    130 
    131 class DynamicEnum {
    132 public:
    133   DynamicEnum() = default;
    134   inline DynamicEnum(EnumSchema::Enumerant enumerant)
    135       : schema(enumerant.getContainingEnum()), value(enumerant.getOrdinal()) {}
    136   inline DynamicEnum(EnumSchema schema, uint16_t value)
    137       : schema(schema), value(value) {}
    138 
    139   template <typename T, typename = kj::EnableIf<kind<T>() == Kind::ENUM>>
    140   inline DynamicEnum(T&& value): DynamicEnum(toDynamic(value)) {}
    141 
    142   template <typename T>
    143   inline T as() const { return static_cast<T>(asImpl(typeId<T>())); }
    144   // Cast to a native enum type.
    145 
    146   inline EnumSchema getSchema() const { return schema; }
    147 
    148   kj::Maybe<EnumSchema::Enumerant> getEnumerant() const;
    149   // Get which enumerant this enum value represents.  Returns nullptr if the numeric value does not
    150   // correspond to any enumerant in the schema -- this can happen if the data was built using a
    151   // newer schema that has more values defined.
    152 
    153   inline uint16_t getRaw() const { return value; }
    154   // Returns the raw underlying enum value.
    155 
    156 private:
    157   EnumSchema schema;
    158   uint16_t value;
    159 
    160   uint16_t asImpl(uint64_t requestedTypeId) const;
    161 
    162   friend struct DynamicStruct;
    163   friend struct DynamicList;
    164   friend struct DynamicValue;
    165   template <typename T>
    166   friend DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value);
    167 };
    168 
    169 // -------------------------------------------------------------------
    170 
    171 enum class HasMode: uint8_t {
    172   // Specifies the meaning of "has(field)".
    173 
    174   NON_NULL,
    175   // "has(field)" only returns false if the field is a pointer and the pointer is null. This is the
    176   // default behavior.
    177 
    178   NON_DEFAULT
    179   // "has(field)" returns false if the field is set to its default value. This differs from
    180   // NON_NULL only in the handling of primitive values.
    181   //
    182   // "Equal to default value" is technically defined as the field value being encoded as all-zero
    183   // on the wire (since primitive values are XORed by their defined default value when encoded).
    184 };
    185 
    186 class DynamicStruct::Reader {
    187 public:
    188   typedef DynamicStruct Reads;
    189 
    190   Reader() = default;
    191 
    192   template <typename T, typename = kj::EnableIf<kind<FromReader<T>>() == Kind::STRUCT>>
    193   inline Reader(T&& value): Reader(toDynamic(value)) {}
    194 
    195   inline operator AnyStruct::Reader() const { return AnyStruct::Reader(reader); }
    196 
    197   inline MessageSize totalSize() const { return reader.totalSize().asPublic(); }
    198 
    199   template <typename T>
    200   typename T::Reader as() const;
    201   // Convert the dynamic struct to its compiled-in type.
    202 
    203   inline StructSchema getSchema() const { return schema; }
    204 
    205   DynamicValue::Reader get(StructSchema::Field field) const;
    206   // Read the given field value.
    207 
    208   bool has(StructSchema::Field field, HasMode mode = HasMode::NON_NULL) const;
    209   // Tests whether the given field is "present". If the field is a union member and is not the
    210   // active member, this always returns false. Otherwise, the field's value is interpreted
    211   // according to `mode`.
    212 
    213   kj::Maybe<StructSchema::Field> which() const;
    214   // If the struct contains an (unnamed) union, and the currently-active field within that union
    215   // is known, this returns that field.  Otherwise, it returns null.  In other words, this returns
    216   // null if there is no union present _or_ if the union's discriminant is set to an unrecognized
    217   // value.  This could happen in particular when receiving a message from a sender who has a
    218   // newer version of the protocol and is using a field of the union that you don't know about yet.
    219 
    220   DynamicValue::Reader get(kj::StringPtr name) const;
    221   bool has(kj::StringPtr name, HasMode mode = HasMode::NON_NULL) const;
    222   // Shortcuts to access fields by name.  These throw exceptions if no such field exists.
    223 
    224 private:
    225   StructSchema schema;
    226   _::StructReader reader;
    227 
    228   inline Reader(StructSchema schema, _::StructReader reader)
    229       : schema(schema), reader(reader) {}
    230   Reader(StructSchema schema, const _::OrphanBuilder& orphan);
    231 
    232   bool isSetInUnion(StructSchema::Field field) const;
    233   void verifySetInUnion(StructSchema::Field field) const;
    234   static DynamicValue::Reader getImpl(_::StructReader reader, StructSchema::Field field);
    235 
    236   template <typename T, Kind K>
    237   friend struct _::PointerHelpers;
    238   friend class DynamicStruct::Builder;
    239   friend struct DynamicList;
    240   friend class MessageReader;
    241   friend class MessageBuilder;
    242   template <typename T, ::capnp::Kind k>
    243   friend struct ::capnp::ToDynamic_;
    244   friend kj::StringTree _::structString(
    245       _::StructReader reader, const _::RawBrandedSchema& schema);
    246   friend class Orphanage;
    247   friend class Orphan<DynamicStruct>;
    248   friend class Orphan<DynamicValue>;
    249   friend class Orphan<AnyPointer>;
    250   friend class AnyStruct::Reader;
    251 };
    252 
    253 class DynamicStruct::Builder {
    254 public:
    255   typedef DynamicStruct Builds;
    256 
    257   Builder() = default;
    258   inline Builder(decltype(nullptr)) {}
    259 
    260   template <typename T, typename = kj::EnableIf<kind<FromBuilder<T>>() == Kind::STRUCT>>
    261   inline Builder(T&& value): Builder(toDynamic(value)) {}
    262 
    263   inline operator AnyStruct::Builder() { return AnyStruct::Builder(builder); }
    264 
    265   inline MessageSize totalSize() const { return asReader().totalSize(); }
    266 
    267   template <typename T>
    268   typename T::Builder as();
    269   // Cast to a particular struct type.
    270 
    271   inline StructSchema getSchema() const { return schema; }
    272 
    273   DynamicValue::Builder get(StructSchema::Field field);
    274   // Read the given field value.
    275 
    276   inline bool has(StructSchema::Field field, HasMode mode = HasMode::NON_NULL)
    277       { return asReader().has(field, mode); }
    278   // Tests whether the given field is "present". If the field is a union member and is not the
    279   // active member, this always returns false. Otherwise, the field's value is interpreted
    280   // according to `mode`.
    281 
    282   kj::Maybe<StructSchema::Field> which();
    283   // If the struct contains an (unnamed) union, and the currently-active field within that union
    284   // is known, this returns that field.  Otherwise, it returns null.  In other words, this returns
    285   // null if there is no union present _or_ if the union's discriminant is set to an unrecognized
    286   // value.  This could happen in particular when receiving a message from a sender who has a
    287   // newer version of the protocol and is using a field of the union that you don't know about yet.
    288 
    289   void set(StructSchema::Field field, const DynamicValue::Reader& value);
    290   // Set the given field value.
    291 
    292   DynamicValue::Builder init(StructSchema::Field field);
    293   DynamicValue::Builder init(StructSchema::Field field, uint size);
    294   // Init a struct, list, or blob field.
    295 
    296   void adopt(StructSchema::Field field, Orphan<DynamicValue>&& orphan);
    297   Orphan<DynamicValue> disown(StructSchema::Field field);
    298   // Adopt/disown.  This works even for non-pointer fields: adopt() becomes equivalent to set()
    299   // and disown() becomes like get() followed by clear().
    300 
    301   void clear(StructSchema::Field field);
    302   // Clear a field, setting it to its default value.  For pointer fields, this actually makes the
    303   // field null.
    304 
    305   DynamicValue::Builder get(kj::StringPtr name);
    306   bool has(kj::StringPtr name, HasMode mode = HasMode::NON_NULL);
    307   void set(kj::StringPtr name, const DynamicValue::Reader& value);
    308   void set(kj::StringPtr name, std::initializer_list<DynamicValue::Reader> value);
    309   DynamicValue::Builder init(kj::StringPtr name);
    310   DynamicValue::Builder init(kj::StringPtr name, uint size);
    311   void adopt(kj::StringPtr name, Orphan<DynamicValue>&& orphan);
    312   Orphan<DynamicValue> disown(kj::StringPtr name);
    313   void clear(kj::StringPtr name);
    314   // Shortcuts to access fields by name.  These throw exceptions if no such field exists.
    315 
    316   Reader asReader() const;
    317 
    318 private:
    319   StructSchema schema;
    320   _::StructBuilder builder;
    321 
    322   inline Builder(StructSchema schema, _::StructBuilder builder)
    323       : schema(schema), builder(builder) {}
    324   Builder(StructSchema schema, _::OrphanBuilder& orphan);
    325 
    326   bool isSetInUnion(StructSchema::Field field);
    327   void verifySetInUnion(StructSchema::Field field);
    328   void setInUnion(StructSchema::Field field);
    329 
    330   template <typename T, Kind k>
    331   friend struct _::PointerHelpers;
    332   friend struct DynamicList;
    333   friend class MessageReader;
    334   friend class MessageBuilder;
    335   template <typename T, ::capnp::Kind k>
    336   friend struct ::capnp::ToDynamic_;
    337   friend class Orphanage;
    338   friend class Orphan<DynamicStruct>;
    339   friend class Orphan<DynamicValue>;
    340   friend class Orphan<AnyPointer>;
    341   friend class AnyStruct::Builder;
    342 };
    343 
    344 class DynamicStruct::Pipeline {
    345 public:
    346   typedef DynamicStruct Pipelines;
    347 
    348   inline Pipeline(decltype(nullptr)): typeless(nullptr) {}
    349 
    350   template <typename T>
    351   typename T::Pipeline releaseAs();
    352   // Convert the dynamic pipeline to its compiled-in type.
    353 
    354   inline StructSchema getSchema() { return schema; }
    355 
    356   DynamicValue::Pipeline get(StructSchema::Field field);
    357   // Read the given field value.
    358 
    359   DynamicValue::Pipeline get(kj::StringPtr name);
    360   // Get by string name.
    361 
    362 private:
    363   StructSchema schema;
    364   AnyPointer::Pipeline typeless;
    365 
    366   inline explicit Pipeline(StructSchema schema, AnyPointer::Pipeline&& typeless)
    367       : schema(schema), typeless(kj::mv(typeless)) {}
    368 
    369   friend class Request<DynamicStruct, DynamicStruct>;
    370 };
    371 
    372 // -------------------------------------------------------------------
    373 
    374 class DynamicList::Reader {
    375 public:
    376   typedef DynamicList Reads;
    377 
    378   inline Reader(): reader(ElementSize::VOID) {}
    379 
    380   template <typename T, typename = kj::EnableIf<kind<FromReader<T>>() == Kind::LIST>>
    381   inline Reader(T&& value): Reader(toDynamic(value)) {}
    382 
    383   inline operator AnyList::Reader() const { return AnyList::Reader(reader); }
    384 
    385   template <typename T>
    386   typename T::Reader as() const;
    387   // Try to convert to any List<T>, Data, or Text.  Throws an exception if the underlying data
    388   // can't possibly represent the requested type.
    389 
    390   inline ListSchema getSchema() const { return schema; }
    391 
    392   inline uint size() const { return unbound(reader.size() / ELEMENTS); }
    393   DynamicValue::Reader operator[](uint index) const;
    394 
    395   typedef _::IndexingIterator<const Reader, DynamicValue::Reader> Iterator;
    396   inline Iterator begin() const { return Iterator(this, 0); }
    397   inline Iterator end() const { return Iterator(this, size()); }
    398 
    399 private:
    400   ListSchema schema;
    401   _::ListReader reader;
    402 
    403   Reader(ListSchema schema, _::ListReader reader): schema(schema), reader(reader) {}
    404   Reader(ListSchema schema, const _::OrphanBuilder& orphan);
    405 
    406   template <typename T, Kind k>
    407   friend struct _::PointerHelpers;
    408   friend struct DynamicStruct;
    409   friend class DynamicList::Builder;
    410   template <typename T, ::capnp::Kind k>
    411   friend struct ::capnp::ToDynamic_;
    412   friend class Orphanage;
    413   friend class Orphan<DynamicList>;
    414   friend class Orphan<DynamicValue>;
    415   friend class Orphan<AnyPointer>;
    416 };
    417 
    418 class DynamicList::Builder {
    419 public:
    420   typedef DynamicList Builds;
    421 
    422   inline Builder(): builder(ElementSize::VOID) {}
    423   inline Builder(decltype(nullptr)): builder(ElementSize::VOID) {}
    424 
    425   template <typename T, typename = kj::EnableIf<kind<FromBuilder<T>>() == Kind::LIST>>
    426   inline Builder(T&& value): Builder(toDynamic(value)) {}
    427 
    428   inline operator AnyList::Builder() { return AnyList::Builder(builder); }
    429 
    430   template <typename T>
    431   typename T::Builder as();
    432   // Try to convert to any List<T>, Data, or Text.  Throws an exception if the underlying data
    433   // can't possibly represent the requested type.
    434 
    435   inline ListSchema getSchema() const { return schema; }
    436 
    437   inline uint size() const { return unbound(builder.size() / ELEMENTS); }
    438   DynamicValue::Builder operator[](uint index);
    439   void set(uint index, const DynamicValue::Reader& value);
    440   DynamicValue::Builder init(uint index, uint size);
    441   void adopt(uint index, Orphan<DynamicValue>&& orphan);
    442   Orphan<DynamicValue> disown(uint index);
    443 
    444   typedef _::IndexingIterator<Builder, DynamicStruct::Builder> Iterator;
    445   inline Iterator begin() { return Iterator(this, 0); }
    446   inline Iterator end() { return Iterator(this, size()); }
    447 
    448   void copyFrom(std::initializer_list<DynamicValue::Reader> value);
    449 
    450   Reader asReader() const;
    451 
    452 private:
    453   ListSchema schema;
    454   _::ListBuilder builder;
    455 
    456   Builder(ListSchema schema, _::ListBuilder builder): schema(schema), builder(builder) {}
    457   Builder(ListSchema schema, _::OrphanBuilder& orphan);
    458 
    459   template <typename T, Kind k>
    460   friend struct _::PointerHelpers;
    461   friend struct DynamicStruct;
    462   template <typename T, ::capnp::Kind k>
    463   friend struct ::capnp::ToDynamic_;
    464   friend class Orphanage;
    465   template <typename T, Kind k>
    466   friend struct _::OrphanGetImpl;
    467   friend class Orphan<DynamicList>;
    468   friend class Orphan<DynamicValue>;
    469   friend class Orphan<AnyPointer>;
    470 };
    471 
    472 // -------------------------------------------------------------------
    473 
    474 class DynamicCapability::Client: public Capability::Client {
    475 public:
    476   typedef DynamicCapability Calls;
    477   typedef DynamicCapability Reads;
    478 
    479   Client() = default;
    480 
    481   template <typename T, typename = kj::EnableIf<kind<FromClient<T>>() == Kind::INTERFACE>>
    482   inline Client(T&& client);
    483 
    484   template <typename T, typename = kj::EnableIf<kj::canConvert<T*, DynamicCapability::Server*>()>>
    485   inline Client(kj::Own<T>&& server);
    486 
    487   template <typename T, typename = kj::EnableIf<kind<T>() == Kind::INTERFACE>>
    488   typename T::Client as();
    489   template <typename T, typename = kj::EnableIf<kind<T>() == Kind::INTERFACE>>
    490   typename T::Client releaseAs();
    491   // Convert to any client type.
    492 
    493   Client upcast(InterfaceSchema requestedSchema);
    494   // Upcast to a superclass.  Throws an exception if `schema` is not a superclass.
    495 
    496   inline InterfaceSchema getSchema() { return schema; }
    497 
    498   Request<DynamicStruct, DynamicStruct> newRequest(
    499       InterfaceSchema::Method method, kj::Maybe<MessageSize> sizeHint = nullptr);
    500   Request<DynamicStruct, DynamicStruct> newRequest(
    501       kj::StringPtr methodName, kj::Maybe<MessageSize> sizeHint = nullptr);
    502 
    503 private:
    504   InterfaceSchema schema;
    505 
    506   Client(InterfaceSchema schema, kj::Own<ClientHook>&& hook)
    507       : Capability::Client(kj::mv(hook)), schema(schema) {}
    508 
    509   template <typename T>
    510   inline Client(InterfaceSchema schema, kj::Own<T>&& server);
    511 
    512   friend struct Capability;
    513   friend struct DynamicStruct;
    514   friend struct DynamicList;
    515   friend struct DynamicValue;
    516   friend class Orphan<DynamicCapability>;
    517   friend class Orphan<DynamicValue>;
    518   friend class Orphan<AnyPointer>;
    519   template <typename T, Kind k>
    520   friend struct _::PointerHelpers;
    521 };
    522 
    523 class DynamicCapability::Server: public Capability::Server {
    524 public:
    525   typedef DynamicCapability Serves;
    526 
    527   Server(InterfaceSchema schema): schema(schema) {}
    528 
    529   virtual kj::Promise<void> call(InterfaceSchema::Method method,
    530                                  CallContext<DynamicStruct, DynamicStruct> context) = 0;
    531 
    532   DispatchCallResult dispatchCall(uint64_t interfaceId, uint16_t methodId,
    533                                   CallContext<AnyPointer, AnyPointer> context) override final;
    534 
    535   inline InterfaceSchema getSchema() const { return schema; }
    536 
    537 private:
    538   InterfaceSchema schema;
    539 };
    540 
    541 template <>
    542 class Request<DynamicStruct, DynamicStruct>: public DynamicStruct::Builder {
    543   // Specialization of `Request<T, U>` for DynamicStruct.
    544 
    545 public:
    546   inline Request(DynamicStruct::Builder builder, kj::Own<RequestHook>&& hook,
    547                  StructSchema resultSchema)
    548       : DynamicStruct::Builder(builder), hook(kj::mv(hook)), resultSchema(resultSchema) {}
    549 
    550   RemotePromise<DynamicStruct> send();
    551   // Send the call and return a promise for the results.
    552 
    553   kj::Promise<void> sendStreaming();
    554   // Use when the caller is aware that the response type is StreamResult and wants to invoke
    555   // streaming behavior. It is an error to call this if the response type is not StreamResult.
    556 
    557 private:
    558   kj::Own<RequestHook> hook;
    559   StructSchema resultSchema;
    560 
    561   friend class Capability::Client;
    562   friend struct DynamicCapability;
    563   template <typename, typename>
    564   friend class CallContext;
    565   friend class RequestHook;
    566 };
    567 
    568 template <>
    569 class CallContext<DynamicStruct, DynamicStruct>: public kj::DisallowConstCopy {
    570   // Wrapper around CallContextHook with a specific return type.
    571   //
    572   // Methods of this class may only be called from within the server's event loop, not from other
    573   // threads.
    574 
    575 public:
    576   explicit CallContext(CallContextHook& hook, StructSchema paramType, StructSchema resultType);
    577 
    578   DynamicStruct::Reader getParams();
    579   void releaseParams();
    580   DynamicStruct::Builder getResults(kj::Maybe<MessageSize> sizeHint = nullptr);
    581   DynamicStruct::Builder initResults(kj::Maybe<MessageSize> sizeHint = nullptr);
    582   void setResults(DynamicStruct::Reader value);
    583   void adoptResults(Orphan<DynamicStruct>&& value);
    584   Orphanage getResultsOrphanage(kj::Maybe<MessageSize> sizeHint = nullptr);
    585   template <typename SubParams>
    586   kj::Promise<void> tailCall(Request<SubParams, DynamicStruct>&& tailRequest);
    587   void allowCancellation();
    588 
    589   StructSchema getParamsType() const { return paramType; }
    590   StructSchema getResultsType() const { return resultType; }
    591 
    592 private:
    593   CallContextHook* hook;
    594   StructSchema paramType;
    595   StructSchema resultType;
    596 
    597   friend class DynamicCapability::Server;
    598 };
    599 
    600 // -------------------------------------------------------------------
    601 
    602 // Make sure ReaderFor<T> and BuilderFor<T> work for DynamicEnum, DynamicStruct, and
    603 // DynamicList, so that we can define DynamicValue::as().
    604 
    605 template <> struct ReaderFor_ <DynamicEnum, Kind::OTHER> { typedef DynamicEnum Type; };
    606 template <> struct BuilderFor_<DynamicEnum, Kind::OTHER> { typedef DynamicEnum Type; };
    607 template <> struct ReaderFor_ <DynamicStruct, Kind::OTHER> { typedef DynamicStruct::Reader Type; };
    608 template <> struct BuilderFor_<DynamicStruct, Kind::OTHER> { typedef DynamicStruct::Builder Type; };
    609 template <> struct ReaderFor_ <DynamicList, Kind::OTHER> { typedef DynamicList::Reader Type; };
    610 template <> struct BuilderFor_<DynamicList, Kind::OTHER> { typedef DynamicList::Builder Type; };
    611 template <> struct ReaderFor_ <DynamicCapability, Kind::OTHER> { typedef DynamicCapability::Client Type; };
    612 template <> struct BuilderFor_<DynamicCapability, Kind::OTHER> { typedef DynamicCapability::Client Type; };
    613 template <> struct PipelineFor_<DynamicCapability, Kind::OTHER> { typedef DynamicCapability::Client Type; };
    614 
    615 class DynamicValue::Reader {
    616 public:
    617   typedef DynamicValue Reads;
    618 
    619   inline Reader(decltype(nullptr) n = nullptr);  // UNKNOWN
    620   inline Reader(Void value);
    621   inline Reader(bool value);
    622   inline Reader(char value);
    623   inline Reader(signed char value);
    624   inline Reader(short value);
    625   inline Reader(int value);
    626   inline Reader(long value);
    627   inline Reader(long long value);
    628   inline Reader(unsigned char value);
    629   inline Reader(unsigned short value);
    630   inline Reader(unsigned int value);
    631   inline Reader(unsigned long value);
    632   inline Reader(unsigned long long value);
    633   inline Reader(float value);
    634   inline Reader(double value);
    635   inline Reader(const char* value);  // Text
    636   inline Reader(const Text::Reader& value);
    637   inline Reader(const Data::Reader& value);
    638   inline Reader(const DynamicList::Reader& value);
    639   inline Reader(DynamicEnum value);
    640   inline Reader(const DynamicStruct::Reader& value);
    641   inline Reader(const AnyPointer::Reader& value);
    642   inline Reader(DynamicCapability::Client& value);
    643   inline Reader(DynamicCapability::Client&& value);
    644   template <typename T, typename = kj::EnableIf<kj::canConvert<T*, DynamicCapability::Server*>()>>
    645   inline Reader(kj::Own<T>&& value);
    646   Reader(ConstSchema constant);
    647 
    648   template <typename T, typename = decltype(toDynamic(kj::instance<T>()))>
    649   inline Reader(T&& value): Reader(toDynamic(kj::mv(value))) {}
    650 
    651   Reader(const Reader& other);
    652   Reader(Reader&& other) noexcept;
    653   ~Reader() noexcept(false);
    654   Reader& operator=(const Reader& other);
    655   Reader& operator=(Reader&& other);
    656   // Unfortunately, we cannot use the implicit definitions of these since DynamicCapability is not
    657   // trivially copyable.
    658 
    659   template <typename T>
    660   inline ReaderFor<T> as() const { return AsImpl<T>::apply(*this); }
    661   // Use to interpret the value as some Cap'n Proto type.  Allowed types are:
    662   // - Void, bool, [u]int{8,16,32,64}_t, float, double, any enum:  Returns the raw value.
    663   // - Text, Data, AnyPointer, any struct type:  Returns the corresponding Reader.
    664   // - List<T> for any T listed above:  Returns List<T>::Reader.
    665   // - DynamicEnum:  Returns the corresponding type.
    666   // - DynamicStruct, DynamicList:  Returns the corresponding Reader.
    667   // - Any capability type, including DynamicCapability:  Returns the corresponding Client.
    668   // - DynamicValue:  Returns an identical Reader. Useful to avoid special-casing in generic code.
    669   //   (TODO(perf):  On GCC 4.8 / Clang 3.3, provide rvalue-qualified version that avoids
    670   //   refcounting.)
    671   //
    672   // DynamicValue allows various implicit conversions, mostly just to make the interface friendlier.
    673   // - Any integer can be converted to any other integer type so long as the actual value is within
    674   //   the new type's range.
    675   // - Floating-point types can be converted to integers as long as no information would be lost
    676   //   in the conversion.
    677   // - Integers can be converted to floating points.  This may lose information, but won't throw.
    678   // - Float32/Float64 can be converted between each other.  Converting Float64 -> Float32 may lose
    679   //   information, but won't throw.
    680   // - Text can be converted to an enum, if the Text matches one of the enumerant names (but not
    681   //   vice-versa).
    682   // - Capabilities can be upcast (cast to a supertype), but not downcast.
    683   //
    684   // Any other conversion attempt will throw an exception.
    685 
    686   inline Type getType() const { return type; }
    687   // Get the type of this value.
    688 
    689 private:
    690   Type type;
    691 
    692   union {
    693     Void voidValue;
    694     bool boolValue;
    695     int64_t intValue;
    696     uint64_t uintValue;
    697     double floatValue;
    698     Text::Reader textValue;
    699     Data::Reader dataValue;
    700     DynamicList::Reader listValue;
    701     DynamicEnum enumValue;
    702     DynamicStruct::Reader structValue;
    703     AnyPointer::Reader anyPointerValue;
    704 
    705     mutable DynamicCapability::Client capabilityValue;
    706     // Declared mutable because `Client`s normally cannot be const.
    707 
    708     // Warning:  Copy/move constructors assume all these types are trivially copyable except
    709     //   Capability.
    710   };
    711 
    712   template <typename T, Kind kind = kind<T>()> struct AsImpl;
    713   // Implementation backing the as() method.  Needs to be a struct to allow partial
    714   // specialization.  Has a method apply() which does the work.
    715 
    716   friend class Orphanage;  // to speed up newOrphanCopy(DynamicValue::Reader)
    717 };
    718 
    719 class DynamicValue::Builder {
    720 public:
    721   typedef DynamicValue Builds;
    722 
    723   inline Builder(decltype(nullptr) n = nullptr);  // UNKNOWN
    724   inline Builder(Void value);
    725   inline Builder(bool value);
    726   inline Builder(char value);
    727   inline Builder(signed char value);
    728   inline Builder(short value);
    729   inline Builder(int value);
    730   inline Builder(long value);
    731   inline Builder(long long value);
    732   inline Builder(unsigned char value);
    733   inline Builder(unsigned short value);
    734   inline Builder(unsigned int value);
    735   inline Builder(unsigned long value);
    736   inline Builder(unsigned long long value);
    737   inline Builder(float value);
    738   inline Builder(double value);
    739   inline Builder(Text::Builder value);
    740   inline Builder(Data::Builder value);
    741   inline Builder(DynamicList::Builder value);
    742   inline Builder(DynamicEnum value);
    743   inline Builder(DynamicStruct::Builder value);
    744   inline Builder(AnyPointer::Builder value);
    745   inline Builder(DynamicCapability::Client& value);
    746   inline Builder(DynamicCapability::Client&& value);
    747 
    748   template <typename T, typename = decltype(toDynamic(kj::instance<T>()))>
    749   inline Builder(T value): Builder(toDynamic(value)) {}
    750 
    751   Builder(Builder& other);
    752   Builder(Builder&& other) noexcept;
    753   ~Builder() noexcept(false);
    754   Builder& operator=(Builder& other);
    755   Builder& operator=(Builder&& other);
    756   // Unfortunately, we cannot use the implicit definitions of these since DynamicCapability is not
    757   // trivially copyable.
    758 
    759   template <typename T>
    760   inline BuilderFor<T> as() { return AsImpl<T>::apply(*this); }
    761   // See DynamicValue::Reader::as().
    762 
    763   inline Type getType() { return type; }
    764   // Get the type of this value.
    765 
    766   Reader asReader() const;
    767 
    768 private:
    769   Type type;
    770 
    771   union {
    772     Void voidValue;
    773     bool boolValue;
    774     int64_t intValue;
    775     uint64_t uintValue;
    776     double floatValue;
    777     Text::Builder textValue;
    778     Data::Builder dataValue;
    779     DynamicList::Builder listValue;
    780     DynamicEnum enumValue;
    781     DynamicStruct::Builder structValue;
    782     AnyPointer::Builder anyPointerValue;
    783 
    784     mutable DynamicCapability::Client capabilityValue;
    785     // Declared mutable because `Client`s normally cannot be const.
    786   };
    787 
    788   template <typename T, Kind kind = kind<T>()> struct AsImpl;
    789   // Implementation backing the as() method.  Needs to be a struct to allow partial
    790   // specialization.  Has a method apply() which does the work.
    791 
    792   friend class Orphan<DynamicValue>;
    793 };
    794 
    795 class DynamicValue::Pipeline {
    796 public:
    797   typedef DynamicValue Pipelines;
    798 
    799   inline Pipeline(decltype(nullptr) n = nullptr);
    800   inline Pipeline(DynamicStruct::Pipeline&& value);
    801   inline Pipeline(DynamicCapability::Client&& value);
    802 
    803   Pipeline(Pipeline&& other) noexcept;
    804   Pipeline& operator=(Pipeline&& other);
    805   ~Pipeline() noexcept(false);
    806 
    807   template <typename T>
    808   inline PipelineFor<T> releaseAs() { return AsImpl<T>::apply(*this); }
    809 
    810   inline Type getType() { return type; }
    811   // Get the type of this value.
    812 
    813 private:
    814   Type type;
    815   union {
    816     DynamicStruct::Pipeline structValue;
    817     DynamicCapability::Client capabilityValue;
    818   };
    819 
    820   template <typename T, Kind kind = kind<T>()> struct AsImpl;
    821   // Implementation backing the releaseAs() method.  Needs to be a struct to allow partial
    822   // specialization.  Has a method apply() which does the work.
    823 };
    824 
    825 kj::StringTree KJ_STRINGIFY(const DynamicValue::Reader& value);
    826 kj::StringTree KJ_STRINGIFY(const DynamicValue::Builder& value);
    827 kj::StringTree KJ_STRINGIFY(DynamicEnum value);
    828 kj::StringTree KJ_STRINGIFY(const DynamicStruct::Reader& value);
    829 kj::StringTree KJ_STRINGIFY(const DynamicStruct::Builder& value);
    830 kj::StringTree KJ_STRINGIFY(const DynamicList::Reader& value);
    831 kj::StringTree KJ_STRINGIFY(const DynamicList::Builder& value);
    832 
    833 // -------------------------------------------------------------------
    834 // Orphan <-> Dynamic glue
    835 
    836 template <>
    837 class Orphan<DynamicStruct> {
    838 public:
    839   Orphan() = default;
    840   KJ_DISALLOW_COPY(Orphan);
    841   Orphan(Orphan&&) = default;
    842   Orphan& operator=(Orphan&&) = default;
    843 
    844   template <typename T, typename = kj::EnableIf<kind<T>() == Kind::STRUCT>>
    845   inline Orphan(Orphan<T>&& other): schema(Schema::from<T>()), builder(kj::mv(other.builder)) {}
    846 
    847   DynamicStruct::Builder get();
    848   DynamicStruct::Reader getReader() const;
    849 
    850   template <typename T>
    851   Orphan<T> releaseAs();
    852   // Like DynamicStruct::Builder::as(), but coerces the Orphan type.  Since Orphans are move-only,
    853   // the original Orphan<DynamicStruct> is no longer valid after this call; ownership is
    854   // transferred to the returned Orphan<T>.
    855 
    856   inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
    857   inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
    858 
    859 private:
    860   StructSchema schema;
    861   _::OrphanBuilder builder;
    862 
    863   inline Orphan(StructSchema schema, _::OrphanBuilder&& builder)
    864       : schema(schema), builder(kj::mv(builder)) {}
    865 
    866   template <typename, Kind>
    867   friend struct _::PointerHelpers;
    868   friend struct DynamicList;
    869   friend class Orphanage;
    870   friend class Orphan<DynamicValue>;
    871   friend class Orphan<AnyPointer>;
    872   friend class MessageBuilder;
    873 };
    874 
    875 template <>
    876 class Orphan<DynamicList> {
    877 public:
    878   Orphan() = default;
    879   KJ_DISALLOW_COPY(Orphan);
    880   Orphan(Orphan&&) = default;
    881   Orphan& operator=(Orphan&&) = default;
    882 
    883   template <typename T, typename = kj::EnableIf<kind<T>() == Kind::LIST>>
    884   inline Orphan(Orphan<T>&& other): schema(Schema::from<T>()), builder(kj::mv(other.builder)) {}
    885 
    886   DynamicList::Builder get();
    887   DynamicList::Reader getReader() const;
    888 
    889   template <typename T>
    890   Orphan<T> releaseAs();
    891   // Like DynamicList::Builder::as(), but coerces the Orphan type.  Since Orphans are move-only,
    892   // the original Orphan<DynamicStruct> is no longer valid after this call; ownership is
    893   // transferred to the returned Orphan<T>.
    894 
    895   // TODO(someday): Support truncate().
    896 
    897   inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
    898   inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
    899 
    900 private:
    901   ListSchema schema;
    902   _::OrphanBuilder builder;
    903 
    904   inline Orphan(ListSchema schema, _::OrphanBuilder&& builder)
    905       : schema(schema), builder(kj::mv(builder)) {}
    906 
    907   template <typename, Kind>
    908   friend struct _::PointerHelpers;
    909   friend struct DynamicList;
    910   friend class Orphanage;
    911   friend class Orphan<DynamicValue>;
    912   friend class Orphan<AnyPointer>;
    913 };
    914 
    915 template <>
    916 class Orphan<DynamicCapability> {
    917 public:
    918   Orphan() = default;
    919   KJ_DISALLOW_COPY(Orphan);
    920   Orphan(Orphan&&) = default;
    921   Orphan& operator=(Orphan&&) = default;
    922 
    923   template <typename T, typename = kj::EnableIf<kind<T>() == Kind::INTERFACE>>
    924   inline Orphan(Orphan<T>&& other): schema(Schema::from<T>()), builder(kj::mv(other.builder)) {}
    925 
    926   DynamicCapability::Client get();
    927   DynamicCapability::Client getReader() const;
    928 
    929   template <typename T>
    930   Orphan<T> releaseAs();
    931   // Like DynamicCapability::Client::as(), but coerces the Orphan type.  Since Orphans are move-only,
    932   // the original Orphan<DynamicCapability> is no longer valid after this call; ownership is
    933   // transferred to the returned Orphan<T>.
    934 
    935   inline bool operator==(decltype(nullptr)) const { return builder == nullptr; }
    936   inline bool operator!=(decltype(nullptr)) const { return builder != nullptr; }
    937 
    938 private:
    939   InterfaceSchema schema;
    940   _::OrphanBuilder builder;
    941 
    942   inline Orphan(InterfaceSchema schema, _::OrphanBuilder&& builder)
    943       : schema(schema), builder(kj::mv(builder)) {}
    944 
    945   template <typename, Kind>
    946   friend struct _::PointerHelpers;
    947   friend struct DynamicList;
    948   friend class Orphanage;
    949   friend class Orphan<DynamicValue>;
    950   friend class Orphan<AnyPointer>;
    951 };
    952 
    953 template <>
    954 class Orphan<DynamicValue> {
    955 public:
    956   inline Orphan(decltype(nullptr) n = nullptr): type(DynamicValue::UNKNOWN) {}
    957   inline Orphan(Void value);
    958   inline Orphan(bool value);
    959   inline Orphan(char value);
    960   inline Orphan(signed char value);
    961   inline Orphan(short value);
    962   inline Orphan(int value);
    963   inline Orphan(long value);
    964   inline Orphan(long long value);
    965   inline Orphan(unsigned char value);
    966   inline Orphan(unsigned short value);
    967   inline Orphan(unsigned int value);
    968   inline Orphan(unsigned long value);
    969   inline Orphan(unsigned long long value);
    970   inline Orphan(float value);
    971   inline Orphan(double value);
    972   inline Orphan(DynamicEnum value);
    973   Orphan(Orphan&&) = default;
    974   template <typename T>
    975   Orphan(Orphan<T>&&);
    976   Orphan(Orphan<AnyPointer>&&);
    977   Orphan(void*) = delete;  // So Orphan(bool) doesn't accept pointers.
    978   KJ_DISALLOW_COPY(Orphan);
    979 
    980   Orphan& operator=(Orphan&&) = default;
    981 
    982   inline DynamicValue::Type getType() { return type; }
    983 
    984   DynamicValue::Builder get();
    985   DynamicValue::Reader getReader() const;
    986 
    987   template <typename T>
    988   Orphan<T> releaseAs();
    989   // Like DynamicValue::Builder::as(), but coerces the Orphan type.  Since Orphans are move-only,
    990   // the original Orphan<DynamicStruct> is no longer valid after this call; ownership is
    991   // transferred to the returned Orphan<T>.
    992 
    993 private:
    994   DynamicValue::Type type;
    995   union {
    996     Void voidValue;
    997     bool boolValue;
    998     int64_t intValue;
    999     uint64_t uintValue;
   1000     double floatValue;
   1001     DynamicEnum enumValue;
   1002     StructSchema structSchema;
   1003     ListSchema listSchema;
   1004     InterfaceSchema interfaceSchema;
   1005   };
   1006 
   1007   _::OrphanBuilder builder;
   1008   // Only used if `type` is a pointer type.
   1009 
   1010   Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder);
   1011   Orphan(DynamicValue::Type type, _::OrphanBuilder&& builder)
   1012       : type(type), builder(kj::mv(builder)) {}
   1013   Orphan(StructSchema structSchema, _::OrphanBuilder&& builder)
   1014       : type(DynamicValue::STRUCT), structSchema(structSchema), builder(kj::mv(builder)) {}
   1015   Orphan(ListSchema listSchema, _::OrphanBuilder&& builder)
   1016       : type(DynamicValue::LIST), listSchema(listSchema), builder(kj::mv(builder)) {}
   1017 
   1018   template <typename, Kind>
   1019   friend struct _::PointerHelpers;
   1020   friend struct DynamicStruct;
   1021   friend struct DynamicList;
   1022   friend struct AnyPointer;
   1023   friend class Orphanage;
   1024 };
   1025 
   1026 template <typename T>
   1027 inline Orphan<DynamicValue>::Orphan(Orphan<T>&& other)
   1028     : Orphan(other.get(), kj::mv(other.builder)) {}
   1029 
   1030 inline Orphan<DynamicValue>::Orphan(Orphan<AnyPointer>&& other)
   1031     : type(DynamicValue::ANY_POINTER), builder(kj::mv(other.builder)) {}
   1032 
   1033 template <typename T>
   1034 Orphan<T> Orphan<DynamicStruct>::releaseAs() {
   1035   get().as<T>();  // type check
   1036   return Orphan<T>(kj::mv(builder));
   1037 }
   1038 
   1039 template <typename T>
   1040 Orphan<T> Orphan<DynamicList>::releaseAs() {
   1041   get().as<T>();  // type check
   1042   return Orphan<T>(kj::mv(builder));
   1043 }
   1044 
   1045 template <typename T>
   1046 Orphan<T> Orphan<DynamicCapability>::releaseAs() {
   1047   get().as<T>();  // type check
   1048   return Orphan<T>(kj::mv(builder));
   1049 }
   1050 
   1051 template <typename T>
   1052 Orphan<T> Orphan<DynamicValue>::releaseAs() {
   1053   get().as<T>();  // type check
   1054   type = DynamicValue::UNKNOWN;
   1055   return Orphan<T>(kj::mv(builder));
   1056 }
   1057 
   1058 template <>
   1059 Orphan<AnyPointer> Orphan<DynamicValue>::releaseAs<AnyPointer>();
   1060 template <>
   1061 Orphan<DynamicStruct> Orphan<DynamicValue>::releaseAs<DynamicStruct>();
   1062 template <>
   1063 Orphan<DynamicList> Orphan<DynamicValue>::releaseAs<DynamicList>();
   1064 template <>
   1065 Orphan<DynamicCapability> Orphan<DynamicValue>::releaseAs<DynamicCapability>();
   1066 
   1067 template <>
   1068 struct Orphanage::GetInnerBuilder<DynamicStruct, Kind::OTHER> {
   1069   static inline _::StructBuilder apply(DynamicStruct::Builder& t) {
   1070     return t.builder;
   1071   }
   1072 };
   1073 
   1074 template <>
   1075 struct Orphanage::GetInnerBuilder<DynamicList, Kind::OTHER> {
   1076   static inline _::ListBuilder apply(DynamicList::Builder& t) {
   1077     return t.builder;
   1078   }
   1079 };
   1080 
   1081 template <>
   1082 inline Orphan<DynamicStruct> Orphanage::newOrphanCopy<DynamicStruct::Reader>(
   1083     DynamicStruct::Reader copyFrom) const {
   1084   return Orphan<DynamicStruct>(
   1085       copyFrom.getSchema(), _::OrphanBuilder::copy(arena, capTable, copyFrom.reader));
   1086 }
   1087 
   1088 template <>
   1089 inline Orphan<DynamicList> Orphanage::newOrphanCopy<DynamicList::Reader>(
   1090     DynamicList::Reader copyFrom) const {
   1091   return Orphan<DynamicList>(copyFrom.getSchema(),
   1092       _::OrphanBuilder::copy(arena, capTable, copyFrom.reader));
   1093 }
   1094 
   1095 template <>
   1096 inline Orphan<DynamicCapability> Orphanage::newOrphanCopy<DynamicCapability::Client>(
   1097     DynamicCapability::Client copyFrom) const {
   1098   return Orphan<DynamicCapability>(
   1099       copyFrom.getSchema(), _::OrphanBuilder::copy(arena, capTable, copyFrom.hook->addRef()));
   1100 }
   1101 
   1102 template <>
   1103 Orphan<DynamicValue> Orphanage::newOrphanCopy<DynamicValue::Reader>(
   1104     DynamicValue::Reader copyFrom) const;
   1105 
   1106 namespace _ {  // private
   1107 
   1108 template <>
   1109 struct PointerHelpers<DynamicStruct, Kind::OTHER> {
   1110   // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for
   1111   // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we
   1112   // don't want people to accidentally be able to provide their own default value.
   1113   static DynamicStruct::Reader getDynamic(PointerReader reader, StructSchema schema);
   1114   static DynamicStruct::Builder getDynamic(PointerBuilder builder, StructSchema schema);
   1115   static void set(PointerBuilder builder, const DynamicStruct::Reader& value);
   1116   static DynamicStruct::Builder init(PointerBuilder builder, StructSchema schema);
   1117   static inline void adopt(PointerBuilder builder, Orphan<DynamicStruct>&& value) {
   1118     builder.adopt(kj::mv(value.builder));
   1119   }
   1120   static inline Orphan<DynamicStruct> disown(PointerBuilder builder, StructSchema schema) {
   1121     return Orphan<DynamicStruct>(schema, builder.disown());
   1122   }
   1123 };
   1124 
   1125 template <>
   1126 struct PointerHelpers<DynamicList, Kind::OTHER> {
   1127   // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for
   1128   // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we
   1129   // don't want people to accidentally be able to provide their own default value.
   1130   static DynamicList::Reader getDynamic(PointerReader reader, ListSchema schema);
   1131   static DynamicList::Builder getDynamic(PointerBuilder builder, ListSchema schema);
   1132   static void set(PointerBuilder builder, const DynamicList::Reader& value);
   1133   static DynamicList::Builder init(PointerBuilder builder, ListSchema schema, uint size);
   1134   static inline void adopt(PointerBuilder builder, Orphan<DynamicList>&& value) {
   1135     builder.adopt(kj::mv(value.builder));
   1136   }
   1137   static inline Orphan<DynamicList> disown(PointerBuilder builder, ListSchema schema) {
   1138     return Orphan<DynamicList>(schema, builder.disown());
   1139   }
   1140 };
   1141 
   1142 template <>
   1143 struct PointerHelpers<DynamicCapability, Kind::OTHER> {
   1144   // getDynamic() is used when an AnyPointer's get() accessor is passed arguments, because for
   1145   // non-dynamic types PointerHelpers::get() takes a default value as the third argument, and we
   1146   // don't want people to accidentally be able to provide their own default value.
   1147   static DynamicCapability::Client getDynamic(PointerReader reader, InterfaceSchema schema);
   1148   static DynamicCapability::Client getDynamic(PointerBuilder builder, InterfaceSchema schema);
   1149   static void set(PointerBuilder builder, DynamicCapability::Client& value);
   1150   static void set(PointerBuilder builder, DynamicCapability::Client&& value);
   1151   static inline void adopt(PointerBuilder builder, Orphan<DynamicCapability>&& value) {
   1152     builder.adopt(kj::mv(value.builder));
   1153   }
   1154   static inline Orphan<DynamicCapability> disown(PointerBuilder builder, InterfaceSchema schema) {
   1155     return Orphan<DynamicCapability>(schema, builder.disown());
   1156   }
   1157 };
   1158 
   1159 }  // namespace _ (private)
   1160 
   1161 template <typename T>
   1162 inline ReaderFor<T> AnyPointer::Reader::getAs(StructSchema schema) const {
   1163   return _::PointerHelpers<T>::getDynamic(reader, schema);
   1164 }
   1165 template <typename T>
   1166 inline ReaderFor<T> AnyPointer::Reader::getAs(ListSchema schema) const {
   1167   return _::PointerHelpers<T>::getDynamic(reader, schema);
   1168 }
   1169 template <typename T>
   1170 inline ReaderFor<T> AnyPointer::Reader::getAs(InterfaceSchema schema) const {
   1171   return _::PointerHelpers<T>::getDynamic(reader, schema);
   1172 }
   1173 template <typename T>
   1174 inline BuilderFor<T> AnyPointer::Builder::getAs(StructSchema schema) {
   1175   return _::PointerHelpers<T>::getDynamic(builder, schema);
   1176 }
   1177 template <typename T>
   1178 inline BuilderFor<T> AnyPointer::Builder::getAs(ListSchema schema) {
   1179   return _::PointerHelpers<T>::getDynamic(builder, schema);
   1180 }
   1181 template <typename T>
   1182 inline BuilderFor<T> AnyPointer::Builder::getAs(InterfaceSchema schema) {
   1183   return _::PointerHelpers<T>::getDynamic(builder, schema);
   1184 }
   1185 template <typename T>
   1186 inline BuilderFor<T> AnyPointer::Builder::initAs(StructSchema schema) {
   1187   return _::PointerHelpers<T>::init(builder, schema);
   1188 }
   1189 template <typename T>
   1190 inline BuilderFor<T> AnyPointer::Builder::initAs(ListSchema schema, uint elementCount) {
   1191   return _::PointerHelpers<T>::init(builder, schema, elementCount);
   1192 }
   1193 template <>
   1194 inline void AnyPointer::Builder::setAs<DynamicStruct>(DynamicStruct::Reader value) {
   1195   return _::PointerHelpers<DynamicStruct>::set(builder, value);
   1196 }
   1197 template <>
   1198 inline void AnyPointer::Builder::setAs<DynamicList>(DynamicList::Reader value) {
   1199   return _::PointerHelpers<DynamicList>::set(builder, value);
   1200 }
   1201 template <>
   1202 inline void AnyPointer::Builder::setAs<DynamicCapability>(DynamicCapability::Client value) {
   1203   return _::PointerHelpers<DynamicCapability>::set(builder, kj::mv(value));
   1204 }
   1205 template <>
   1206 void AnyPointer::Builder::adopt<DynamicValue>(Orphan<DynamicValue>&& orphan);
   1207 template <typename T>
   1208 inline Orphan<T> AnyPointer::Builder::disownAs(StructSchema schema) {
   1209   return _::PointerHelpers<T>::disown(builder, schema);
   1210 }
   1211 template <typename T>
   1212 inline Orphan<T> AnyPointer::Builder::disownAs(ListSchema schema) {
   1213   return _::PointerHelpers<T>::disown(builder, schema);
   1214 }
   1215 template <typename T>
   1216 inline Orphan<T> AnyPointer::Builder::disownAs(InterfaceSchema schema) {
   1217   return _::PointerHelpers<T>::disown(builder, schema);
   1218 }
   1219 
   1220 // We have to declare the methods below inline because Clang and GCC disagree about how to mangle
   1221 // their symbol names.
   1222 template <>
   1223 inline DynamicStruct::Builder Orphan<AnyPointer>::getAs<DynamicStruct>(StructSchema schema) {
   1224   return DynamicStruct::Builder(schema, builder);
   1225 }
   1226 template <>
   1227 inline DynamicStruct::Reader Orphan<AnyPointer>::getAsReader<DynamicStruct>(
   1228     StructSchema schema) const {
   1229   return DynamicStruct::Reader(schema, builder);
   1230 }
   1231 template <>
   1232 inline Orphan<DynamicStruct> Orphan<AnyPointer>::releaseAs<DynamicStruct>(StructSchema schema) {
   1233   return Orphan<DynamicStruct>(schema, kj::mv(builder));
   1234 }
   1235 template <>
   1236 inline DynamicList::Builder Orphan<AnyPointer>::getAs<DynamicList>(ListSchema schema) {
   1237   return DynamicList::Builder(schema, builder);
   1238 }
   1239 template <>
   1240 inline DynamicList::Reader Orphan<AnyPointer>::getAsReader<DynamicList>(ListSchema schema) const {
   1241   return DynamicList::Reader(schema, builder);
   1242 }
   1243 template <>
   1244 inline Orphan<DynamicList> Orphan<AnyPointer>::releaseAs<DynamicList>(ListSchema schema) {
   1245   return Orphan<DynamicList>(schema, kj::mv(builder));
   1246 }
   1247 template <>
   1248 inline DynamicCapability::Client Orphan<AnyPointer>::getAs<DynamicCapability>(
   1249     InterfaceSchema schema) {
   1250   return DynamicCapability::Client(schema, builder.asCapability());
   1251 }
   1252 template <>
   1253 inline DynamicCapability::Client Orphan<AnyPointer>::getAsReader<DynamicCapability>(
   1254     InterfaceSchema schema) const {
   1255   return DynamicCapability::Client(schema, builder.asCapability());
   1256 }
   1257 template <>
   1258 inline Orphan<DynamicCapability> Orphan<AnyPointer>::releaseAs<DynamicCapability>(
   1259     InterfaceSchema schema) {
   1260   return Orphan<DynamicCapability>(schema, kj::mv(builder));
   1261 }
   1262 
   1263 // =======================================================================================
   1264 // Inline implementation details.
   1265 
   1266 template <typename T>
   1267 struct ToDynamic_<T, Kind::STRUCT> {
   1268   static inline DynamicStruct::Reader apply(const typename T::Reader& value) {
   1269     return DynamicStruct::Reader(Schema::from<T>(), value._reader);
   1270   }
   1271   static inline DynamicStruct::Builder apply(typename T::Builder& value) {
   1272     return DynamicStruct::Builder(Schema::from<T>(), value._builder);
   1273   }
   1274 };
   1275 
   1276 template <typename T>
   1277 struct ToDynamic_<T, Kind::LIST> {
   1278   static inline DynamicList::Reader apply(const typename T::Reader& value) {
   1279     return DynamicList::Reader(Schema::from<T>(), value.reader);
   1280   }
   1281   static inline DynamicList::Builder apply(typename T::Builder& value) {
   1282     return DynamicList::Builder(Schema::from<T>(), value.builder);
   1283   }
   1284 };
   1285 
   1286 template <typename T>
   1287 struct ToDynamic_<T, Kind::INTERFACE> {
   1288   static inline DynamicCapability::Client apply(typename T::Client value) {
   1289     return DynamicCapability::Client(kj::mv(value));
   1290   }
   1291   static inline DynamicCapability::Client apply(typename T::Client&& value) {
   1292     return DynamicCapability::Client(kj::mv(value));
   1293   }
   1294 };
   1295 
   1296 template <typename T>
   1297 ReaderFor<DynamicTypeFor<FromReader<T>>> toDynamic(T&& value) {
   1298   return ToDynamic_<FromReader<T>>::apply(value);
   1299 }
   1300 template <typename T>
   1301 BuilderFor<DynamicTypeFor<FromBuilder<T>>> toDynamic(T&& value) {
   1302   return ToDynamic_<FromBuilder<T>>::apply(value);
   1303 }
   1304 template <typename T>
   1305 DynamicTypeFor<TypeIfEnum<T>> toDynamic(T&& value) {
   1306   return DynamicEnum(Schema::from<kj::Decay<T>>(), static_cast<uint16_t>(value));
   1307 }
   1308 template <typename T>
   1309 typename DynamicTypeFor<FromServer<T>>::Client toDynamic(kj::Own<T>&& value) {
   1310   return typename FromServer<T>::Client(kj::mv(value));
   1311 }
   1312 
   1313 inline DynamicValue::Reader::Reader(std::nullptr_t n): type(UNKNOWN) {}
   1314 inline DynamicValue::Builder::Builder(std::nullptr_t n): type(UNKNOWN) {}
   1315 
   1316 #define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
   1317 inline DynamicValue::Reader::Reader(cppType value) \
   1318     : type(typeTag), fieldName##Value(value) {} \
   1319 inline DynamicValue::Builder::Builder(cppType value) \
   1320     : type(typeTag), fieldName##Value(value) {} \
   1321 inline Orphan<DynamicValue>::Orphan(cppType value) \
   1322     : type(DynamicValue::typeTag), fieldName##Value(value) {}
   1323 
   1324 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Void, VOID, void);
   1325 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(bool, BOOL, bool);
   1326 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(char, INT, int);
   1327 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(signed char, INT, int);
   1328 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(short, INT, int);
   1329 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(int, INT, int);
   1330 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long, INT, int);
   1331 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(long long, INT, int);
   1332 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned char, UINT, uint);
   1333 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned short, UINT, uint);
   1334 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned int, UINT, uint);
   1335 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long, UINT, uint);
   1336 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(unsigned long long, UINT, uint);
   1337 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(float, FLOAT, float);
   1338 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(double, FLOAT, float);
   1339 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicEnum, ENUM, enum);
   1340 #undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
   1341 
   1342 #define CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(cppType, typeTag, fieldName) \
   1343 inline DynamicValue::Reader::Reader(const cppType::Reader& value) \
   1344     : type(typeTag), fieldName##Value(value) {} \
   1345 inline DynamicValue::Builder::Builder(cppType::Builder value) \
   1346     : type(typeTag), fieldName##Value(value) {}
   1347 
   1348 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Text, TEXT, text);
   1349 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(Data, DATA, data);
   1350 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicList, LIST, list);
   1351 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(DynamicStruct, STRUCT, struct);
   1352 CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR(AnyPointer, ANY_POINTER, anyPointer);
   1353 
   1354 #undef CAPNP_DECLARE_DYNAMIC_VALUE_CONSTRUCTOR
   1355 
   1356 inline DynamicValue::Reader::Reader(DynamicCapability::Client& value)
   1357     : type(CAPABILITY), capabilityValue(value) {}
   1358 inline DynamicValue::Reader::Reader(DynamicCapability::Client&& value)
   1359     : type(CAPABILITY), capabilityValue(kj::mv(value)) {}
   1360 template <typename T, typename>
   1361 inline DynamicValue::Reader::Reader(kj::Own<T>&& value)
   1362     : type(CAPABILITY), capabilityValue(kj::mv(value)) {}
   1363 inline DynamicValue::Builder::Builder(DynamicCapability::Client& value)
   1364     : type(CAPABILITY), capabilityValue(value) {}
   1365 inline DynamicValue::Builder::Builder(DynamicCapability::Client&& value)
   1366     : type(CAPABILITY), capabilityValue(kj::mv(value)) {}
   1367 
   1368 inline DynamicValue::Reader::Reader(const char* value): Reader(Text::Reader(value)) {}
   1369 
   1370 #define CAPNP_DECLARE_TYPE(discrim, typeName) \
   1371 template <> \
   1372 struct DynamicValue::Reader::AsImpl<typeName> { \
   1373   static ReaderFor<typeName> apply(const Reader& reader); \
   1374 }; \
   1375 template <> \
   1376 struct DynamicValue::Builder::AsImpl<typeName> { \
   1377   static BuilderFor<typeName> apply(Builder& builder); \
   1378 };
   1379 
   1380 //CAPNP_DECLARE_TYPE(VOID, Void)
   1381 CAPNP_DECLARE_TYPE(BOOL, bool)
   1382 CAPNP_DECLARE_TYPE(INT8, int8_t)
   1383 CAPNP_DECLARE_TYPE(INT16, int16_t)
   1384 CAPNP_DECLARE_TYPE(INT32, int32_t)
   1385 CAPNP_DECLARE_TYPE(INT64, int64_t)
   1386 CAPNP_DECLARE_TYPE(UINT8, uint8_t)
   1387 CAPNP_DECLARE_TYPE(UINT16, uint16_t)
   1388 CAPNP_DECLARE_TYPE(UINT32, uint32_t)
   1389 CAPNP_DECLARE_TYPE(UINT64, uint64_t)
   1390 CAPNP_DECLARE_TYPE(FLOAT32, float)
   1391 CAPNP_DECLARE_TYPE(FLOAT64, double)
   1392 
   1393 CAPNP_DECLARE_TYPE(TEXT, Text)
   1394 CAPNP_DECLARE_TYPE(DATA, Data)
   1395 CAPNP_DECLARE_TYPE(LIST, DynamicList)
   1396 CAPNP_DECLARE_TYPE(STRUCT, DynamicStruct)
   1397 CAPNP_DECLARE_TYPE(INTERFACE, DynamicCapability)
   1398 CAPNP_DECLARE_TYPE(ENUM, DynamicEnum)
   1399 CAPNP_DECLARE_TYPE(ANY_POINTER, AnyPointer)
   1400 #undef CAPNP_DECLARE_TYPE
   1401 
   1402 // CAPNP_DECLARE_TYPE(Void) causes gcc 4.7 to segfault.  If I do it manually and remove the
   1403 // ReaderFor<> and BuilderFor<> wrappers, it works.
   1404 template <>
   1405 struct DynamicValue::Reader::AsImpl<Void> {
   1406   static Void apply(const Reader& reader);
   1407 };
   1408 template <>
   1409 struct DynamicValue::Builder::AsImpl<Void> {
   1410   static Void apply(Builder& builder);
   1411 };
   1412 
   1413 template <typename T>
   1414 struct DynamicValue::Reader::AsImpl<T, Kind::ENUM> {
   1415   static T apply(const Reader& reader) {
   1416     return reader.as<DynamicEnum>().as<T>();
   1417   }
   1418 };
   1419 template <typename T>
   1420 struct DynamicValue::Builder::AsImpl<T, Kind::ENUM> {
   1421   static T apply(Builder& builder) {
   1422     return builder.as<DynamicEnum>().as<T>();
   1423   }
   1424 };
   1425 
   1426 template <typename T>
   1427 struct DynamicValue::Reader::AsImpl<T, Kind::STRUCT> {
   1428   static typename T::Reader apply(const Reader& reader) {
   1429     return reader.as<DynamicStruct>().as<T>();
   1430   }
   1431 };
   1432 template <typename T>
   1433 struct DynamicValue::Builder::AsImpl<T, Kind::STRUCT> {
   1434   static typename T::Builder apply(Builder& builder) {
   1435     return builder.as<DynamicStruct>().as<T>();
   1436   }
   1437 };
   1438 
   1439 template <typename T>
   1440 struct DynamicValue::Reader::AsImpl<T, Kind::LIST> {
   1441   static typename T::Reader apply(const Reader& reader) {
   1442     return reader.as<DynamicList>().as<T>();
   1443   }
   1444 };
   1445 template <typename T>
   1446 struct DynamicValue::Builder::AsImpl<T, Kind::LIST> {
   1447   static typename T::Builder apply(Builder& builder) {
   1448     return builder.as<DynamicList>().as<T>();
   1449   }
   1450 };
   1451 
   1452 template <typename T>
   1453 struct DynamicValue::Reader::AsImpl<T, Kind::INTERFACE> {
   1454   static typename T::Client apply(const Reader& reader) {
   1455     return reader.as<DynamicCapability>().as<T>();
   1456   }
   1457 };
   1458 template <typename T>
   1459 struct DynamicValue::Builder::AsImpl<T, Kind::INTERFACE> {
   1460   static typename T::Client apply(Builder& builder) {
   1461     return builder.as<DynamicCapability>().as<T>();
   1462   }
   1463 };
   1464 
   1465 template <>
   1466 struct DynamicValue::Reader::AsImpl<DynamicValue> {
   1467   static DynamicValue::Reader apply(const Reader& reader) {
   1468     return reader;
   1469   }
   1470 };
   1471 template <>
   1472 struct DynamicValue::Builder::AsImpl<DynamicValue> {
   1473   static DynamicValue::Builder apply(Builder& builder) {
   1474     return builder;
   1475   }
   1476 };
   1477 
   1478 inline DynamicValue::Pipeline::Pipeline(std::nullptr_t n): type(UNKNOWN) {}
   1479 inline DynamicValue::Pipeline::Pipeline(DynamicStruct::Pipeline&& value)
   1480     : type(STRUCT), structValue(kj::mv(value)) {}
   1481 inline DynamicValue::Pipeline::Pipeline(DynamicCapability::Client&& value)
   1482     : type(CAPABILITY), capabilityValue(kj::mv(value)) {}
   1483 
   1484 template <typename T>
   1485 struct DynamicValue::Pipeline::AsImpl<T, Kind::STRUCT> {
   1486   static typename T::Pipeline apply(Pipeline& pipeline) {
   1487     return pipeline.releaseAs<DynamicStruct>().releaseAs<T>();
   1488   }
   1489 };
   1490 template <typename T>
   1491 struct DynamicValue::Pipeline::AsImpl<T, Kind::INTERFACE> {
   1492   static typename T::Client apply(Pipeline& pipeline) {
   1493     return pipeline.releaseAs<DynamicCapability>().releaseAs<T>();
   1494   }
   1495 };
   1496 template <>
   1497 struct DynamicValue::Pipeline::AsImpl<DynamicStruct, Kind::OTHER> {
   1498   static PipelineFor<DynamicStruct> apply(Pipeline& pipeline);
   1499 };
   1500 template <>
   1501 struct DynamicValue::Pipeline::AsImpl<DynamicCapability, Kind::OTHER> {
   1502   static PipelineFor<DynamicCapability> apply(Pipeline& pipeline);
   1503 };
   1504 
   1505 // -------------------------------------------------------------------
   1506 
   1507 template <typename T>
   1508 typename T::Reader DynamicStruct::Reader::as() const {
   1509   static_assert(kind<T>() == Kind::STRUCT,
   1510                 "DynamicStruct::Reader::as<T>() can only convert to struct types.");
   1511   schema.requireUsableAs<T>();
   1512   return typename T::Reader(reader);
   1513 }
   1514 
   1515 template <typename T>
   1516 typename T::Builder DynamicStruct::Builder::as() {
   1517   static_assert(kind<T>() == Kind::STRUCT,
   1518                 "DynamicStruct::Builder::as<T>() can only convert to struct types.");
   1519   schema.requireUsableAs<T>();
   1520   return typename T::Builder(builder);
   1521 }
   1522 
   1523 template <>
   1524 inline DynamicStruct::Reader DynamicStruct::Reader::as<DynamicStruct>() const {
   1525   return *this;
   1526 }
   1527 template <>
   1528 inline DynamicStruct::Builder DynamicStruct::Builder::as<DynamicStruct>() {
   1529   return *this;
   1530 }
   1531 
   1532 inline DynamicStruct::Reader DynamicStruct::Builder::asReader() const {
   1533   return DynamicStruct::Reader(schema, builder.asReader());
   1534 }
   1535 
   1536 template <>
   1537 inline AnyStruct::Reader DynamicStruct::Reader::as<AnyStruct>() const {
   1538   return AnyStruct::Reader(reader);
   1539 }
   1540 
   1541 template <>
   1542 inline AnyStruct::Builder DynamicStruct::Builder::as<AnyStruct>() {
   1543   return AnyStruct::Builder(builder);
   1544 }
   1545 
   1546 template <>
   1547 inline DynamicStruct::Reader AnyStruct::Reader::as<DynamicStruct>(StructSchema schema) const {
   1548   return DynamicStruct::Reader(schema, _reader);
   1549 }
   1550 
   1551 template <>
   1552 inline DynamicStruct::Builder AnyStruct::Builder::as<DynamicStruct>(StructSchema schema) {
   1553   return DynamicStruct::Builder(schema, _builder);
   1554 }
   1555 
   1556 template <typename T>
   1557 typename T::Pipeline DynamicStruct::Pipeline::releaseAs() {
   1558   static_assert(kind<T>() == Kind::STRUCT,
   1559                 "DynamicStruct::Pipeline::releaseAs<T>() can only convert to struct types.");
   1560   schema.requireUsableAs<T>();
   1561   return typename T::Pipeline(kj::mv(typeless));
   1562 }
   1563 
   1564 // -------------------------------------------------------------------
   1565 
   1566 template <typename T>
   1567 typename T::Reader DynamicList::Reader::as() const {
   1568   static_assert(kind<T>() == Kind::LIST,
   1569                 "DynamicStruct::Reader::as<T>() can only convert to list types.");
   1570   schema.requireUsableAs<T>();
   1571   return typename T::Reader(reader);
   1572 }
   1573 template <typename T>
   1574 typename T::Builder DynamicList::Builder::as() {
   1575   static_assert(kind<T>() == Kind::LIST,
   1576                 "DynamicStruct::Builder::as<T>() can only convert to list types.");
   1577   schema.requireUsableAs<T>();
   1578   return typename T::Builder(builder);
   1579 }
   1580 
   1581 template <>
   1582 inline DynamicList::Reader DynamicList::Reader::as<DynamicList>() const {
   1583   return *this;
   1584 }
   1585 template <>
   1586 inline DynamicList::Builder DynamicList::Builder::as<DynamicList>() {
   1587   return *this;
   1588 }
   1589 
   1590 template <>
   1591 inline AnyList::Reader DynamicList::Reader::as<AnyList>() const {
   1592   return AnyList::Reader(reader);
   1593 }
   1594 
   1595 template <>
   1596 inline AnyList::Builder DynamicList::Builder::as<AnyList>() {
   1597   return AnyList::Builder(builder);
   1598 }
   1599 
   1600 // -------------------------------------------------------------------
   1601 
   1602 template <typename T, typename>
   1603 inline DynamicCapability::Client::Client(T&& client)
   1604     : Capability::Client(kj::mv(client)), schema(Schema::from<FromClient<T>>()) {}
   1605 
   1606 template <typename T, typename>
   1607 inline DynamicCapability::Client::Client(kj::Own<T>&& server)
   1608     : Client(server->getSchema(), kj::mv(server)) {}
   1609 template <typename T>
   1610 inline DynamicCapability::Client::Client(InterfaceSchema schema, kj::Own<T>&& server)
   1611     : Capability::Client(kj::mv(server)), schema(schema) {}
   1612 
   1613 template <typename T, typename>
   1614 typename T::Client DynamicCapability::Client::as() {
   1615   static_assert(kind<T>() == Kind::INTERFACE,
   1616                 "DynamicCapability::Client::as<T>() can only convert to interface types.");
   1617   schema.requireUsableAs<T>();
   1618   return typename T::Client(hook->addRef());
   1619 }
   1620 
   1621 template <typename T, typename>
   1622 typename T::Client DynamicCapability::Client::releaseAs() {
   1623   static_assert(kind<T>() == Kind::INTERFACE,
   1624                 "DynamicCapability::Client::as<T>() can only convert to interface types.");
   1625   schema.requireUsableAs<T>();
   1626   return typename T::Client(kj::mv(hook));
   1627 }
   1628 
   1629 inline CallContext<DynamicStruct, DynamicStruct>::CallContext(
   1630     CallContextHook& hook, StructSchema paramType, StructSchema resultType)
   1631     : hook(&hook), paramType(paramType), resultType(resultType) {}
   1632 inline DynamicStruct::Reader CallContext<DynamicStruct, DynamicStruct>::getParams() {
   1633   return hook->getParams().getAs<DynamicStruct>(paramType);
   1634 }
   1635 inline void CallContext<DynamicStruct, DynamicStruct>::releaseParams() {
   1636   hook->releaseParams();
   1637 }
   1638 inline DynamicStruct::Builder CallContext<DynamicStruct, DynamicStruct>::getResults(
   1639     kj::Maybe<MessageSize> sizeHint) {
   1640   return hook->getResults(sizeHint).getAs<DynamicStruct>(resultType);
   1641 }
   1642 inline DynamicStruct::Builder CallContext<DynamicStruct, DynamicStruct>::initResults(
   1643     kj::Maybe<MessageSize> sizeHint) {
   1644   return hook->getResults(sizeHint).initAs<DynamicStruct>(resultType);
   1645 }
   1646 inline void CallContext<DynamicStruct, DynamicStruct>::setResults(DynamicStruct::Reader value) {
   1647   hook->getResults(value.totalSize()).setAs<DynamicStruct>(value);
   1648 }
   1649 inline void CallContext<DynamicStruct, DynamicStruct>::adoptResults(Orphan<DynamicStruct>&& value) {
   1650   hook->getResults(MessageSize { 0, 0 }).adopt(kj::mv(value));
   1651 }
   1652 inline Orphanage CallContext<DynamicStruct, DynamicStruct>::getResultsOrphanage(
   1653     kj::Maybe<MessageSize> sizeHint) {
   1654   return Orphanage::getForMessageContaining(hook->getResults(sizeHint));
   1655 }
   1656 template <typename SubParams>
   1657 inline kj::Promise<void> CallContext<DynamicStruct, DynamicStruct>::tailCall(
   1658     Request<SubParams, DynamicStruct>&& tailRequest) {
   1659   return hook->tailCall(kj::mv(tailRequest.hook));
   1660 }
   1661 inline void CallContext<DynamicStruct, DynamicStruct>::allowCancellation() {
   1662   hook->allowCancellation();
   1663 }
   1664 
   1665 template <>
   1666 inline DynamicCapability::Client Capability::Client::castAs<DynamicCapability>(
   1667     InterfaceSchema schema) {
   1668   return DynamicCapability::Client(schema, hook->addRef());
   1669 }
   1670 
   1671 // -------------------------------------------------------------------
   1672 
   1673 template <typename T>
   1674 ReaderFor<T> ConstSchema::as() const {
   1675   return DynamicValue::Reader(*this).as<T>();
   1676 }
   1677 
   1678 }  // namespace capnp
   1679 
   1680 CAPNP_END_HEADER