annotate 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
rev   line source
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