Coverage Report

Created: 2024-09-08 06:35

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