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