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