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