Mercurial > hg > sv-dependency-builds
comparison src/capnproto-git-20161025/c++/src/capnp/dynamic.c++ @ 48:9530b331f8c1
Add Cap'n Proto source
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 25 Oct 2016 11:17:01 +0100 (2016-10-25) |
parents | |
children |
comparison
equal
deleted
inserted
replaced
47:d93140aac40b | 48:9530b331f8c1 |
---|---|
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 #include "dynamic.h" | |
23 #include <kj/debug.h> | |
24 | |
25 namespace capnp { | |
26 | |
27 namespace { | |
28 | |
29 bool hasDiscriminantValue(const schema::Field::Reader& reader) { | |
30 return reader.getDiscriminantValue() != schema::Field::NO_DISCRIMINANT; | |
31 } | |
32 | |
33 template <typename T, typename U> | |
34 KJ_ALWAYS_INLINE(T bitCast(U value)); | |
35 | |
36 template <typename T, typename U> | |
37 inline T bitCast(U value) { | |
38 static_assert(sizeof(T) == sizeof(U), "Size must match."); | |
39 return value; | |
40 } | |
41 template <> | |
42 inline float bitCast<float, uint32_t>(uint32_t value) KJ_UNUSED; | |
43 template <> | |
44 inline float bitCast<float, uint32_t>(uint32_t value) { | |
45 float result; | |
46 memcpy(&result, &value, sizeof(value)); | |
47 return result; | |
48 } | |
49 template <> | |
50 inline double bitCast<double, uint64_t>(uint64_t value) KJ_UNUSED; | |
51 template <> | |
52 inline double bitCast<double, uint64_t>(uint64_t value) { | |
53 double result; | |
54 memcpy(&result, &value, sizeof(value)); | |
55 return result; | |
56 } | |
57 template <> | |
58 inline uint32_t bitCast<uint32_t, float>(float value) { | |
59 uint32_t result; | |
60 memcpy(&result, &value, sizeof(value)); | |
61 return result; | |
62 } | |
63 template <> | |
64 inline uint64_t bitCast<uint64_t, double>(double value) { | |
65 uint64_t result; | |
66 memcpy(&result, &value, sizeof(value)); | |
67 return result; | |
68 } | |
69 | |
70 ElementSize elementSizeFor(schema::Type::Which elementType) { | |
71 switch (elementType) { | |
72 case schema::Type::VOID: return ElementSize::VOID; | |
73 case schema::Type::BOOL: return ElementSize::BIT; | |
74 case schema::Type::INT8: return ElementSize::BYTE; | |
75 case schema::Type::INT16: return ElementSize::TWO_BYTES; | |
76 case schema::Type::INT32: return ElementSize::FOUR_BYTES; | |
77 case schema::Type::INT64: return ElementSize::EIGHT_BYTES; | |
78 case schema::Type::UINT8: return ElementSize::BYTE; | |
79 case schema::Type::UINT16: return ElementSize::TWO_BYTES; | |
80 case schema::Type::UINT32: return ElementSize::FOUR_BYTES; | |
81 case schema::Type::UINT64: return ElementSize::EIGHT_BYTES; | |
82 case schema::Type::FLOAT32: return ElementSize::FOUR_BYTES; | |
83 case schema::Type::FLOAT64: return ElementSize::EIGHT_BYTES; | |
84 | |
85 case schema::Type::TEXT: return ElementSize::POINTER; | |
86 case schema::Type::DATA: return ElementSize::POINTER; | |
87 case schema::Type::LIST: return ElementSize::POINTER; | |
88 case schema::Type::ENUM: return ElementSize::TWO_BYTES; | |
89 case schema::Type::STRUCT: return ElementSize::INLINE_COMPOSITE; | |
90 case schema::Type::INTERFACE: return ElementSize::POINTER; | |
91 case schema::Type::ANY_POINTER: KJ_FAIL_ASSERT("List(AnyPointer) not supported."); break; | |
92 } | |
93 | |
94 // Unknown type. Treat it as zero-size. | |
95 return ElementSize::VOID; | |
96 } | |
97 | |
98 inline _::StructSize structSizeFromSchema(StructSchema schema) { | |
99 auto node = schema.getProto().getStruct(); | |
100 return _::StructSize( | |
101 node.getDataWordCount() * WORDS, | |
102 node.getPointerCount() * POINTERS); | |
103 } | |
104 | |
105 } // namespace | |
106 | |
107 // ======================================================================================= | |
108 | |
109 kj::Maybe<EnumSchema::Enumerant> DynamicEnum::getEnumerant() const { | |
110 auto enumerants = schema.getEnumerants(); | |
111 if (value < enumerants.size()) { | |
112 return enumerants[value]; | |
113 } else { | |
114 return nullptr; | |
115 } | |
116 } | |
117 | |
118 uint16_t DynamicEnum::asImpl(uint64_t requestedTypeId) const { | |
119 KJ_REQUIRE(requestedTypeId == schema.getProto().getId(), | |
120 "Type mismatch in DynamicEnum.as().") { | |
121 // use it anyway | |
122 break; | |
123 } | |
124 return value; | |
125 } | |
126 | |
127 // ======================================================================================= | |
128 | |
129 bool DynamicStruct::Reader::isSetInUnion(StructSchema::Field field) const { | |
130 auto proto = field.getProto(); | |
131 if (hasDiscriminantValue(proto)) { | |
132 uint16_t discrim = reader.getDataField<uint16_t>( | |
133 schema.getProto().getStruct().getDiscriminantOffset() * ELEMENTS); | |
134 return discrim == proto.getDiscriminantValue(); | |
135 } else { | |
136 return true; | |
137 } | |
138 } | |
139 | |
140 void DynamicStruct::Reader::verifySetInUnion(StructSchema::Field field) const { | |
141 KJ_REQUIRE(isSetInUnion(field), | |
142 "Tried to get() a union member which is not currently initialized.", | |
143 field.getProto().getName(), schema.getProto().getDisplayName()); | |
144 } | |
145 | |
146 bool DynamicStruct::Builder::isSetInUnion(StructSchema::Field field) { | |
147 auto proto = field.getProto(); | |
148 if (hasDiscriminantValue(proto)) { | |
149 uint16_t discrim = builder.getDataField<uint16_t>( | |
150 schema.getProto().getStruct().getDiscriminantOffset() * ELEMENTS); | |
151 return discrim == proto.getDiscriminantValue(); | |
152 } else { | |
153 return true; | |
154 } | |
155 } | |
156 | |
157 void DynamicStruct::Builder::verifySetInUnion(StructSchema::Field field) { | |
158 KJ_REQUIRE(isSetInUnion(field), | |
159 "Tried to get() a union member which is not currently initialized.", | |
160 field.getProto().getName(), schema.getProto().getDisplayName()); | |
161 } | |
162 | |
163 void DynamicStruct::Builder::setInUnion(StructSchema::Field field) { | |
164 // If a union member, set the discriminant to match. | |
165 auto proto = field.getProto(); | |
166 if (hasDiscriminantValue(proto)) { | |
167 builder.setDataField<uint16_t>( | |
168 schema.getProto().getStruct().getDiscriminantOffset() * ELEMENTS, | |
169 proto.getDiscriminantValue()); | |
170 } | |
171 } | |
172 | |
173 DynamicValue::Reader DynamicStruct::Reader::get(StructSchema::Field field) const { | |
174 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
175 verifySetInUnion(field); | |
176 | |
177 auto type = field.getType(); | |
178 auto proto = field.getProto(); | |
179 switch (proto.which()) { | |
180 case schema::Field::SLOT: { | |
181 auto slot = proto.getSlot(); | |
182 | |
183 // Note that the default value might be "anyPointer" even if the type is some poniter type | |
184 // *other than* anyPointer. This happens with generics -- the field is actually a generic | |
185 // parameter that has been bound, but the default value was of course compiled without any | |
186 // binding available. | |
187 auto dval = slot.getDefaultValue(); | |
188 | |
189 switch (type.which()) { | |
190 case schema::Type::VOID: | |
191 return reader.getDataField<Void>(slot.getOffset() * ELEMENTS); | |
192 | |
193 #define HANDLE_TYPE(discrim, titleCase, type) \ | |
194 case schema::Type::discrim: \ | |
195 return reader.getDataField<type>( \ | |
196 slot.getOffset() * ELEMENTS, \ | |
197 bitCast<_::Mask<type>>(dval.get##titleCase())); | |
198 | |
199 HANDLE_TYPE(BOOL, Bool, bool) | |
200 HANDLE_TYPE(INT8, Int8, int8_t) | |
201 HANDLE_TYPE(INT16, Int16, int16_t) | |
202 HANDLE_TYPE(INT32, Int32, int32_t) | |
203 HANDLE_TYPE(INT64, Int64, int64_t) | |
204 HANDLE_TYPE(UINT8, Uint8, uint8_t) | |
205 HANDLE_TYPE(UINT16, Uint16, uint16_t) | |
206 HANDLE_TYPE(UINT32, Uint32, uint32_t) | |
207 HANDLE_TYPE(UINT64, Uint64, uint64_t) | |
208 HANDLE_TYPE(FLOAT32, Float32, float) | |
209 HANDLE_TYPE(FLOAT64, Float64, double) | |
210 | |
211 #undef HANDLE_TYPE | |
212 | |
213 case schema::Type::ENUM: { | |
214 uint16_t typedDval = dval.getEnum(); | |
215 return DynamicEnum(type.asEnum(), | |
216 reader.getDataField<uint16_t>(slot.getOffset() * ELEMENTS, typedDval)); | |
217 } | |
218 | |
219 case schema::Type::TEXT: { | |
220 Text::Reader typedDval = dval.isAnyPointer() ? Text::Reader() : dval.getText(); | |
221 return reader.getPointerField(slot.getOffset() * POINTERS) | |
222 .getBlob<Text>(typedDval.begin(), typedDval.size() * BYTES); | |
223 } | |
224 | |
225 case schema::Type::DATA: { | |
226 Data::Reader typedDval = dval.isAnyPointer() ? Data::Reader() : dval.getData(); | |
227 return reader.getPointerField(slot.getOffset() * POINTERS) | |
228 .getBlob<Data>(typedDval.begin(), typedDval.size() * BYTES); | |
229 } | |
230 | |
231 case schema::Type::LIST: { | |
232 auto elementType = type.asList().getElementType(); | |
233 return DynamicList::Reader(type.asList(), | |
234 reader.getPointerField(slot.getOffset() * POINTERS) | |
235 .getList(elementSizeFor(elementType.which()), dval.isAnyPointer() ? nullptr : | |
236 dval.getList().getAs<_::UncheckedMessage>())); | |
237 } | |
238 | |
239 case schema::Type::STRUCT: | |
240 return DynamicStruct::Reader(type.asStruct(), | |
241 reader.getPointerField(slot.getOffset() * POINTERS) | |
242 .getStruct(dval.isAnyPointer() ? nullptr : | |
243 dval.getStruct().getAs<_::UncheckedMessage>())); | |
244 | |
245 case schema::Type::ANY_POINTER: | |
246 return AnyPointer::Reader(reader.getPointerField(slot.getOffset() * POINTERS)); | |
247 | |
248 case schema::Type::INTERFACE: | |
249 return DynamicCapability::Client(type.asInterface(), | |
250 reader.getPointerField(slot.getOffset() * POINTERS).getCapability()); | |
251 } | |
252 | |
253 KJ_UNREACHABLE; | |
254 } | |
255 | |
256 case schema::Field::GROUP: | |
257 return DynamicStruct::Reader(type.asStruct(), reader); | |
258 } | |
259 | |
260 KJ_UNREACHABLE; | |
261 } | |
262 | |
263 DynamicValue::Builder DynamicStruct::Builder::get(StructSchema::Field field) { | |
264 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
265 verifySetInUnion(field); | |
266 | |
267 auto proto = field.getProto(); | |
268 auto type = field.getType(); | |
269 switch (proto.which()) { | |
270 case schema::Field::SLOT: { | |
271 auto slot = proto.getSlot(); | |
272 | |
273 // Note that the default value might be "anyPointer" even if the type is some poniter type | |
274 // *other than* anyPointer. This happens with generics -- the field is actually a generic | |
275 // parameter that has been bound, but the default value was of course compiled without any | |
276 // binding available. | |
277 auto dval = slot.getDefaultValue(); | |
278 | |
279 switch (type.which()) { | |
280 case schema::Type::VOID: | |
281 return builder.getDataField<Void>(slot.getOffset() * ELEMENTS); | |
282 | |
283 #define HANDLE_TYPE(discrim, titleCase, type) \ | |
284 case schema::Type::discrim: \ | |
285 return builder.getDataField<type>( \ | |
286 slot.getOffset() * ELEMENTS, \ | |
287 bitCast<_::Mask<type>>(dval.get##titleCase())); | |
288 | |
289 HANDLE_TYPE(BOOL, Bool, bool) | |
290 HANDLE_TYPE(INT8, Int8, int8_t) | |
291 HANDLE_TYPE(INT16, Int16, int16_t) | |
292 HANDLE_TYPE(INT32, Int32, int32_t) | |
293 HANDLE_TYPE(INT64, Int64, int64_t) | |
294 HANDLE_TYPE(UINT8, Uint8, uint8_t) | |
295 HANDLE_TYPE(UINT16, Uint16, uint16_t) | |
296 HANDLE_TYPE(UINT32, Uint32, uint32_t) | |
297 HANDLE_TYPE(UINT64, Uint64, uint64_t) | |
298 HANDLE_TYPE(FLOAT32, Float32, float) | |
299 HANDLE_TYPE(FLOAT64, Float64, double) | |
300 | |
301 #undef HANDLE_TYPE | |
302 | |
303 case schema::Type::ENUM: { | |
304 uint16_t typedDval = dval.getEnum(); | |
305 return DynamicEnum(type.asEnum(), | |
306 builder.getDataField<uint16_t>(slot.getOffset() * ELEMENTS, typedDval)); | |
307 } | |
308 | |
309 case schema::Type::TEXT: { | |
310 Text::Reader typedDval = dval.isAnyPointer() ? Text::Reader() : dval.getText(); | |
311 return builder.getPointerField(slot.getOffset() * POINTERS) | |
312 .getBlob<Text>(typedDval.begin(), typedDval.size() * BYTES); | |
313 } | |
314 | |
315 case schema::Type::DATA: { | |
316 Data::Reader typedDval = dval.isAnyPointer() ? Data::Reader() : dval.getData(); | |
317 return builder.getPointerField(slot.getOffset() * POINTERS) | |
318 .getBlob<Data>(typedDval.begin(), typedDval.size() * BYTES); | |
319 } | |
320 | |
321 case schema::Type::LIST: { | |
322 ListSchema listType = type.asList(); | |
323 if (listType.whichElementType() == schema::Type::STRUCT) { | |
324 return DynamicList::Builder(listType, | |
325 builder.getPointerField(slot.getOffset() * POINTERS) | |
326 .getStructList(structSizeFromSchema(listType.getStructElementType()), | |
327 dval.isAnyPointer() ? nullptr : | |
328 dval.getList().getAs<_::UncheckedMessage>())); | |
329 } else { | |
330 return DynamicList::Builder(listType, | |
331 builder.getPointerField(slot.getOffset() * POINTERS) | |
332 .getList(elementSizeFor(listType.whichElementType()), | |
333 dval.isAnyPointer() ? nullptr : | |
334 dval.getList().getAs<_::UncheckedMessage>())); | |
335 } | |
336 } | |
337 | |
338 case schema::Type::STRUCT: { | |
339 auto structSchema = type.asStruct(); | |
340 return DynamicStruct::Builder(structSchema, | |
341 builder.getPointerField(slot.getOffset() * POINTERS) | |
342 .getStruct(structSizeFromSchema(structSchema), | |
343 dval.isAnyPointer() ? nullptr : | |
344 dval.getStruct().getAs<_::UncheckedMessage>())); | |
345 } | |
346 | |
347 case schema::Type::ANY_POINTER: | |
348 return AnyPointer::Builder(builder.getPointerField(slot.getOffset() * POINTERS)); | |
349 | |
350 case schema::Type::INTERFACE: | |
351 return DynamicCapability::Client(type.asInterface(), | |
352 builder.getPointerField(slot.getOffset() * POINTERS).getCapability()); | |
353 } | |
354 | |
355 KJ_UNREACHABLE; | |
356 } | |
357 | |
358 case schema::Field::GROUP: | |
359 return DynamicStruct::Builder(type.asStruct(), builder); | |
360 } | |
361 | |
362 KJ_UNREACHABLE; | |
363 } | |
364 | |
365 DynamicValue::Pipeline DynamicStruct::Pipeline::get(StructSchema::Field field) { | |
366 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
367 | |
368 auto proto = field.getProto(); | |
369 KJ_REQUIRE(!hasDiscriminantValue(proto), "Can't pipeline on union members."); | |
370 | |
371 auto type = field.getType(); | |
372 | |
373 switch (proto.which()) { | |
374 case schema::Field::SLOT: { | |
375 auto slot = proto.getSlot(); | |
376 | |
377 switch (type.which()) { | |
378 case schema::Type::STRUCT: | |
379 return DynamicStruct::Pipeline(type.asStruct(), | |
380 typeless.getPointerField(slot.getOffset())); | |
381 | |
382 case schema::Type::INTERFACE: | |
383 return DynamicCapability::Client(type.asInterface(), | |
384 typeless.getPointerField(slot.getOffset()).asCap()); | |
385 | |
386 default: | |
387 KJ_FAIL_REQUIRE("Can only pipeline on struct and interface fields."); | |
388 } | |
389 | |
390 KJ_UNREACHABLE; | |
391 } | |
392 | |
393 case schema::Field::GROUP: | |
394 return DynamicStruct::Pipeline(type.asStruct(), typeless.noop()); | |
395 } | |
396 | |
397 KJ_UNREACHABLE; | |
398 } | |
399 | |
400 bool DynamicStruct::Reader::has(StructSchema::Field field) const { | |
401 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
402 | |
403 auto proto = field.getProto(); | |
404 if (hasDiscriminantValue(proto)) { | |
405 uint16_t discrim = reader.getDataField<uint16_t>( | |
406 schema.getProto().getStruct().getDiscriminantOffset() * ELEMENTS); | |
407 if (discrim != proto.getDiscriminantValue()) { | |
408 // Field is not active in the union. | |
409 return false; | |
410 } | |
411 } | |
412 | |
413 switch (proto.which()) { | |
414 case schema::Field::SLOT: | |
415 // Continue to below. | |
416 break; | |
417 | |
418 case schema::Field::GROUP: | |
419 return true; | |
420 } | |
421 | |
422 auto slot = proto.getSlot(); | |
423 auto type = field.getType(); | |
424 | |
425 switch (type.which()) { | |
426 case schema::Type::VOID: | |
427 case schema::Type::BOOL: | |
428 case schema::Type::INT8: | |
429 case schema::Type::INT16: | |
430 case schema::Type::INT32: | |
431 case schema::Type::INT64: | |
432 case schema::Type::UINT8: | |
433 case schema::Type::UINT16: | |
434 case schema::Type::UINT32: | |
435 case schema::Type::UINT64: | |
436 case schema::Type::FLOAT32: | |
437 case schema::Type::FLOAT64: | |
438 case schema::Type::ENUM: | |
439 // Primitive types are always present. | |
440 return true; | |
441 | |
442 case schema::Type::TEXT: | |
443 case schema::Type::DATA: | |
444 case schema::Type::LIST: | |
445 case schema::Type::STRUCT: | |
446 case schema::Type::ANY_POINTER: | |
447 case schema::Type::INTERFACE: | |
448 return !reader.getPointerField(slot.getOffset() * POINTERS).isNull(); | |
449 } | |
450 | |
451 // Unknown type. As far as we know, it isn't set. | |
452 return false; | |
453 } | |
454 | |
455 kj::Maybe<StructSchema::Field> DynamicStruct::Reader::which() const { | |
456 auto structProto = schema.getProto().getStruct(); | |
457 if (structProto.getDiscriminantCount() == 0) { | |
458 return nullptr; | |
459 } | |
460 | |
461 uint16_t discrim = reader.getDataField<uint16_t>(structProto.getDiscriminantOffset() * ELEMENTS); | |
462 return schema.getFieldByDiscriminant(discrim); | |
463 } | |
464 | |
465 kj::Maybe<StructSchema::Field> DynamicStruct::Builder::which() { | |
466 auto structProto = schema.getProto().getStruct(); | |
467 if (structProto.getDiscriminantCount() == 0) { | |
468 return nullptr; | |
469 } | |
470 | |
471 uint16_t discrim = builder.getDataField<uint16_t>(structProto.getDiscriminantOffset() * ELEMENTS); | |
472 return schema.getFieldByDiscriminant(discrim); | |
473 } | |
474 | |
475 void DynamicStruct::Builder::set(StructSchema::Field field, const DynamicValue::Reader& value) { | |
476 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
477 setInUnion(field); | |
478 | |
479 auto proto = field.getProto(); | |
480 auto type = field.getType(); | |
481 switch (proto.which()) { | |
482 case schema::Field::SLOT: { | |
483 auto slot = proto.getSlot(); | |
484 auto dval = slot.getDefaultValue(); | |
485 | |
486 switch (type.which()) { | |
487 case schema::Type::VOID: | |
488 builder.setDataField<Void>(slot.getOffset() * ELEMENTS, value.as<Void>()); | |
489 return; | |
490 | |
491 #define HANDLE_TYPE(discrim, titleCase, type) \ | |
492 case schema::Type::discrim: \ | |
493 builder.setDataField<type>( \ | |
494 slot.getOffset() * ELEMENTS, value.as<type>(), \ | |
495 bitCast<_::Mask<type> >(dval.get##titleCase())); \ | |
496 return; | |
497 | |
498 HANDLE_TYPE(BOOL, Bool, bool) | |
499 HANDLE_TYPE(INT8, Int8, int8_t) | |
500 HANDLE_TYPE(INT16, Int16, int16_t) | |
501 HANDLE_TYPE(INT32, Int32, int32_t) | |
502 HANDLE_TYPE(INT64, Int64, int64_t) | |
503 HANDLE_TYPE(UINT8, Uint8, uint8_t) | |
504 HANDLE_TYPE(UINT16, Uint16, uint16_t) | |
505 HANDLE_TYPE(UINT32, Uint32, uint32_t) | |
506 HANDLE_TYPE(UINT64, Uint64, uint64_t) | |
507 HANDLE_TYPE(FLOAT32, Float32, float) | |
508 HANDLE_TYPE(FLOAT64, Float64, double) | |
509 | |
510 #undef HANDLE_TYPE | |
511 | |
512 case schema::Type::ENUM: { | |
513 uint16_t rawValue; | |
514 auto enumSchema = type.asEnum(); | |
515 if (value.getType() == DynamicValue::TEXT) { | |
516 // Convert from text. | |
517 rawValue = enumSchema.getEnumerantByName(value.as<Text>()).getOrdinal(); | |
518 } else if (value.getType() == DynamicValue::INT || | |
519 value.getType() == DynamicValue::UINT) { | |
520 rawValue = value.as<uint16_t>(); | |
521 } else { | |
522 DynamicEnum enumValue = value.as<DynamicEnum>(); | |
523 KJ_REQUIRE(enumValue.getSchema() == enumSchema, "Value type mismatch.") { | |
524 return; | |
525 } | |
526 rawValue = enumValue.getRaw(); | |
527 } | |
528 builder.setDataField<uint16_t>(slot.getOffset() * ELEMENTS, rawValue, | |
529 dval.getEnum()); | |
530 return; | |
531 } | |
532 | |
533 case schema::Type::TEXT: | |
534 builder.getPointerField(slot.getOffset() * POINTERS).setBlob<Text>(value.as<Text>()); | |
535 return; | |
536 | |
537 case schema::Type::DATA: | |
538 builder.getPointerField(slot.getOffset() * POINTERS).setBlob<Data>(value.as<Data>()); | |
539 return; | |
540 | |
541 case schema::Type::LIST: { | |
542 ListSchema listType = type.asList(); | |
543 auto listValue = value.as<DynamicList>(); | |
544 KJ_REQUIRE(listValue.getSchema() == listType, "Value type mismatch.") { | |
545 return; | |
546 } | |
547 builder.getPointerField(slot.getOffset() * POINTERS).setList(listValue.reader); | |
548 return; | |
549 } | |
550 | |
551 case schema::Type::STRUCT: { | |
552 auto structType = type.asStruct(); | |
553 auto structValue = value.as<DynamicStruct>(); | |
554 KJ_REQUIRE(structValue.getSchema() == structType, "Value type mismatch.") { | |
555 return; | |
556 } | |
557 builder.getPointerField(slot.getOffset() * POINTERS).setStruct(structValue.reader); | |
558 return; | |
559 } | |
560 | |
561 case schema::Type::ANY_POINTER: { | |
562 auto target = AnyPointer::Builder(builder.getPointerField(slot.getOffset() * POINTERS)); | |
563 | |
564 switch (value.getType()) { | |
565 case DynamicValue::Type::TEXT: | |
566 target.setAs<Text>(value.as<Text>()); | |
567 return; | |
568 case DynamicValue::Type::DATA: | |
569 target.setAs<Data>(value.as<Data>()); | |
570 return; | |
571 case DynamicValue::Type::LIST: | |
572 target.setAs<DynamicList>(value.as<DynamicList>()); | |
573 return; | |
574 case DynamicValue::Type::STRUCT: | |
575 target.setAs<DynamicStruct>(value.as<DynamicStruct>()); | |
576 return; | |
577 case DynamicValue::Type::CAPABILITY: | |
578 target.setAs<DynamicCapability>(value.as<DynamicCapability>()); | |
579 return; | |
580 case DynamicValue::Type::ANY_POINTER: | |
581 target.set(value.as<AnyPointer>()); | |
582 return; | |
583 | |
584 case DynamicValue::Type::UNKNOWN: | |
585 case DynamicValue::Type::VOID: | |
586 case DynamicValue::Type::BOOL: | |
587 case DynamicValue::Type::INT: | |
588 case DynamicValue::Type::UINT: | |
589 case DynamicValue::Type::FLOAT: | |
590 case DynamicValue::Type::ENUM: | |
591 KJ_FAIL_ASSERT("Value type mismatch; expected AnyPointer"); | |
592 } | |
593 | |
594 KJ_UNREACHABLE; | |
595 } | |
596 | |
597 case schema::Type::INTERFACE: { | |
598 auto interfaceType = type.asInterface(); | |
599 auto capability = value.as<DynamicCapability>(); | |
600 KJ_REQUIRE(capability.getSchema().extends(interfaceType), "Value type mismatch.") { | |
601 return; | |
602 } | |
603 builder.getPointerField(slot.getOffset() * POINTERS).setCapability( | |
604 kj::mv(capability.hook)); | |
605 return; | |
606 } | |
607 } | |
608 | |
609 KJ_UNREACHABLE; | |
610 } | |
611 | |
612 case schema::Field::GROUP: { | |
613 auto src = value.as<DynamicStruct>(); | |
614 auto dst = init(field).as<DynamicStruct>(); | |
615 | |
616 KJ_IF_MAYBE(unionField, src.which()) { | |
617 dst.set(*unionField, src.get(*unionField)); | |
618 } | |
619 | |
620 for (auto field: src.schema.getNonUnionFields()) { | |
621 if (src.has(field)) { | |
622 dst.set(field, src.get(field)); | |
623 } | |
624 } | |
625 } | |
626 } | |
627 | |
628 KJ_UNREACHABLE; | |
629 } | |
630 | |
631 DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Field field) { | |
632 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
633 setInUnion(field); | |
634 | |
635 auto proto = field.getProto(); | |
636 auto type = field.getType(); | |
637 | |
638 switch (proto.which()) { | |
639 case schema::Field::SLOT: { | |
640 auto slot = proto.getSlot(); | |
641 switch (type.which()) { | |
642 case schema::Type::STRUCT: { | |
643 auto subSchema = type.asStruct(); | |
644 return DynamicStruct::Builder(subSchema, | |
645 builder.getPointerField(slot.getOffset() * POINTERS) | |
646 .initStruct(structSizeFromSchema(subSchema))); | |
647 } | |
648 case schema::Type::ANY_POINTER: { | |
649 auto pointer = builder.getPointerField(slot.getOffset() * POINTERS); | |
650 pointer.clear(); | |
651 return AnyPointer::Builder(pointer); | |
652 } | |
653 default: | |
654 KJ_FAIL_REQUIRE("init() without a size is only valid for struct and object fields."); | |
655 } | |
656 } | |
657 | |
658 case schema::Field::GROUP: { | |
659 clear(field); | |
660 return DynamicStruct::Builder(type.asStruct(), builder); | |
661 } | |
662 } | |
663 | |
664 KJ_UNREACHABLE; | |
665 } | |
666 | |
667 DynamicValue::Builder DynamicStruct::Builder::init(StructSchema::Field field, uint size) { | |
668 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
669 setInUnion(field); | |
670 | |
671 auto proto = field.getProto(); | |
672 auto type = field.getType(); | |
673 | |
674 switch (proto.which()) { | |
675 case schema::Field::SLOT: { | |
676 auto slot = proto.getSlot(); | |
677 switch (type.which()) { | |
678 case schema::Type::LIST: { | |
679 auto listType = type.asList(); | |
680 if (listType.whichElementType() == schema::Type::STRUCT) { | |
681 return DynamicList::Builder(listType, | |
682 builder.getPointerField(slot.getOffset() * POINTERS) | |
683 .initStructList(size * ELEMENTS, | |
684 structSizeFromSchema(listType.getStructElementType()))); | |
685 } else { | |
686 return DynamicList::Builder(listType, | |
687 builder.getPointerField(slot.getOffset() * POINTERS) | |
688 .initList(elementSizeFor(listType.whichElementType()), size * ELEMENTS)); | |
689 } | |
690 } | |
691 case schema::Type::TEXT: | |
692 return builder.getPointerField(slot.getOffset() * POINTERS) | |
693 .initBlob<Text>(size * BYTES); | |
694 case schema::Type::DATA: | |
695 return builder.getPointerField(slot.getOffset() * POINTERS) | |
696 .initBlob<Data>(size * BYTES); | |
697 default: | |
698 KJ_FAIL_REQUIRE( | |
699 "init() with size is only valid for list, text, or data fields.", | |
700 (uint)type.which()); | |
701 break; | |
702 } | |
703 } | |
704 | |
705 case schema::Field::GROUP: | |
706 KJ_FAIL_REQUIRE("init() with size is only valid for list, text, or data fields."); | |
707 } | |
708 | |
709 KJ_UNREACHABLE; | |
710 } | |
711 | |
712 void DynamicStruct::Builder::adopt(StructSchema::Field field, Orphan<DynamicValue>&& orphan) { | |
713 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
714 setInUnion(field); | |
715 | |
716 auto proto = field.getProto(); | |
717 switch (proto.which()) { | |
718 case schema::Field::SLOT: { | |
719 auto slot = proto.getSlot(); | |
720 auto type = field.getType(); | |
721 | |
722 switch (type.which()) { | |
723 case schema::Type::VOID: | |
724 case schema::Type::BOOL: | |
725 case schema::Type::INT8: | |
726 case schema::Type::INT16: | |
727 case schema::Type::INT32: | |
728 case schema::Type::INT64: | |
729 case schema::Type::UINT8: | |
730 case schema::Type::UINT16: | |
731 case schema::Type::UINT32: | |
732 case schema::Type::UINT64: | |
733 case schema::Type::FLOAT32: | |
734 case schema::Type::FLOAT64: | |
735 case schema::Type::ENUM: | |
736 set(field, orphan.getReader()); | |
737 return; | |
738 | |
739 case schema::Type::TEXT: | |
740 KJ_REQUIRE(orphan.getType() == DynamicValue::TEXT, "Value type mismatch."); | |
741 break; | |
742 | |
743 case schema::Type::DATA: | |
744 KJ_REQUIRE(orphan.getType() == DynamicValue::DATA, "Value type mismatch."); | |
745 break; | |
746 | |
747 case schema::Type::LIST: { | |
748 ListSchema listType = type.asList(); | |
749 KJ_REQUIRE(orphan.getType() == DynamicValue::LIST && orphan.listSchema == listType, | |
750 "Value type mismatch.") { | |
751 return; | |
752 } | |
753 break; | |
754 } | |
755 | |
756 case schema::Type::STRUCT: { | |
757 auto structType = type.asStruct(); | |
758 KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == structType, | |
759 "Value type mismatch.") { | |
760 return; | |
761 } | |
762 break; | |
763 } | |
764 | |
765 case schema::Type::ANY_POINTER: | |
766 KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT || | |
767 orphan.getType() == DynamicValue::LIST || | |
768 orphan.getType() == DynamicValue::TEXT || | |
769 orphan.getType() == DynamicValue::DATA || | |
770 orphan.getType() == DynamicValue::CAPABILITY || | |
771 orphan.getType() == DynamicValue::ANY_POINTER, | |
772 "Value type mismatch.") { | |
773 return; | |
774 } | |
775 break; | |
776 | |
777 case schema::Type::INTERFACE: { | |
778 auto interfaceType = type.asInterface(); | |
779 KJ_REQUIRE(orphan.getType() == DynamicValue::CAPABILITY && | |
780 orphan.interfaceSchema.extends(interfaceType), | |
781 "Value type mismatch.") { | |
782 return; | |
783 } | |
784 break; | |
785 } | |
786 } | |
787 | |
788 builder.getPointerField(slot.getOffset() * POINTERS).adopt(kj::mv(orphan.builder)); | |
789 return; | |
790 } | |
791 | |
792 case schema::Field::GROUP: | |
793 // Have to transfer fields. | |
794 auto src = orphan.get().as<DynamicStruct>(); | |
795 auto dst = init(field).as<DynamicStruct>(); | |
796 | |
797 KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == dst.getSchema(), | |
798 "Value type mismatch."); | |
799 | |
800 KJ_IF_MAYBE(unionField, src.which()) { | |
801 dst.adopt(*unionField, src.disown(*unionField)); | |
802 } | |
803 | |
804 for (auto field: src.schema.getNonUnionFields()) { | |
805 if (src.has(field)) { | |
806 dst.adopt(field, src.disown(field)); | |
807 } | |
808 } | |
809 | |
810 return; | |
811 } | |
812 | |
813 KJ_UNREACHABLE; | |
814 } | |
815 | |
816 Orphan<DynamicValue> DynamicStruct::Builder::disown(StructSchema::Field field) { | |
817 // We end up calling get(field) below, so we don't need to validate `field` here. | |
818 | |
819 auto proto = field.getProto(); | |
820 switch (proto.which()) { | |
821 case schema::Field::SLOT: { | |
822 auto slot = proto.getSlot(); | |
823 | |
824 switch (field.getType().which()) { | |
825 case schema::Type::VOID: | |
826 case schema::Type::BOOL: | |
827 case schema::Type::INT8: | |
828 case schema::Type::INT16: | |
829 case schema::Type::INT32: | |
830 case schema::Type::INT64: | |
831 case schema::Type::UINT8: | |
832 case schema::Type::UINT16: | |
833 case schema::Type::UINT32: | |
834 case schema::Type::UINT64: | |
835 case schema::Type::FLOAT32: | |
836 case schema::Type::FLOAT64: | |
837 case schema::Type::ENUM: { | |
838 auto result = Orphan<DynamicValue>(get(field), _::OrphanBuilder()); | |
839 clear(field); | |
840 return kj::mv(result); | |
841 } | |
842 | |
843 case schema::Type::TEXT: | |
844 case schema::Type::DATA: | |
845 case schema::Type::LIST: | |
846 case schema::Type::STRUCT: | |
847 case schema::Type::ANY_POINTER: | |
848 case schema::Type::INTERFACE: { | |
849 auto value = get(field); | |
850 return Orphan<DynamicValue>( | |
851 value, builder.getPointerField(slot.getOffset() * POINTERS).disown()); | |
852 } | |
853 } | |
854 KJ_UNREACHABLE; | |
855 } | |
856 | |
857 case schema::Field::GROUP: { | |
858 // We have to allocate new space for the group, unfortunately. | |
859 auto src = get(field).as<DynamicStruct>(); | |
860 | |
861 Orphan<DynamicStruct> result = | |
862 Orphanage::getForMessageContaining(*this).newOrphan(src.getSchema()); | |
863 auto dst = result.get(); | |
864 | |
865 KJ_IF_MAYBE(unionField, src.which()) { | |
866 dst.adopt(*unionField, src.disown(*unionField)); | |
867 } | |
868 | |
869 // We need to explicitly reset the union to its default field. | |
870 KJ_IF_MAYBE(unionField, src.schema.getFieldByDiscriminant(0)) { | |
871 src.clear(*unionField); | |
872 } | |
873 | |
874 for (auto field: src.schema.getNonUnionFields()) { | |
875 if (src.has(field)) { | |
876 dst.adopt(field, src.disown(field)); | |
877 } | |
878 } | |
879 | |
880 return kj::mv(result); | |
881 } | |
882 } | |
883 | |
884 KJ_UNREACHABLE; | |
885 } | |
886 | |
887 void DynamicStruct::Builder::clear(StructSchema::Field field) { | |
888 KJ_REQUIRE(field.getContainingStruct() == schema, "`field` is not a field of this struct."); | |
889 setInUnion(field); | |
890 | |
891 auto proto = field.getProto(); | |
892 auto type = field.getType(); | |
893 switch (proto.which()) { | |
894 case schema::Field::SLOT: { | |
895 auto slot = proto.getSlot(); | |
896 | |
897 switch (type.which()) { | |
898 case schema::Type::VOID: | |
899 builder.setDataField<Void>(slot.getOffset() * ELEMENTS, VOID); | |
900 return; | |
901 | |
902 #define HANDLE_TYPE(discrim, type) \ | |
903 case schema::Type::discrim: \ | |
904 builder.setDataField<type>(slot.getOffset() * ELEMENTS, 0); \ | |
905 return; | |
906 | |
907 HANDLE_TYPE(BOOL, bool) | |
908 HANDLE_TYPE(INT8, uint8_t) | |
909 HANDLE_TYPE(INT16, uint16_t) | |
910 HANDLE_TYPE(INT32, uint32_t) | |
911 HANDLE_TYPE(INT64, uint64_t) | |
912 HANDLE_TYPE(UINT8, uint8_t) | |
913 HANDLE_TYPE(UINT16, uint16_t) | |
914 HANDLE_TYPE(UINT32, uint32_t) | |
915 HANDLE_TYPE(UINT64, uint64_t) | |
916 HANDLE_TYPE(FLOAT32, uint32_t) | |
917 HANDLE_TYPE(FLOAT64, uint64_t) | |
918 HANDLE_TYPE(ENUM, uint16_t) | |
919 | |
920 #undef HANDLE_TYPE | |
921 | |
922 case schema::Type::TEXT: | |
923 case schema::Type::DATA: | |
924 case schema::Type::LIST: | |
925 case schema::Type::STRUCT: | |
926 case schema::Type::ANY_POINTER: | |
927 case schema::Type::INTERFACE: | |
928 builder.getPointerField(slot.getOffset() * POINTERS).clear(); | |
929 return; | |
930 } | |
931 | |
932 KJ_UNREACHABLE; | |
933 } | |
934 | |
935 case schema::Field::GROUP: { | |
936 DynamicStruct::Builder group(type.asStruct(), builder); | |
937 | |
938 // We clear the union field with discriminant 0 rather than the one that is set because | |
939 // we want the union to end up with its default field active. | |
940 KJ_IF_MAYBE(unionField, group.schema.getFieldByDiscriminant(0)) { | |
941 group.clear(*unionField); | |
942 } | |
943 | |
944 for (auto subField: group.schema.getNonUnionFields()) { | |
945 group.clear(subField); | |
946 } | |
947 return; | |
948 } | |
949 } | |
950 | |
951 KJ_UNREACHABLE; | |
952 } | |
953 | |
954 DynamicValue::Reader DynamicStruct::Reader::get(kj::StringPtr name) const { | |
955 return get(schema.getFieldByName(name)); | |
956 } | |
957 DynamicValue::Builder DynamicStruct::Builder::get(kj::StringPtr name) { | |
958 return get(schema.getFieldByName(name)); | |
959 } | |
960 DynamicValue::Pipeline DynamicStruct::Pipeline::get(kj::StringPtr name) { | |
961 return get(schema.getFieldByName(name)); | |
962 } | |
963 bool DynamicStruct::Reader::has(kj::StringPtr name) const { | |
964 return has(schema.getFieldByName(name)); | |
965 } | |
966 bool DynamicStruct::Builder::has(kj::StringPtr name) { | |
967 return has(schema.getFieldByName(name)); | |
968 } | |
969 void DynamicStruct::Builder::set(kj::StringPtr name, const DynamicValue::Reader& value) { | |
970 set(schema.getFieldByName(name), value); | |
971 } | |
972 void DynamicStruct::Builder::set(kj::StringPtr name, | |
973 std::initializer_list<DynamicValue::Reader> value) { | |
974 auto list = init(name, value.size()).as<DynamicList>(); | |
975 uint i = 0; | |
976 for (auto element: value) { | |
977 list.set(i++, element); | |
978 } | |
979 } | |
980 DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name) { | |
981 return init(schema.getFieldByName(name)); | |
982 } | |
983 DynamicValue::Builder DynamicStruct::Builder::init(kj::StringPtr name, uint size) { | |
984 return init(schema.getFieldByName(name), size); | |
985 } | |
986 void DynamicStruct::Builder::adopt(kj::StringPtr name, Orphan<DynamicValue>&& orphan) { | |
987 adopt(schema.getFieldByName(name), kj::mv(orphan)); | |
988 } | |
989 Orphan<DynamicValue> DynamicStruct::Builder::disown(kj::StringPtr name) { | |
990 return disown(schema.getFieldByName(name)); | |
991 } | |
992 void DynamicStruct::Builder::clear(kj::StringPtr name) { | |
993 clear(schema.getFieldByName(name)); | |
994 } | |
995 | |
996 // ======================================================================================= | |
997 | |
998 DynamicValue::Reader DynamicList::Reader::operator[](uint index) const { | |
999 KJ_REQUIRE(index < size(), "List index out-of-bounds."); | |
1000 | |
1001 switch (schema.whichElementType()) { | |
1002 #define HANDLE_TYPE(name, discrim, typeName) \ | |
1003 case schema::Type::discrim: \ | |
1004 return reader.getDataElement<typeName>(index * ELEMENTS); | |
1005 | |
1006 HANDLE_TYPE(void, VOID, Void) | |
1007 HANDLE_TYPE(bool, BOOL, bool) | |
1008 HANDLE_TYPE(int8, INT8, int8_t) | |
1009 HANDLE_TYPE(int16, INT16, int16_t) | |
1010 HANDLE_TYPE(int32, INT32, int32_t) | |
1011 HANDLE_TYPE(int64, INT64, int64_t) | |
1012 HANDLE_TYPE(uint8, UINT8, uint8_t) | |
1013 HANDLE_TYPE(uint16, UINT16, uint16_t) | |
1014 HANDLE_TYPE(uint32, UINT32, uint32_t) | |
1015 HANDLE_TYPE(uint64, UINT64, uint64_t) | |
1016 HANDLE_TYPE(float32, FLOAT32, float) | |
1017 HANDLE_TYPE(float64, FLOAT64, double) | |
1018 #undef HANDLE_TYPE | |
1019 | |
1020 case schema::Type::TEXT: | |
1021 return reader.getPointerElement(index * ELEMENTS).getBlob<Text>(nullptr, 0 * BYTES); | |
1022 case schema::Type::DATA: | |
1023 return reader.getPointerElement(index * ELEMENTS).getBlob<Data>(nullptr, 0 * BYTES); | |
1024 | |
1025 case schema::Type::LIST: { | |
1026 auto elementType = schema.getListElementType(); | |
1027 return DynamicList::Reader(elementType, | |
1028 reader.getPointerElement(index * ELEMENTS) | |
1029 .getList(elementSizeFor(elementType.whichElementType()), nullptr)); | |
1030 } | |
1031 | |
1032 case schema::Type::STRUCT: | |
1033 return DynamicStruct::Reader(schema.getStructElementType(), | |
1034 reader.getStructElement(index * ELEMENTS)); | |
1035 | |
1036 case schema::Type::ENUM: | |
1037 return DynamicEnum(schema.getEnumElementType(), | |
1038 reader.getDataElement<uint16_t>(index * ELEMENTS)); | |
1039 | |
1040 case schema::Type::ANY_POINTER: | |
1041 return AnyPointer::Reader(reader.getPointerElement(index * ELEMENTS)); | |
1042 | |
1043 case schema::Type::INTERFACE: | |
1044 return DynamicCapability::Client(schema.getInterfaceElementType(), | |
1045 reader.getPointerElement(index * ELEMENTS).getCapability()); | |
1046 } | |
1047 | |
1048 return nullptr; | |
1049 } | |
1050 | |
1051 DynamicValue::Builder DynamicList::Builder::operator[](uint index) { | |
1052 KJ_REQUIRE(index < size(), "List index out-of-bounds."); | |
1053 | |
1054 switch (schema.whichElementType()) { | |
1055 #define HANDLE_TYPE(name, discrim, typeName) \ | |
1056 case schema::Type::discrim: \ | |
1057 return builder.getDataElement<typeName>(index * ELEMENTS); | |
1058 | |
1059 HANDLE_TYPE(void, VOID, Void) | |
1060 HANDLE_TYPE(bool, BOOL, bool) | |
1061 HANDLE_TYPE(int8, INT8, int8_t) | |
1062 HANDLE_TYPE(int16, INT16, int16_t) | |
1063 HANDLE_TYPE(int32, INT32, int32_t) | |
1064 HANDLE_TYPE(int64, INT64, int64_t) | |
1065 HANDLE_TYPE(uint8, UINT8, uint8_t) | |
1066 HANDLE_TYPE(uint16, UINT16, uint16_t) | |
1067 HANDLE_TYPE(uint32, UINT32, uint32_t) | |
1068 HANDLE_TYPE(uint64, UINT64, uint64_t) | |
1069 HANDLE_TYPE(float32, FLOAT32, float) | |
1070 HANDLE_TYPE(float64, FLOAT64, double) | |
1071 #undef HANDLE_TYPE | |
1072 | |
1073 case schema::Type::TEXT: | |
1074 return builder.getPointerElement(index * ELEMENTS).getBlob<Text>(nullptr, 0 * BYTES); | |
1075 case schema::Type::DATA: | |
1076 return builder.getPointerElement(index * ELEMENTS).getBlob<Data>(nullptr, 0 * BYTES); | |
1077 | |
1078 case schema::Type::LIST: { | |
1079 ListSchema elementType = schema.getListElementType(); | |
1080 if (elementType.whichElementType() == schema::Type::STRUCT) { | |
1081 return DynamicList::Builder(elementType, | |
1082 builder.getPointerElement(index * ELEMENTS) | |
1083 .getStructList(structSizeFromSchema(elementType.getStructElementType()), | |
1084 nullptr)); | |
1085 } else { | |
1086 return DynamicList::Builder(elementType, | |
1087 builder.getPointerElement(index * ELEMENTS) | |
1088 .getList(elementSizeFor(elementType.whichElementType()), nullptr)); | |
1089 } | |
1090 } | |
1091 | |
1092 case schema::Type::STRUCT: | |
1093 return DynamicStruct::Builder(schema.getStructElementType(), | |
1094 builder.getStructElement(index * ELEMENTS)); | |
1095 | |
1096 case schema::Type::ENUM: | |
1097 return DynamicEnum(schema.getEnumElementType(), | |
1098 builder.getDataElement<uint16_t>(index * ELEMENTS)); | |
1099 | |
1100 case schema::Type::ANY_POINTER: | |
1101 KJ_FAIL_ASSERT("List(AnyPointer) not supported."); | |
1102 return nullptr; | |
1103 | |
1104 case schema::Type::INTERFACE: | |
1105 return DynamicCapability::Client(schema.getInterfaceElementType(), | |
1106 builder.getPointerElement(index * ELEMENTS).getCapability()); | |
1107 } | |
1108 | |
1109 return nullptr; | |
1110 } | |
1111 | |
1112 void DynamicList::Builder::set(uint index, const DynamicValue::Reader& value) { | |
1113 KJ_REQUIRE(index < size(), "List index out-of-bounds.") { | |
1114 return; | |
1115 } | |
1116 | |
1117 switch (schema.whichElementType()) { | |
1118 #define HANDLE_TYPE(name, discrim, typeName) \ | |
1119 case schema::Type::discrim: \ | |
1120 builder.setDataElement<typeName>(index * ELEMENTS, value.as<typeName>()); \ | |
1121 return; | |
1122 | |
1123 HANDLE_TYPE(void, VOID, Void) | |
1124 HANDLE_TYPE(bool, BOOL, bool) | |
1125 HANDLE_TYPE(int8, INT8, int8_t) | |
1126 HANDLE_TYPE(int16, INT16, int16_t) | |
1127 HANDLE_TYPE(int32, INT32, int32_t) | |
1128 HANDLE_TYPE(int64, INT64, int64_t) | |
1129 HANDLE_TYPE(uint8, UINT8, uint8_t) | |
1130 HANDLE_TYPE(uint16, UINT16, uint16_t) | |
1131 HANDLE_TYPE(uint32, UINT32, uint32_t) | |
1132 HANDLE_TYPE(uint64, UINT64, uint64_t) | |
1133 HANDLE_TYPE(float32, FLOAT32, float) | |
1134 HANDLE_TYPE(float64, FLOAT64, double) | |
1135 #undef HANDLE_TYPE | |
1136 | |
1137 case schema::Type::TEXT: | |
1138 builder.getPointerElement(index * ELEMENTS).setBlob<Text>(value.as<Text>()); | |
1139 return; | |
1140 case schema::Type::DATA: | |
1141 builder.getPointerElement(index * ELEMENTS).setBlob<Data>(value.as<Data>()); | |
1142 return; | |
1143 | |
1144 case schema::Type::LIST: { | |
1145 auto listValue = value.as<DynamicList>(); | |
1146 KJ_REQUIRE(listValue.getSchema() == schema.getListElementType(), "Value type mismatch.") { | |
1147 return; | |
1148 } | |
1149 builder.getPointerElement(index * ELEMENTS).setList(listValue.reader); | |
1150 return; | |
1151 } | |
1152 | |
1153 case schema::Type::STRUCT: { | |
1154 auto structValue = value.as<DynamicStruct>(); | |
1155 KJ_REQUIRE(structValue.getSchema() == schema.getStructElementType(), "Value type mismatch.") { | |
1156 return; | |
1157 } | |
1158 builder.getStructElement(index * ELEMENTS).copyContentFrom(structValue.reader); | |
1159 return; | |
1160 } | |
1161 | |
1162 case schema::Type::ENUM: { | |
1163 uint16_t rawValue; | |
1164 if (value.getType() == DynamicValue::TEXT) { | |
1165 // Convert from text. | |
1166 rawValue = schema.getEnumElementType().getEnumerantByName(value.as<Text>()).getOrdinal(); | |
1167 } else { | |
1168 DynamicEnum enumValue = value.as<DynamicEnum>(); | |
1169 KJ_REQUIRE(schema.getEnumElementType() == enumValue.getSchema(), | |
1170 "Type mismatch when using DynamicList::Builder::set().") { | |
1171 return; | |
1172 } | |
1173 rawValue = enumValue.getRaw(); | |
1174 } | |
1175 builder.setDataElement<uint16_t>(index * ELEMENTS, rawValue); | |
1176 return; | |
1177 } | |
1178 | |
1179 case schema::Type::ANY_POINTER: | |
1180 KJ_FAIL_ASSERT("List(AnyPointer) not supported.") { | |
1181 return; | |
1182 } | |
1183 | |
1184 case schema::Type::INTERFACE: { | |
1185 auto capValue = value.as<DynamicCapability>(); | |
1186 KJ_REQUIRE(capValue.getSchema().extends(schema.getInterfaceElementType()), | |
1187 "Value type mismatch.") { | |
1188 return; | |
1189 } | |
1190 builder.getPointerElement(index * ELEMENTS).setCapability(kj::mv(capValue.hook)); | |
1191 return; | |
1192 } | |
1193 } | |
1194 | |
1195 KJ_FAIL_REQUIRE("can't set element of unknown type", (uint)schema.whichElementType()) { | |
1196 return; | |
1197 } | |
1198 } | |
1199 | |
1200 DynamicValue::Builder DynamicList::Builder::init(uint index, uint size) { | |
1201 KJ_REQUIRE(index < this->size(), "List index out-of-bounds."); | |
1202 | |
1203 switch (schema.whichElementType()) { | |
1204 case schema::Type::VOID: | |
1205 case schema::Type::BOOL: | |
1206 case schema::Type::INT8: | |
1207 case schema::Type::INT16: | |
1208 case schema::Type::INT32: | |
1209 case schema::Type::INT64: | |
1210 case schema::Type::UINT8: | |
1211 case schema::Type::UINT16: | |
1212 case schema::Type::UINT32: | |
1213 case schema::Type::UINT64: | |
1214 case schema::Type::FLOAT32: | |
1215 case schema::Type::FLOAT64: | |
1216 case schema::Type::ENUM: | |
1217 case schema::Type::STRUCT: | |
1218 case schema::Type::INTERFACE: | |
1219 KJ_FAIL_REQUIRE("Expected a list or blob."); | |
1220 return nullptr; | |
1221 | |
1222 case schema::Type::TEXT: | |
1223 return builder.getPointerElement(index * ELEMENTS).initBlob<Text>(size * BYTES); | |
1224 | |
1225 case schema::Type::DATA: | |
1226 return builder.getPointerElement(index * ELEMENTS).initBlob<Data>(size * BYTES); | |
1227 | |
1228 case schema::Type::LIST: { | |
1229 auto elementType = schema.getListElementType(); | |
1230 | |
1231 if (elementType.whichElementType() == schema::Type::STRUCT) { | |
1232 return DynamicList::Builder(elementType, | |
1233 builder.getPointerElement(index * ELEMENTS) | |
1234 .initStructList(size * ELEMENTS, | |
1235 structSizeFromSchema(elementType.getStructElementType()))); | |
1236 } else { | |
1237 return DynamicList::Builder(elementType, | |
1238 builder.getPointerElement(index * ELEMENTS) | |
1239 .initList(elementSizeFor(elementType.whichElementType()), size * ELEMENTS)); | |
1240 } | |
1241 } | |
1242 | |
1243 case schema::Type::ANY_POINTER: { | |
1244 KJ_FAIL_ASSERT("List(AnyPointer) not supported."); | |
1245 return nullptr; | |
1246 } | |
1247 } | |
1248 | |
1249 return nullptr; | |
1250 } | |
1251 | |
1252 void DynamicList::Builder::adopt(uint index, Orphan<DynamicValue>&& orphan) { | |
1253 switch (schema.whichElementType()) { | |
1254 case schema::Type::VOID: | |
1255 case schema::Type::BOOL: | |
1256 case schema::Type::INT8: | |
1257 case schema::Type::INT16: | |
1258 case schema::Type::INT32: | |
1259 case schema::Type::INT64: | |
1260 case schema::Type::UINT8: | |
1261 case schema::Type::UINT16: | |
1262 case schema::Type::UINT32: | |
1263 case schema::Type::UINT64: | |
1264 case schema::Type::FLOAT32: | |
1265 case schema::Type::FLOAT64: | |
1266 case schema::Type::ENUM: | |
1267 set(index, orphan.getReader()); | |
1268 return; | |
1269 | |
1270 case schema::Type::TEXT: | |
1271 KJ_REQUIRE(orphan.getType() == DynamicValue::TEXT, "Value type mismatch."); | |
1272 builder.getPointerElement(index * ELEMENTS).adopt(kj::mv(orphan.builder)); | |
1273 return; | |
1274 | |
1275 case schema::Type::DATA: | |
1276 KJ_REQUIRE(orphan.getType() == DynamicValue::DATA, "Value type mismatch."); | |
1277 builder.getPointerElement(index * ELEMENTS).adopt(kj::mv(orphan.builder)); | |
1278 return; | |
1279 | |
1280 case schema::Type::LIST: { | |
1281 ListSchema elementType = schema.getListElementType(); | |
1282 KJ_REQUIRE(orphan.getType() == DynamicValue::LIST && orphan.listSchema == elementType, | |
1283 "Value type mismatch."); | |
1284 builder.getPointerElement(index * ELEMENTS).adopt(kj::mv(orphan.builder)); | |
1285 return; | |
1286 } | |
1287 | |
1288 case schema::Type::STRUCT: { | |
1289 auto elementType = schema.getStructElementType(); | |
1290 KJ_REQUIRE(orphan.getType() == DynamicValue::STRUCT && orphan.structSchema == elementType, | |
1291 "Value type mismatch."); | |
1292 builder.getStructElement(index * ELEMENTS).transferContentFrom( | |
1293 orphan.builder.asStruct(structSizeFromSchema(elementType))); | |
1294 return; | |
1295 } | |
1296 | |
1297 case schema::Type::ANY_POINTER: | |
1298 KJ_FAIL_ASSERT("List(AnyPointer) not supported."); | |
1299 | |
1300 case schema::Type::INTERFACE: { | |
1301 auto elementType = schema.getInterfaceElementType(); | |
1302 KJ_REQUIRE(orphan.getType() == DynamicValue::CAPABILITY && | |
1303 orphan.interfaceSchema.extends(elementType), | |
1304 "Value type mismatch."); | |
1305 builder.getPointerElement(index * ELEMENTS).adopt(kj::mv(orphan.builder)); | |
1306 return; | |
1307 } | |
1308 } | |
1309 | |
1310 KJ_UNREACHABLE; | |
1311 } | |
1312 | |
1313 Orphan<DynamicValue> DynamicList::Builder::disown(uint index) { | |
1314 switch (schema.whichElementType()) { | |
1315 case schema::Type::VOID: | |
1316 case schema::Type::BOOL: | |
1317 case schema::Type::INT8: | |
1318 case schema::Type::INT16: | |
1319 case schema::Type::INT32: | |
1320 case schema::Type::INT64: | |
1321 case schema::Type::UINT8: | |
1322 case schema::Type::UINT16: | |
1323 case schema::Type::UINT32: | |
1324 case schema::Type::UINT64: | |
1325 case schema::Type::FLOAT32: | |
1326 case schema::Type::FLOAT64: | |
1327 case schema::Type::ENUM: { | |
1328 auto result = Orphan<DynamicValue>(operator[](index), _::OrphanBuilder()); | |
1329 switch (elementSizeFor(schema.whichElementType())) { | |
1330 case ElementSize::VOID: break; | |
1331 case ElementSize::BIT: builder.setDataElement<bool>(index * ELEMENTS, false); break; | |
1332 case ElementSize::BYTE: builder.setDataElement<uint8_t>(index * ELEMENTS, 0); break; | |
1333 case ElementSize::TWO_BYTES: builder.setDataElement<uint16_t>(index * ELEMENTS, 0); break; | |
1334 case ElementSize::FOUR_BYTES: builder.setDataElement<uint32_t>(index * ELEMENTS, 0); break; | |
1335 case ElementSize::EIGHT_BYTES: builder.setDataElement<uint64_t>(index * ELEMENTS, 0);break; | |
1336 | |
1337 case ElementSize::POINTER: | |
1338 case ElementSize::INLINE_COMPOSITE: | |
1339 KJ_UNREACHABLE; | |
1340 } | |
1341 return kj::mv(result); | |
1342 } | |
1343 | |
1344 case schema::Type::TEXT: | |
1345 case schema::Type::DATA: | |
1346 case schema::Type::LIST: | |
1347 case schema::Type::ANY_POINTER: | |
1348 case schema::Type::INTERFACE: { | |
1349 auto value = operator[](index); | |
1350 return Orphan<DynamicValue>(value, builder.getPointerElement(index * ELEMENTS).disown()); | |
1351 } | |
1352 | |
1353 case schema::Type::STRUCT: { | |
1354 // We have to make a copy. | |
1355 Orphan<DynamicStruct> result = | |
1356 Orphanage::getForMessageContaining(*this).newOrphan(schema.getStructElementType()); | |
1357 auto element = builder.getStructElement(index * ELEMENTS); | |
1358 result.get().builder.transferContentFrom(element); | |
1359 element.clearAll(); | |
1360 return kj::mv(result); | |
1361 } | |
1362 } | |
1363 KJ_UNREACHABLE; | |
1364 } | |
1365 | |
1366 void DynamicList::Builder::copyFrom(std::initializer_list<DynamicValue::Reader> value) { | |
1367 KJ_REQUIRE(value.size() == size(), "DynamicList::copyFrom() argument had different size."); | |
1368 uint i = 0; | |
1369 for (auto element: value) { | |
1370 set(i++, element); | |
1371 } | |
1372 } | |
1373 | |
1374 DynamicList::Reader DynamicList::Builder::asReader() const { | |
1375 return DynamicList::Reader(schema, builder.asReader()); | |
1376 } | |
1377 | |
1378 // ======================================================================================= | |
1379 | |
1380 DynamicValue::Reader::Reader(ConstSchema constant): type(VOID) { | |
1381 auto type = constant.getType(); | |
1382 auto value = constant.getProto().getConst().getValue(); | |
1383 switch (type.which()) { | |
1384 case schema::Type::VOID: *this = capnp::VOID; break; | |
1385 case schema::Type::BOOL: *this = value.getBool(); break; | |
1386 case schema::Type::INT8: *this = value.getInt8(); break; | |
1387 case schema::Type::INT16: *this = value.getInt16(); break; | |
1388 case schema::Type::INT32: *this = value.getInt32(); break; | |
1389 case schema::Type::INT64: *this = value.getInt64(); break; | |
1390 case schema::Type::UINT8: *this = value.getUint8(); break; | |
1391 case schema::Type::UINT16: *this = value.getUint16(); break; | |
1392 case schema::Type::UINT32: *this = value.getUint32(); break; | |
1393 case schema::Type::UINT64: *this = value.getUint64(); break; | |
1394 case schema::Type::FLOAT32: *this = value.getFloat32(); break; | |
1395 case schema::Type::FLOAT64: *this = value.getFloat64(); break; | |
1396 case schema::Type::TEXT: *this = value.getText(); break; | |
1397 case schema::Type::DATA: *this = value.getData(); break; | |
1398 | |
1399 case schema::Type::ENUM: | |
1400 *this = DynamicEnum(type.asEnum(), value.getEnum()); | |
1401 break; | |
1402 | |
1403 case schema::Type::STRUCT: | |
1404 *this = value.getStruct().getAs<DynamicStruct>(type.asStruct()); | |
1405 break; | |
1406 | |
1407 case schema::Type::LIST: | |
1408 *this = value.getList().getAs<DynamicList>(type.asList()); | |
1409 break; | |
1410 | |
1411 case schema::Type::ANY_POINTER: | |
1412 *this = value.getAnyPointer(); | |
1413 break; | |
1414 | |
1415 case schema::Type::INTERFACE: | |
1416 KJ_FAIL_ASSERT("Constants can't have interface type."); | |
1417 } | |
1418 } | |
1419 | |
1420 DynamicValue::Reader::Reader(const Reader& other) { | |
1421 switch (other.type) { | |
1422 case UNKNOWN: | |
1423 case VOID: | |
1424 case BOOL: | |
1425 case INT: | |
1426 case UINT: | |
1427 case FLOAT: | |
1428 case TEXT: | |
1429 case DATA: | |
1430 case LIST: | |
1431 case ENUM: | |
1432 case STRUCT: | |
1433 case ANY_POINTER: | |
1434 static_assert(kj::canMemcpy<Text::Reader>() && | |
1435 kj::canMemcpy<Data::Reader>() && | |
1436 kj::canMemcpy<DynamicList::Reader>() && | |
1437 kj::canMemcpy<DynamicEnum>() && | |
1438 kj::canMemcpy<DynamicStruct::Reader>() && | |
1439 kj::canMemcpy<AnyPointer::Reader>(), | |
1440 "Assumptions here don't hold."); | |
1441 break; | |
1442 | |
1443 case CAPABILITY: | |
1444 type = CAPABILITY; | |
1445 kj::ctor(capabilityValue, other.capabilityValue); | |
1446 return; | |
1447 } | |
1448 | |
1449 memcpy(this, &other, sizeof(*this)); | |
1450 } | |
1451 DynamicValue::Reader::Reader(Reader&& other) noexcept { | |
1452 switch (other.type) { | |
1453 case UNKNOWN: | |
1454 case VOID: | |
1455 case BOOL: | |
1456 case INT: | |
1457 case UINT: | |
1458 case FLOAT: | |
1459 case TEXT: | |
1460 case DATA: | |
1461 case LIST: | |
1462 case ENUM: | |
1463 case STRUCT: | |
1464 case ANY_POINTER: | |
1465 static_assert(kj::canMemcpy<Text::Reader>() && | |
1466 kj::canMemcpy<Data::Reader>() && | |
1467 kj::canMemcpy<DynamicList::Reader>() && | |
1468 kj::canMemcpy<DynamicEnum>() && | |
1469 kj::canMemcpy<DynamicStruct::Reader>() && | |
1470 kj::canMemcpy<AnyPointer::Reader>(), | |
1471 "Assumptions here don't hold."); | |
1472 break; | |
1473 | |
1474 case CAPABILITY: | |
1475 type = CAPABILITY; | |
1476 kj::ctor(capabilityValue, kj::mv(other.capabilityValue)); | |
1477 return; | |
1478 } | |
1479 | |
1480 memcpy(this, &other, sizeof(*this)); | |
1481 } | |
1482 DynamicValue::Reader::~Reader() noexcept(false) { | |
1483 if (type == CAPABILITY) { | |
1484 kj::dtor(capabilityValue); | |
1485 } | |
1486 } | |
1487 | |
1488 DynamicValue::Reader& DynamicValue::Reader::operator=(const Reader& other) { | |
1489 if (type == CAPABILITY) { | |
1490 kj::dtor(capabilityValue); | |
1491 } | |
1492 kj::ctor(*this, other); | |
1493 return *this; | |
1494 } | |
1495 DynamicValue::Reader& DynamicValue::Reader::operator=(Reader&& other) { | |
1496 if (type == CAPABILITY) { | |
1497 kj::dtor(capabilityValue); | |
1498 } | |
1499 kj::ctor(*this, kj::mv(other)); | |
1500 return *this; | |
1501 } | |
1502 | |
1503 DynamicValue::Builder::Builder(Builder& other) { | |
1504 switch (other.type) { | |
1505 case UNKNOWN: | |
1506 case VOID: | |
1507 case BOOL: | |
1508 case INT: | |
1509 case UINT: | |
1510 case FLOAT: | |
1511 case TEXT: | |
1512 case DATA: | |
1513 case LIST: | |
1514 case ENUM: | |
1515 case STRUCT: | |
1516 case ANY_POINTER: | |
1517 // Unfortunately canMemcpy() doesn't work on these types due to the use of | |
1518 // DisallowConstCopy, but __has_trivial_destructor should detect if any of these types | |
1519 // become non-trivial. | |
1520 static_assert(__has_trivial_destructor(Text::Builder) && | |
1521 __has_trivial_destructor(Data::Builder) && | |
1522 __has_trivial_destructor(DynamicList::Builder) && | |
1523 __has_trivial_destructor(DynamicEnum) && | |
1524 __has_trivial_destructor(DynamicStruct::Builder) && | |
1525 __has_trivial_destructor(AnyPointer::Builder), | |
1526 "Assumptions here don't hold."); | |
1527 break; | |
1528 | |
1529 case CAPABILITY: | |
1530 type = CAPABILITY; | |
1531 kj::ctor(capabilityValue, other.capabilityValue); | |
1532 return; | |
1533 } | |
1534 | |
1535 memcpy(this, &other, sizeof(*this)); | |
1536 } | |
1537 DynamicValue::Builder::Builder(Builder&& other) noexcept { | |
1538 switch (other.type) { | |
1539 case UNKNOWN: | |
1540 case VOID: | |
1541 case BOOL: | |
1542 case INT: | |
1543 case UINT: | |
1544 case FLOAT: | |
1545 case TEXT: | |
1546 case DATA: | |
1547 case LIST: | |
1548 case ENUM: | |
1549 case STRUCT: | |
1550 case ANY_POINTER: | |
1551 // Unfortunately __has_trivial_copy doesn't work on these types due to the use of | |
1552 // DisallowConstCopy, but __has_trivial_destructor should detect if any of these types | |
1553 // become non-trivial. | |
1554 static_assert(__has_trivial_destructor(Text::Builder) && | |
1555 __has_trivial_destructor(Data::Builder) && | |
1556 __has_trivial_destructor(DynamicList::Builder) && | |
1557 __has_trivial_destructor(DynamicEnum) && | |
1558 __has_trivial_destructor(DynamicStruct::Builder) && | |
1559 __has_trivial_destructor(AnyPointer::Builder), | |
1560 "Assumptions here don't hold."); | |
1561 break; | |
1562 | |
1563 case CAPABILITY: | |
1564 type = CAPABILITY; | |
1565 kj::ctor(capabilityValue, kj::mv(other.capabilityValue)); | |
1566 return; | |
1567 } | |
1568 | |
1569 memcpy(this, &other, sizeof(*this)); | |
1570 } | |
1571 DynamicValue::Builder::~Builder() noexcept(false) { | |
1572 if (type == CAPABILITY) { | |
1573 kj::dtor(capabilityValue); | |
1574 } | |
1575 } | |
1576 | |
1577 DynamicValue::Builder& DynamicValue::Builder::operator=(Builder& other) { | |
1578 if (type == CAPABILITY) { | |
1579 kj::dtor(capabilityValue); | |
1580 } | |
1581 kj::ctor(*this, other); | |
1582 return *this; | |
1583 } | |
1584 DynamicValue::Builder& DynamicValue::Builder::operator=(Builder&& other) { | |
1585 if (type == CAPABILITY) { | |
1586 kj::dtor(capabilityValue); | |
1587 } | |
1588 kj::ctor(*this, kj::mv(other)); | |
1589 return *this; | |
1590 } | |
1591 | |
1592 DynamicValue::Reader DynamicValue::Builder::asReader() const { | |
1593 switch (type) { | |
1594 case UNKNOWN: return Reader(); | |
1595 case VOID: return Reader(voidValue); | |
1596 case BOOL: return Reader(boolValue); | |
1597 case INT: return Reader(intValue); | |
1598 case UINT: return Reader(uintValue); | |
1599 case FLOAT: return Reader(floatValue); | |
1600 case TEXT: return Reader(textValue.asReader()); | |
1601 case DATA: return Reader(dataValue.asReader()); | |
1602 case LIST: return Reader(listValue.asReader()); | |
1603 case ENUM: return Reader(enumValue); | |
1604 case STRUCT: return Reader(structValue.asReader()); | |
1605 case CAPABILITY: return Reader(capabilityValue); | |
1606 case ANY_POINTER: return Reader(anyPointerValue.asReader()); | |
1607 } | |
1608 KJ_FAIL_ASSERT("Missing switch case."); | |
1609 return Reader(); | |
1610 } | |
1611 | |
1612 DynamicValue::Pipeline::Pipeline(Pipeline&& other) noexcept: type(other.type) { | |
1613 switch (type) { | |
1614 case UNKNOWN: break; | |
1615 case STRUCT: kj::ctor(structValue, kj::mv(other.structValue)); break; | |
1616 case CAPABILITY: kj::ctor(capabilityValue, kj::mv(other.capabilityValue)); break; | |
1617 default: | |
1618 KJ_LOG(ERROR, "Unexpected pipeline type.", (uint)type); | |
1619 type = UNKNOWN; | |
1620 break; | |
1621 } | |
1622 } | |
1623 DynamicValue::Pipeline& DynamicValue::Pipeline::operator=(Pipeline&& other) { | |
1624 kj::dtor(*this); | |
1625 kj::ctor(*this, kj::mv(other)); | |
1626 return *this; | |
1627 } | |
1628 DynamicValue::Pipeline::~Pipeline() noexcept(false) { | |
1629 switch (type) { | |
1630 case UNKNOWN: break; | |
1631 case STRUCT: kj::dtor(structValue); break; | |
1632 case CAPABILITY: kj::dtor(capabilityValue); break; | |
1633 default: | |
1634 KJ_FAIL_ASSERT("Unexpected pipeline type.", (uint)type) { type = UNKNOWN; break; } | |
1635 break; | |
1636 } | |
1637 } | |
1638 | |
1639 namespace { | |
1640 | |
1641 template <typename T> | |
1642 T signedToUnsigned(long long value) { | |
1643 KJ_REQUIRE(value >= 0 && T(value) == value, "Value out-of-range for requested type.", value) { | |
1644 // Use it anyway. | |
1645 break; | |
1646 } | |
1647 return value; | |
1648 } | |
1649 | |
1650 template <> | |
1651 uint64_t signedToUnsigned<uint64_t>(long long value) { | |
1652 KJ_REQUIRE(value >= 0, "Value out-of-range for requested type.", value) { | |
1653 // Use it anyway. | |
1654 break; | |
1655 } | |
1656 return value; | |
1657 } | |
1658 | |
1659 template <typename T> | |
1660 T unsignedToSigned(unsigned long long value) { | |
1661 KJ_REQUIRE(T(value) >= 0 && (unsigned long long)T(value) == value, | |
1662 "Value out-of-range for requested type.", value) { | |
1663 // Use it anyway. | |
1664 break; | |
1665 } | |
1666 return value; | |
1667 } | |
1668 | |
1669 template <> | |
1670 int64_t unsignedToSigned<int64_t>(unsigned long long value) { | |
1671 KJ_REQUIRE(int64_t(value) >= 0, "Value out-of-range for requested type.", value) { | |
1672 // Use it anyway. | |
1673 break; | |
1674 } | |
1675 return value; | |
1676 } | |
1677 | |
1678 template <typename T, typename U> | |
1679 T checkRoundTrip(U value) { | |
1680 KJ_REQUIRE(T(value) == value, "Value out-of-range for requested type.", value) { | |
1681 // Use it anyway. | |
1682 break; | |
1683 } | |
1684 return value; | |
1685 } | |
1686 | |
1687 } // namespace | |
1688 | |
1689 #define HANDLE_NUMERIC_TYPE(typeName, ifInt, ifUint, ifFloat) \ | |
1690 typeName DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \ | |
1691 switch (reader.type) { \ | |
1692 case INT: \ | |
1693 return ifInt<typeName>(reader.intValue); \ | |
1694 case UINT: \ | |
1695 return ifUint<typeName>(reader.uintValue); \ | |
1696 case FLOAT: \ | |
1697 return ifFloat<typeName>(reader.floatValue); \ | |
1698 default: \ | |
1699 KJ_FAIL_REQUIRE("Value type mismatch.") { \ | |
1700 return 0; \ | |
1701 } \ | |
1702 } \ | |
1703 } \ | |
1704 typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \ | |
1705 switch (builder.type) { \ | |
1706 case INT: \ | |
1707 return ifInt<typeName>(builder.intValue); \ | |
1708 case UINT: \ | |
1709 return ifUint<typeName>(builder.uintValue); \ | |
1710 case FLOAT: \ | |
1711 return ifFloat<typeName>(builder.floatValue); \ | |
1712 default: \ | |
1713 KJ_FAIL_REQUIRE("Value type mismatch.") { \ | |
1714 return 0; \ | |
1715 } \ | |
1716 } \ | |
1717 } | |
1718 | |
1719 HANDLE_NUMERIC_TYPE(int8_t, checkRoundTrip, unsignedToSigned, checkRoundTrip) | |
1720 HANDLE_NUMERIC_TYPE(int16_t, checkRoundTrip, unsignedToSigned, checkRoundTrip) | |
1721 HANDLE_NUMERIC_TYPE(int32_t, checkRoundTrip, unsignedToSigned, checkRoundTrip) | |
1722 HANDLE_NUMERIC_TYPE(int64_t, kj::implicitCast, unsignedToSigned, checkRoundTrip) | |
1723 HANDLE_NUMERIC_TYPE(uint8_t, signedToUnsigned, checkRoundTrip, checkRoundTrip) | |
1724 HANDLE_NUMERIC_TYPE(uint16_t, signedToUnsigned, checkRoundTrip, checkRoundTrip) | |
1725 HANDLE_NUMERIC_TYPE(uint32_t, signedToUnsigned, checkRoundTrip, checkRoundTrip) | |
1726 HANDLE_NUMERIC_TYPE(uint64_t, signedToUnsigned, kj::implicitCast, checkRoundTrip) | |
1727 HANDLE_NUMERIC_TYPE(float, kj::implicitCast, kj::implicitCast, kj::implicitCast) | |
1728 HANDLE_NUMERIC_TYPE(double, kj::implicitCast, kj::implicitCast, kj::implicitCast) | |
1729 | |
1730 #undef HANDLE_NUMERIC_TYPE | |
1731 | |
1732 #define HANDLE_TYPE(name, discrim, typeName) \ | |
1733 ReaderFor<typeName> DynamicValue::Reader::AsImpl<typeName>::apply(const Reader& reader) { \ | |
1734 KJ_REQUIRE(reader.type == discrim, "Value type mismatch.") { \ | |
1735 return ReaderFor<typeName>(); \ | |
1736 } \ | |
1737 return reader.name##Value; \ | |
1738 } \ | |
1739 BuilderFor<typeName> DynamicValue::Builder::AsImpl<typeName>::apply(Builder& builder) { \ | |
1740 KJ_REQUIRE(builder.type == discrim, "Value type mismatch."); \ | |
1741 return builder.name##Value; \ | |
1742 } | |
1743 | |
1744 //HANDLE_TYPE(void, VOID, Void) | |
1745 HANDLE_TYPE(bool, BOOL, bool) | |
1746 | |
1747 HANDLE_TYPE(text, TEXT, Text) | |
1748 HANDLE_TYPE(list, LIST, DynamicList) | |
1749 HANDLE_TYPE(struct, STRUCT, DynamicStruct) | |
1750 HANDLE_TYPE(enum, ENUM, DynamicEnum) | |
1751 HANDLE_TYPE(anyPointer, ANY_POINTER, AnyPointer) | |
1752 | |
1753 #undef HANDLE_TYPE | |
1754 | |
1755 PipelineFor<DynamicStruct> DynamicValue::Pipeline::AsImpl<DynamicStruct>::apply( | |
1756 Pipeline& pipeline) { | |
1757 KJ_REQUIRE(pipeline.type == STRUCT, "Pipeline type mismatch."); | |
1758 return kj::mv(pipeline.structValue); | |
1759 } | |
1760 | |
1761 ReaderFor<DynamicCapability> DynamicValue::Reader::AsImpl<DynamicCapability>::apply( | |
1762 const Reader& reader) { | |
1763 KJ_REQUIRE(reader.type == CAPABILITY, "Value type mismatch.") { | |
1764 return DynamicCapability::Client(); | |
1765 } | |
1766 return reader.capabilityValue; | |
1767 } | |
1768 BuilderFor<DynamicCapability> DynamicValue::Builder::AsImpl<DynamicCapability>::apply( | |
1769 Builder& builder) { | |
1770 KJ_REQUIRE(builder.type == CAPABILITY, "Value type mismatch.") { | |
1771 return DynamicCapability::Client(); | |
1772 } | |
1773 return builder.capabilityValue; | |
1774 } | |
1775 PipelineFor<DynamicCapability> DynamicValue::Pipeline::AsImpl<DynamicCapability>::apply( | |
1776 Pipeline& pipeline) { | |
1777 KJ_REQUIRE(pipeline.type == CAPABILITY, "Pipeline type mismatch.") { | |
1778 return DynamicCapability::Client(); | |
1779 } | |
1780 return kj::mv(pipeline.capabilityValue); | |
1781 } | |
1782 | |
1783 Data::Reader DynamicValue::Reader::AsImpl<Data>::apply(const Reader& reader) { | |
1784 if (reader.type == TEXT) { | |
1785 // Coerce text to data. | |
1786 return reader.textValue.asBytes(); | |
1787 } | |
1788 KJ_REQUIRE(reader.type == DATA, "Value type mismatch.") { | |
1789 return Data::Reader(); | |
1790 } | |
1791 return reader.dataValue; | |
1792 } | |
1793 Data::Builder DynamicValue::Builder::AsImpl<Data>::apply(Builder& builder) { | |
1794 if (builder.type == TEXT) { | |
1795 // Coerce text to data. | |
1796 return builder.textValue.asBytes(); | |
1797 } | |
1798 KJ_REQUIRE(builder.type == DATA, "Value type mismatch.") { | |
1799 return BuilderFor<Data>(); | |
1800 } | |
1801 return builder.dataValue; | |
1802 } | |
1803 | |
1804 // As in the header, HANDLE_TYPE(void, VOID, Void) crashes GCC 4.7. | |
1805 Void DynamicValue::Reader::AsImpl<Void>::apply(const Reader& reader) { | |
1806 KJ_REQUIRE(reader.type == VOID, "Value type mismatch.") { | |
1807 return Void(); | |
1808 } | |
1809 return reader.voidValue; | |
1810 } | |
1811 Void DynamicValue::Builder::AsImpl<Void>::apply(Builder& builder) { | |
1812 KJ_REQUIRE(builder.type == VOID, "Value type mismatch.") { | |
1813 return Void(); | |
1814 } | |
1815 return builder.voidValue; | |
1816 } | |
1817 | |
1818 // ======================================================================================= | |
1819 | |
1820 namespace _ { // private | |
1821 | |
1822 DynamicStruct::Reader PointerHelpers<DynamicStruct, Kind::OTHER>::getDynamic( | |
1823 PointerReader reader, StructSchema schema) { | |
1824 KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), | |
1825 "Cannot form pointer to group type."); | |
1826 return DynamicStruct::Reader(schema, reader.getStruct(nullptr)); | |
1827 } | |
1828 DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::OTHER>::getDynamic( | |
1829 PointerBuilder builder, StructSchema schema) { | |
1830 KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), | |
1831 "Cannot form pointer to group type."); | |
1832 return DynamicStruct::Builder(schema, builder.getStruct( | |
1833 structSizeFromSchema(schema), nullptr)); | |
1834 } | |
1835 void PointerHelpers<DynamicStruct, Kind::OTHER>::set( | |
1836 PointerBuilder builder, const DynamicStruct::Reader& value) { | |
1837 KJ_REQUIRE(!value.schema.getProto().getStruct().getIsGroup(), | |
1838 "Cannot form pointer to group type."); | |
1839 builder.setStruct(value.reader); | |
1840 } | |
1841 DynamicStruct::Builder PointerHelpers<DynamicStruct, Kind::OTHER>::init( | |
1842 PointerBuilder builder, StructSchema schema) { | |
1843 KJ_REQUIRE(!schema.getProto().getStruct().getIsGroup(), | |
1844 "Cannot form pointer to group type."); | |
1845 return DynamicStruct::Builder(schema, | |
1846 builder.initStruct(structSizeFromSchema(schema))); | |
1847 } | |
1848 | |
1849 DynamicList::Reader PointerHelpers<DynamicList, Kind::OTHER>::getDynamic( | |
1850 PointerReader reader, ListSchema schema) { | |
1851 return DynamicList::Reader(schema, | |
1852 reader.getList(elementSizeFor(schema.whichElementType()), nullptr)); | |
1853 } | |
1854 DynamicList::Builder PointerHelpers<DynamicList, Kind::OTHER>::getDynamic( | |
1855 PointerBuilder builder, ListSchema schema) { | |
1856 if (schema.whichElementType() == schema::Type::STRUCT) { | |
1857 return DynamicList::Builder(schema, | |
1858 builder.getStructList( | |
1859 structSizeFromSchema(schema.getStructElementType()), | |
1860 nullptr)); | |
1861 } else { | |
1862 return DynamicList::Builder(schema, | |
1863 builder.getList(elementSizeFor(schema.whichElementType()), nullptr)); | |
1864 } | |
1865 } | |
1866 void PointerHelpers<DynamicList, Kind::OTHER>::set( | |
1867 PointerBuilder builder, const DynamicList::Reader& value) { | |
1868 builder.setList(value.reader); | |
1869 } | |
1870 DynamicList::Builder PointerHelpers<DynamicList, Kind::OTHER>::init( | |
1871 PointerBuilder builder, ListSchema schema, uint size) { | |
1872 if (schema.whichElementType() == schema::Type::STRUCT) { | |
1873 return DynamicList::Builder(schema, | |
1874 builder.initStructList(size * ELEMENTS, | |
1875 structSizeFromSchema(schema.getStructElementType()))); | |
1876 } else { | |
1877 return DynamicList::Builder(schema, | |
1878 builder.initList(elementSizeFor(schema.whichElementType()), size * ELEMENTS)); | |
1879 } | |
1880 } | |
1881 | |
1882 DynamicCapability::Client PointerHelpers<DynamicCapability, Kind::OTHER>::getDynamic( | |
1883 PointerReader reader, InterfaceSchema schema) { | |
1884 return DynamicCapability::Client(schema, reader.getCapability()); | |
1885 } | |
1886 DynamicCapability::Client PointerHelpers<DynamicCapability, Kind::OTHER>::getDynamic( | |
1887 PointerBuilder builder, InterfaceSchema schema) { | |
1888 return DynamicCapability::Client(schema, builder.getCapability()); | |
1889 } | |
1890 void PointerHelpers<DynamicCapability, Kind::OTHER>::set( | |
1891 PointerBuilder builder, DynamicCapability::Client& value) { | |
1892 builder.setCapability(value.hook->addRef()); | |
1893 } | |
1894 void PointerHelpers<DynamicCapability, Kind::OTHER>::set( | |
1895 PointerBuilder builder, DynamicCapability::Client&& value) { | |
1896 builder.setCapability(kj::mv(value.hook)); | |
1897 } | |
1898 | |
1899 } // namespace _ (private) | |
1900 | |
1901 template <> | |
1902 void AnyPointer::Builder::adopt<DynamicValue>(Orphan<DynamicValue>&& orphan) { | |
1903 switch (orphan.getType()) { | |
1904 case DynamicValue::UNKNOWN: | |
1905 case DynamicValue::VOID: | |
1906 case DynamicValue::BOOL: | |
1907 case DynamicValue::INT: | |
1908 case DynamicValue::UINT: | |
1909 case DynamicValue::FLOAT: | |
1910 case DynamicValue::ENUM: | |
1911 KJ_FAIL_REQUIRE("AnyPointer cannot adopt primitive (non-object) value."); | |
1912 | |
1913 case DynamicValue::STRUCT: | |
1914 case DynamicValue::LIST: | |
1915 case DynamicValue::TEXT: | |
1916 case DynamicValue::DATA: | |
1917 case DynamicValue::CAPABILITY: | |
1918 case DynamicValue::ANY_POINTER: | |
1919 builder.adopt(kj::mv(orphan.builder)); | |
1920 break; | |
1921 } | |
1922 } | |
1923 | |
1924 template <> | |
1925 DynamicStruct::Builder Orphan<AnyPointer>::getAs<DynamicStruct>(StructSchema schema) { | |
1926 return DynamicStruct::Builder(schema, builder.asStruct(structSizeFromSchema(schema))); | |
1927 } | |
1928 template <> | |
1929 DynamicStruct::Reader Orphan<AnyPointer>::getAsReader<DynamicStruct>(StructSchema schema) const { | |
1930 return DynamicStruct::Reader(schema, builder.asStructReader(structSizeFromSchema(schema))); | |
1931 } | |
1932 template <> | |
1933 Orphan<DynamicStruct> Orphan<AnyPointer>::releaseAs<DynamicStruct>(StructSchema schema) { | |
1934 return Orphan<DynamicStruct>(schema, kj::mv(builder)); | |
1935 } | |
1936 | |
1937 template <> | |
1938 DynamicList::Builder Orphan<AnyPointer>::getAs<DynamicList>(ListSchema schema) { | |
1939 if (schema.whichElementType() == schema::Type::STRUCT) { | |
1940 return DynamicList::Builder(schema, builder.asStructList( | |
1941 structSizeFromSchema(schema.getStructElementType()))); | |
1942 } else { | |
1943 return DynamicList::Builder(schema, builder.asList(elementSizeFor(schema.whichElementType()))); | |
1944 } | |
1945 } | |
1946 template <> | |
1947 DynamicList::Reader Orphan<AnyPointer>::getAsReader<DynamicList>(ListSchema schema) const { | |
1948 return DynamicList::Reader(schema, builder.asListReader( | |
1949 elementSizeFor(schema.whichElementType()))); | |
1950 } | |
1951 template <> | |
1952 Orphan<DynamicList> Orphan<AnyPointer>::releaseAs<DynamicList>(ListSchema schema) { | |
1953 return Orphan<DynamicList>(schema, kj::mv(builder)); | |
1954 } | |
1955 | |
1956 template <> | |
1957 DynamicCapability::Client Orphan<AnyPointer>::getAs<DynamicCapability>(InterfaceSchema schema) { | |
1958 return DynamicCapability::Client(schema, builder.asCapability()); | |
1959 } | |
1960 template <> | |
1961 DynamicCapability::Client Orphan<AnyPointer>::getAsReader<DynamicCapability>( | |
1962 InterfaceSchema schema) const { | |
1963 return DynamicCapability::Client(schema, builder.asCapability()); | |
1964 } | |
1965 template <> | |
1966 Orphan<DynamicCapability> Orphan<AnyPointer>::releaseAs<DynamicCapability>( | |
1967 InterfaceSchema schema) { | |
1968 return Orphan<DynamicCapability>(schema, kj::mv(builder)); | |
1969 } | |
1970 | |
1971 // ------------------------------------------------------------------- | |
1972 | |
1973 Orphan<DynamicStruct> Orphanage::newOrphan(StructSchema schema) const { | |
1974 return Orphan<DynamicStruct>( | |
1975 schema, _::OrphanBuilder::initStruct(arena, capTable, structSizeFromSchema(schema))); | |
1976 } | |
1977 | |
1978 Orphan<DynamicList> Orphanage::newOrphan(ListSchema schema, uint size) const { | |
1979 if (schema.whichElementType() == schema::Type::STRUCT) { | |
1980 return Orphan<DynamicList>(schema, _::OrphanBuilder::initStructList( | |
1981 arena, capTable, size * ELEMENTS, structSizeFromSchema(schema.getStructElementType()))); | |
1982 } else { | |
1983 return Orphan<DynamicList>(schema, _::OrphanBuilder::initList( | |
1984 arena, capTable, size * ELEMENTS, elementSizeFor(schema.whichElementType()))); | |
1985 } | |
1986 } | |
1987 | |
1988 DynamicStruct::Builder Orphan<DynamicStruct>::get() { | |
1989 return DynamicStruct::Builder(schema, builder.asStruct(structSizeFromSchema(schema))); | |
1990 } | |
1991 | |
1992 DynamicStruct::Reader Orphan<DynamicStruct>::getReader() const { | |
1993 return DynamicStruct::Reader(schema, builder.asStructReader(structSizeFromSchema(schema))); | |
1994 } | |
1995 | |
1996 DynamicList::Builder Orphan<DynamicList>::get() { | |
1997 if (schema.whichElementType() == schema::Type::STRUCT) { | |
1998 return DynamicList::Builder( | |
1999 schema, builder.asStructList(structSizeFromSchema(schema.getStructElementType()))); | |
2000 } else { | |
2001 return DynamicList::Builder( | |
2002 schema, builder.asList(elementSizeFor(schema.whichElementType()))); | |
2003 } | |
2004 } | |
2005 | |
2006 DynamicList::Reader Orphan<DynamicList>::getReader() const { | |
2007 return DynamicList::Reader( | |
2008 schema, builder.asListReader(elementSizeFor(schema.whichElementType()))); | |
2009 } | |
2010 | |
2011 DynamicCapability::Client Orphan<DynamicCapability>::get() { | |
2012 return DynamicCapability::Client(schema, builder.asCapability()); | |
2013 } | |
2014 | |
2015 DynamicCapability::Client Orphan<DynamicCapability>::getReader() const { | |
2016 return DynamicCapability::Client(schema, builder.asCapability()); | |
2017 } | |
2018 | |
2019 Orphan<DynamicValue>::Orphan(DynamicValue::Builder value, _::OrphanBuilder&& builder) | |
2020 : type(value.getType()), builder(kj::mv(builder)) { | |
2021 switch (type) { | |
2022 case DynamicValue::UNKNOWN: break; | |
2023 case DynamicValue::VOID: voidValue = value.voidValue; break; | |
2024 case DynamicValue::BOOL: boolValue = value.boolValue; break; | |
2025 case DynamicValue::INT: intValue = value.intValue; break; | |
2026 case DynamicValue::UINT: uintValue = value.uintValue; break; | |
2027 case DynamicValue::FLOAT: floatValue = value.floatValue; break; | |
2028 case DynamicValue::ENUM: enumValue = value.enumValue; break; | |
2029 | |
2030 case DynamicValue::TEXT: break; | |
2031 case DynamicValue::DATA: break; | |
2032 case DynamicValue::LIST: listSchema = value.listValue.getSchema(); break; | |
2033 case DynamicValue::STRUCT: structSchema = value.structValue.getSchema(); break; | |
2034 case DynamicValue::CAPABILITY: interfaceSchema = value.capabilityValue.getSchema(); break; | |
2035 case DynamicValue::ANY_POINTER: break; | |
2036 } | |
2037 } | |
2038 | |
2039 DynamicValue::Builder Orphan<DynamicValue>::get() { | |
2040 switch (type) { | |
2041 case DynamicValue::UNKNOWN: return nullptr; | |
2042 case DynamicValue::VOID: return voidValue; | |
2043 case DynamicValue::BOOL: return boolValue; | |
2044 case DynamicValue::INT: return intValue; | |
2045 case DynamicValue::UINT: return uintValue; | |
2046 case DynamicValue::FLOAT: return floatValue; | |
2047 case DynamicValue::ENUM: return enumValue; | |
2048 | |
2049 case DynamicValue::TEXT: return builder.asText(); | |
2050 case DynamicValue::DATA: return builder.asData(); | |
2051 case DynamicValue::LIST: | |
2052 if (listSchema.whichElementType() == schema::Type::STRUCT) { | |
2053 return DynamicList::Builder(listSchema, | |
2054 builder.asStructList(structSizeFromSchema(listSchema.getStructElementType()))); | |
2055 } else { | |
2056 return DynamicList::Builder(listSchema, | |
2057 builder.asList(elementSizeFor(listSchema.whichElementType()))); | |
2058 } | |
2059 case DynamicValue::STRUCT: | |
2060 return DynamicStruct::Builder(structSchema, | |
2061 builder.asStruct(structSizeFromSchema(structSchema))); | |
2062 case DynamicValue::CAPABILITY: | |
2063 return DynamicCapability::Client(interfaceSchema, builder.asCapability()); | |
2064 case DynamicValue::ANY_POINTER: | |
2065 KJ_FAIL_REQUIRE("Can't get() an AnyPointer orphan; there is no underlying pointer to " | |
2066 "wrap in an AnyPointer::Builder."); | |
2067 } | |
2068 KJ_UNREACHABLE; | |
2069 } | |
2070 DynamicValue::Reader Orphan<DynamicValue>::getReader() const { | |
2071 switch (type) { | |
2072 case DynamicValue::UNKNOWN: return nullptr; | |
2073 case DynamicValue::VOID: return voidValue; | |
2074 case DynamicValue::BOOL: return boolValue; | |
2075 case DynamicValue::INT: return intValue; | |
2076 case DynamicValue::UINT: return uintValue; | |
2077 case DynamicValue::FLOAT: return floatValue; | |
2078 case DynamicValue::ENUM: return enumValue; | |
2079 | |
2080 case DynamicValue::TEXT: return builder.asTextReader(); | |
2081 case DynamicValue::DATA: return builder.asDataReader(); | |
2082 case DynamicValue::LIST: | |
2083 return DynamicList::Reader(listSchema, | |
2084 builder.asListReader(elementSizeFor(listSchema.whichElementType()))); | |
2085 case DynamicValue::STRUCT: | |
2086 return DynamicStruct::Reader(structSchema, | |
2087 builder.asStructReader(structSizeFromSchema(structSchema))); | |
2088 case DynamicValue::CAPABILITY: | |
2089 return DynamicCapability::Client(interfaceSchema, builder.asCapability()); | |
2090 case DynamicValue::ANY_POINTER: | |
2091 KJ_FAIL_ASSERT("Can't get() an AnyPointer orphan; there is no underlying pointer to " | |
2092 "wrap in an AnyPointer::Builder."); | |
2093 } | |
2094 KJ_UNREACHABLE; | |
2095 } | |
2096 | |
2097 template <> | |
2098 Orphan<AnyPointer> Orphan<DynamicValue>::releaseAs<AnyPointer>() { | |
2099 KJ_REQUIRE(type == DynamicValue::ANY_POINTER, "Value type mismatch."); | |
2100 type = DynamicValue::UNKNOWN; | |
2101 return Orphan<AnyPointer>(kj::mv(builder)); | |
2102 } | |
2103 template <> | |
2104 Orphan<DynamicStruct> Orphan<DynamicValue>::releaseAs<DynamicStruct>() { | |
2105 KJ_REQUIRE(type == DynamicValue::STRUCT, "Value type mismatch."); | |
2106 type = DynamicValue::UNKNOWN; | |
2107 return Orphan<DynamicStruct>(structSchema, kj::mv(builder)); | |
2108 } | |
2109 template <> | |
2110 Orphan<DynamicList> Orphan<DynamicValue>::releaseAs<DynamicList>() { | |
2111 KJ_REQUIRE(type == DynamicValue::LIST, "Value type mismatch."); | |
2112 type = DynamicValue::UNKNOWN; | |
2113 return Orphan<DynamicList>(listSchema, kj::mv(builder)); | |
2114 } | |
2115 | |
2116 template <> | |
2117 Orphan<DynamicValue> Orphanage::newOrphanCopy<DynamicValue::Reader>( | |
2118 DynamicValue::Reader copyFrom) const { | |
2119 switch (copyFrom.getType()) { | |
2120 case DynamicValue::UNKNOWN: return nullptr; | |
2121 case DynamicValue::VOID: return copyFrom.voidValue; | |
2122 case DynamicValue::BOOL: return copyFrom.boolValue; | |
2123 case DynamicValue::INT: return copyFrom.intValue; | |
2124 case DynamicValue::UINT: return copyFrom.uintValue; | |
2125 case DynamicValue::FLOAT: return copyFrom.floatValue; | |
2126 case DynamicValue::ENUM: return copyFrom.enumValue; | |
2127 | |
2128 case DynamicValue::TEXT: return newOrphanCopy(copyFrom.textValue); | |
2129 case DynamicValue::DATA: return newOrphanCopy(copyFrom.dataValue); | |
2130 case DynamicValue::LIST: return newOrphanCopy(copyFrom.listValue); | |
2131 case DynamicValue::STRUCT: return newOrphanCopy(copyFrom.structValue); | |
2132 case DynamicValue::CAPABILITY: return newOrphanCopy(copyFrom.capabilityValue); | |
2133 case DynamicValue::ANY_POINTER: return newOrphanCopy(copyFrom.anyPointerValue); | |
2134 } | |
2135 KJ_UNREACHABLE; | |
2136 } | |
2137 | |
2138 } // namespace capnp |