annotate win32-mingw/include/capnp/dynamic.h @ 141:1b5b6dfd0d0e

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