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