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