annotate win64-msvc/include/capnp/dynamic.h @ 148:b4bfdf10c4b3

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