layout.h 42.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Kenton Varda's avatar
Kenton Varda committed
24 25
// This file is NOT intended for use by clients, except in generated code.
//
Kenton Varda's avatar
Kenton Varda committed
26 27 28 29
// This file defines low-level, non-type-safe classes for traversing the Cap'n Proto memory layout
// (which is also its wire format).  Code generated by the Cap'n Proto compiler uses these classes,
// as does other parts of the Cap'n proto library which provide a higher-level interface for
// dynamic introspection.
Kenton Varda's avatar
Kenton Varda committed
30

Kenton Varda's avatar
Kenton Varda committed
31 32
#ifndef CAPNP_LAYOUT_H_
#define CAPNP_LAYOUT_H_
33

Kenton Varda's avatar
Kenton Varda committed
34
#include <kj/common.h>
35
#include "common.h"
Kenton Varda's avatar
Kenton Varda committed
36
#include "blob.h"
37
#include "endian.h"
38

39
namespace capnp {
40
namespace _ {  // private
Kenton Varda's avatar
Kenton Varda committed
41

42 43 44 45
class StructBuilder;
class StructReader;
class ListBuilder;
class ListReader;
46
class OrphanBuilder;
Kenton Varda's avatar
Kenton Varda committed
47 48
struct ObjectBuilder;
struct ObjectReader;
49
struct WirePointer;
50
struct WireHelpers;
51 52
class SegmentReader;
class SegmentBuilder;
53
class BuilderArena;
54

55
// =============================================================================
56 57

enum class FieldSize: uint8_t {
58
  // TODO(cleanup):  Rename to FieldLayout or maybe ValueLayout.
59

60 61 62 63 64
  // Notice that each member of this enum, when representing a list element size, represents a
  // size that is greater than or equal to the previous members, since INLINE_COMPOSITE is used
  // only for multi-word structs.  This is important because it allows us to compare FieldSize
  // values for the purpose of deciding when we need to upgrade a list.

65 66 67 68 69 70 71
  VOID = 0,
  BIT = 1,
  BYTE = 2,
  TWO_BYTES = 3,
  FOUR_BYTES = 4,
  EIGHT_BYTES = 5,

72
  POINTER = 6,  // Indicates that the field lives in the pointer section, not the data section.
73 74 75 76

  INLINE_COMPOSITE = 7
  // A composite type of fixed width.  This serves two purposes:
  // 1) For lists of composite types where all the elements would have the exact same width,
77
  //    allocating a list of pointers which in turn point at the elements would waste space.  We
78 79 80
  //    can avoid a layer of indirection by placing all the elements in a flat sequence, and only
  //    indicating the element properties (e.g. field count for structs) once.
  //
81 82
  //    Specifically, a list pointer indicating INLINE_COMPOSITE element size actually points to
  //    a "tag" describing one element.  This tag is formatted like a wire pointer, but the
83
  //    "offset" instead stores the element count of the list.  The flat list of elements appears
84
  //    immediately after the tag.  In the list pointer itself, the element count is replaced with
85 86 87
  //    a word count for the whole list (excluding tag).  This allows the tag and elements to be
  //    precached in a single step rather than two sequential steps.
  //
88
  //    It is NOT intended to be possible to substitute an INLINE_COMPOSITE list for a POINTER
89 90 91 92 93 94 95 96 97 98
  //    list or vice-versa without breaking recipients.  Recipients expect one or the other
  //    depending on the message definition.
  //
  //    However, it IS allowed to substitute an INLINE_COMPOSITE list -- specifically, of structs --
  //    when a list was expected, or vice versa, with the assumption that the first field of the
  //    struct (field number zero) correspond to the element type.  This allows a list of
  //    primitives to be upgraded to a list of structs, avoiding the need to use parallel arrays
  //    when you realize that you need to attach some extra information to each element of some
  //    primitive list.
  //
99 100
  // 2) At one point there was a notion of "inline" struct fields, but it was deemed too much of
  //    an implementation burden for too little gain, and so was deleted.
101 102 103
};

typedef decltype(BITS / ELEMENTS) BitsPerElement;
104
typedef decltype(POINTERS / ELEMENTS) PointersPerElement;
105

Kenton Varda's avatar
Kenton Varda committed
106 107 108 109 110 111 112 113 114 115
static constexpr BitsPerElement BITS_PER_ELEMENT_TABLE[8] = {
    0 * BITS / ELEMENTS,
    1 * BITS / ELEMENTS,
    8 * BITS / ELEMENTS,
    16 * BITS / ELEMENTS,
    32 * BITS / ELEMENTS,
    64 * BITS / ELEMENTS,
    0 * BITS / ELEMENTS,
    0 * BITS / ELEMENTS
};
116

117
inline constexpr BitsPerElement dataBitsPerElement(FieldSize size) {
118
  return _::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)];
119 120
}

121
inline constexpr PointersPerElement pointersPerElement(FieldSize size) {
122
  return size == FieldSize::POINTER ? 1 * POINTERS / ELEMENTS : 0 * POINTERS / ELEMENTS;
123 124
}

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
template <size_t size> struct ElementSizeForByteSize;
template <> struct ElementSizeForByteSize<1> { static constexpr FieldSize value = FieldSize::BYTE; };
template <> struct ElementSizeForByteSize<2> { static constexpr FieldSize value = FieldSize::TWO_BYTES; };
template <> struct ElementSizeForByteSize<4> { static constexpr FieldSize value = FieldSize::FOUR_BYTES; };
template <> struct ElementSizeForByteSize<8> { static constexpr FieldSize value = FieldSize::EIGHT_BYTES; };

template <typename T> struct ElementSizeForType {
  static constexpr FieldSize value =
      // Primitive types that aren't special-cased below can be determined from sizeof().
      kind<T>() == Kind::PRIMITIVE ? ElementSizeForByteSize<sizeof(T)>::value :
      kind<T>() == Kind::ENUM ? FieldSize::TWO_BYTES :
      kind<T>() == Kind::STRUCT ? FieldSize::INLINE_COMPOSITE :

      // Everything else is a pointer.
      FieldSize::POINTER;
140 141
};

142 143 144
// Void and bool are special.
template <> struct ElementSizeForType<Void> { static constexpr FieldSize value = FieldSize::VOID; };
template <> struct ElementSizeForType<bool> { static constexpr FieldSize value = FieldSize::BIT; };
145

146 147 148 149 150 151 152 153 154 155
// Lists and blobs are pointers, not structs.
template <typename T, bool b> struct ElementSizeForType<List<T, b>> {
  static constexpr FieldSize value = FieldSize::POINTER;
};
template <> struct ElementSizeForType<Text> {
  static constexpr FieldSize value = FieldSize::POINTER;
};
template <> struct ElementSizeForType<Data> {
  static constexpr FieldSize value = FieldSize::POINTER;
};
156

157
}  // namespace _ (private)
158 159 160

// =============================================================================

161
namespace _ {  // private
162

163 164 165 166 167 168 169 170 171
template <int wordCount>
union AlignedData {
  // Useful for declaring static constant data blobs as an array of bytes, but forcing those
  // bytes to be word-aligned.

  uint8_t bytes[wordCount * sizeof(word)];
  word words[wordCount];
};

172 173
struct StructSize {
  WordCount16 data;
174
  WirePointerCount16 pointers;
175

176 177 178 179
  FieldSize preferredListEncoding;
  // Preferred size to use when encoding a list of this struct.  This is INLINE_COMPOSITE if and
  // only if the struct is larger than one word; otherwise the struct list can be encoded more
  // efficiently by encoding it as if it were some primitive type.
180

181
  inline constexpr WordCount total() const { return data + pointers * WORDS_PER_POINTER; }
182 183

  StructSize() = default;
184
  inline constexpr StructSize(WordCount data, WirePointerCount pointers,
185 186
                              FieldSize preferredListEncoding)
      : data(data), pointers(pointers), preferredListEncoding(preferredListEncoding) {}
187 188
};

189
template <typename T> struct StructSize_;
190 191
// Specialized for every struct type with member:  static constexpr StructSize value"

192
template <typename T>
193
inline constexpr StructSize structSize() {
194
  return StructSize_<T>::value;
195
}
196

197 198
// -------------------------------------------------------------------
// Masking of default values
199

200 201 202 203 204
template <typename T, Kind kind = kind<T>()> struct Mask_;
template <typename T> struct Mask_<T, Kind::PRIMITIVE> { typedef T Type; };
template <typename T> struct Mask_<T, Kind::ENUM> { typedef uint16_t Type; };
template <> struct Mask_<float, Kind::PRIMITIVE> { typedef uint32_t Type; };
template <> struct Mask_<double, Kind::PRIMITIVE> { typedef uint64_t Type; };
205

206
template <typename T> struct Mask_<T, Kind::UNKNOWN> {
207 208 209
  // Union discriminants end up here.
  static_assert(sizeof(T) == 2, "Don't know how to mask this type.");
  typedef uint16_t Type;
210 211
};

212
template <typename T>
213
using Mask = typename Mask_<T>::Type;
214 215

template <typename T>
216
KJ_ALWAYS_INLINE(Mask<T> mask(T value, Mask<T> mask));
217
template <typename T>
218
KJ_ALWAYS_INLINE(T unmask(Mask<T> value, Mask<T> mask));
219 220

template <typename T>
221 222
inline Mask<T> mask(T value, Mask<T> mask) {
  return static_cast<Mask<T> >(value) ^ mask;
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
}

template <>
inline uint32_t mask<float>(float value, uint32_t mask) {
  uint32_t i;
  static_assert(sizeof(i) == sizeof(value), "float is not 32 bits?");
  memcpy(&i, &value, sizeof(value));
  return i ^ mask;
}

template <>
inline uint64_t mask<double>(double value, uint64_t mask) {
  uint64_t i;
  static_assert(sizeof(i) == sizeof(value), "double is not 64 bits?");
  memcpy(&i, &value, sizeof(value));
  return i ^ mask;
}

template <typename T>
242
inline T unmask(Mask<T> value, Mask<T> mask) {
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
  return static_cast<T>(value ^ mask);
}

template <>
inline float unmask<float>(uint32_t value, uint32_t mask) {
  value ^= mask;
  float result;
  static_assert(sizeof(result) == sizeof(value), "float is not 32 bits?");
  memcpy(&result, &value, sizeof(value));
  return result;
}

template <>
inline double unmask<double>(uint64_t value, uint64_t mask) {
  value ^= mask;
  double result;
  static_assert(sizeof(result) == sizeof(value), "double is not 64 bits?");
  memcpy(&result, &value, sizeof(value));
  return result;
}

264 265
// -------------------------------------------------------------------

266
// -------------------------------------------------------------------
Kenton Varda's avatar
Kenton Varda committed
267

268
class StructBuilder: public kj::DisallowConstCopy {
269
public:
270
  inline StructBuilder(): segment(nullptr), data(nullptr), pointers(nullptr), bit0Offset(0) {}
271

272
  static StructBuilder initRoot(SegmentBuilder* segment, word* location, StructSize size);
273
  static void setRoot(SegmentBuilder* segment, word* location, StructReader value);
274
  static StructBuilder getRoot(SegmentBuilder* segment, word* location, StructSize size);
275

276
  inline BitCount getDataSectionSize() const { return dataSize; }
277
  inline WirePointerCount getPointerSectionSize() const { return pointerCount; }
278 279
  inline Data::Builder getDataSectionAsBlob();

280
  template <typename T>
281
  KJ_ALWAYS_INLINE(T getDataField(ElementCount offset));
282
  // Gets the data field value of the given type at the given offset.  The offset is measured in
283 284
  // multiples of the field size, determined by the type.

285
  template <typename T>
286
  KJ_ALWAYS_INLINE(T getDataField(ElementCount offset, Mask<T> mask));
287 288 289
  // Like getDataField() but applies the given XOR mask to the data on load.  Used for reading
  // fields with non-zero default values.

290
  template <typename T>
291
  KJ_ALWAYS_INLINE(void setDataField(
292
      ElementCount offset, kj::NoInfer<T> value));
293 294
  // Sets the data field value at the given offset.

295
  template <typename T>
296
  KJ_ALWAYS_INLINE(void setDataField(
297
      ElementCount offset, kj::NoInfer<T> value, Mask<T> mask));
298 299 300
  // Like setDataField() but applies the given XOR mask before storing.  Used for writing fields
  // with non-zero default values.

301
  StructBuilder initStructField(WirePointerCount ptrIndex, StructSize size);
302
  // Initializes the struct field at the given index in the pointer section.  If it is already
303
  // initialized, the previous value is discarded or overwritten.  The struct is initialized to
304
  // the type's default state (all-zero).  Use getStructField() if you want the struct to be
305
  // initialized as a copy of the field's default value (which may have non-null pointers).
306

307
  StructBuilder getStructField(WirePointerCount ptrIndex, StructSize size,
308
                               const word* defaultValue);
309
  // Gets the struct field at the given index in the pointer section.  If the field is not already
310
  // initialized, it is initialized as a deep copy of the given default value (a flat message),
311
  // or to the empty state if defaultValue is nullptr.
312

313
  ListBuilder initListField(WirePointerCount ptrIndex, FieldSize elementSize,
314
                            ElementCount elementCount);
315
  // Allocates a new list of the given size for the field at the given index in the pointer
316
  // segment, and return a pointer to it.  All elements are initialized to zero.
317

318
  ListBuilder initStructListField(WirePointerCount ptrIndex, ElementCount elementCount,
319
                                  StructSize size);
320
  // Allocates a new list of the given size for the field at the given index in the pointer
321
  // segment, and return a pointer to it.  Each element is initialized to its empty state.
322

323
  ListBuilder getListField(WirePointerCount ptrIndex, FieldSize elementSize,
324
                           const word* defaultValue);
325 326
  // Gets the already-allocated list field for the given pointer index, ensuring that the list is
  // suitable for storing non-struct elements of the given size.  If the list is not already
327
  // allocated, it is allocated as a deep copy of the given default value (a flat message).  If
328 329 330
  // the default value is null, an empty list is used.

  ListBuilder getStructListField(WirePointerCount ptrIndex, StructSize elementSize,
331
                                 const word* defaultValue);
332 333
  // Gets the already-allocated list field for the given pointer index, ensuring that the list
  // is suitable for storing struct elements of the given size.  If the list is not
334
  // already allocated, it is allocated as a deep copy of the given default value (a flat
335
  // message).  If the default value is null, an empty list is used.
336

337
  template <typename T>
338
  typename T::Builder initBlobField(WirePointerCount ptrIndex, ByteCount size);
339 340
  // Initialize a Text or Data field to the given size in bytes (not including NUL terminator for
  // Text) and return a Text::Builder which can be used to fill in the content.
Kenton Varda's avatar
Kenton Varda committed
341

342
  template <typename T>
343
  void setBlobField(WirePointerCount ptrIndex, typename T::Reader value);
344
  // Set the blob field to a copy of the given blob.
Kenton Varda's avatar
Kenton Varda committed
345

346
  template <typename T>
347
  typename T::Builder getBlobField(WirePointerCount ptrIndex,
348
                                   const void* defaultValue, ByteCount defaultSize);
349
  // Get the blob field.  If it is not initialized, initialize it to a copy of the given default.
Kenton Varda's avatar
Kenton Varda committed
350

351
  ObjectBuilder getObjectField(WirePointerCount ptrIndex, const word* defaultValue);
352 353
  // Read a pointer of arbitrary type.

354 355 356
  void setStructField(WirePointerCount ptrIndex, StructReader value);
  void setListField(WirePointerCount ptrIndex, ListReader value);
  void setObjectField(WirePointerCount ptrIndex, ObjectReader value);
357 358
  // Sets a pointer field to a deep copy of the given value.

359 360 361 362 363 364 365 366
  void adopt(WirePointerCount ptrIndex, OrphanBuilder&& orphan);
  // Adopt the orphaned object as the value of the given pointer field.  The orphan must reside in
  // the same message as the new parent.  No copying occurs.

  OrphanBuilder disown(WirePointerCount ptrIndex);
  // Detach the given pointer field from this object.  The pointer becomes null, and the child
  // object is returned as an orphan.

367 368 369 370 371
  void transferContentFrom(StructBuilder other);
  // Adopt all pointers from `other`, and also copy all data.  If `other`'s sections are larger
  // than this, the extra data is not transferred, meaning there is a risk of data loss when
  // transferring from messages built with future versions of the protocol.

372
  bool isPointerFieldNull(WirePointerCount ptrIndex);
373

374
  StructReader asReader() const;
375
  // Gets a StructReader pointing at the same memory.
376

377 378 379
  BuilderArena* getArena();
  // Gets the arena in which this object is allocated.

380
private:
381
  SegmentBuilder* segment;     // Memory segment in which the struct resides.
Kenton Varda's avatar
Kenton Varda committed
382
  void* data;                  // Pointer to the encoded data.
383
  WirePointer* pointers;   // Pointer to the encoded pointers.
384

385
  BitCount32 dataSize;
386
  // Size of data section.  We use a bit count rather than a word count to more easily handle the
387 388
  // case of struct lists encoded with less than a word per element.

389
  WirePointerCount16 pointerCount;  // Size of the pointer section.
390 391 392 393 394 395

  BitCount8 bit0Offset;
  // A special hack:  If dataSize == 1 bit, then bit0Offset is the offset of that bit within the
  // byte pointed to by `data`.  In all other cases, this is zero.  This is needed to implement
  // struct lists where each struct is one bit.

396 397 398 399
  inline StructBuilder(SegmentBuilder* segment, void* data, WirePointer* pointers,
                       BitCount dataSize, WirePointerCount pointerCount, BitCount8 bit0Offset)
      : segment(segment), data(data), pointers(pointers),
        dataSize(dataSize), pointerCount(pointerCount), bit0Offset(bit0Offset) {}
400

401
  friend class ListBuilder;
402
  friend struct WireHelpers;
403
  friend class OrphanBuilder;
404 405
};

406
class StructReader {
407
public:
408
  inline StructReader()
409
      : segment(nullptr), data(nullptr), pointers(nullptr), dataSize(0),
410
        pointerCount(0), bit0Offset(0), nestingLimit(0x7fffffff) {}
411

412
  static StructReader readRootUnchecked(const word* location);
413
  static StructReader readRoot(const word* location, SegmentReader* segment, int nestingLimit);
414

415
  inline BitCount getDataSectionSize() const { return dataSize; }
416
  inline WirePointerCount getPointerSectionSize() const { return pointerCount; }
417 418
  inline Data::Reader getDataSectionAsBlob();

419
  template <typename T>
420
  KJ_ALWAYS_INLINE(T getDataField(ElementCount offset) const);
421
  // Get the data field value of the given type at the given offset.  The offset is measured in
422
  // multiples of the field size, determined by the type.  Returns zero if the offset is past the
423
  // end of the struct's data section.
424 425

  template <typename T>
426
  KJ_ALWAYS_INLINE(
427
      T getDataField(ElementCount offset, Mask<T> mask) const);
428 429
  // Like getDataField(offset), but applies the given XOR mask to the result.  Used for reading
  // fields with non-zero default values.
430

431
  StructReader getStructField(WirePointerCount ptrIndex, const word* defaultValue) const;
432
  // Get the struct field at the given index in the pointer section, or the default value if not
433
  // initialized.  defaultValue will be interpreted as a flat message -- it must point at a
434
  // struct pointer, which in turn points at the struct value.  The default value is allowed to
435
  // be null, in which case an empty struct is used.
436

437
  ListReader getListField(WirePointerCount ptrIndex, FieldSize expectedElementSize,
438
                          const word* defaultValue) const;
439
  // Get the list field at the given index in the pointer section, or the default value if not
440
  // initialized.  The default value is allowed to be null, in which case an empty list is used.
441

442
  template <typename T>
443
  typename T::Reader getBlobField(WirePointerCount ptrIndex,
444 445
                                  const void* defaultValue, ByteCount defaultSize) const;
  // Gets the text or data field, or the given default value if not initialized.
Kenton Varda's avatar
Kenton Varda committed
446

447
  ObjectReader getObjectField(WirePointerCount ptrIndex, const word* defaultValue) const;
448 449
  // Read a pointer of arbitrary type.

450 451 452 453
  const word* getUncheckedPointer(WirePointerCount ptrIndex) const;
  // If this is an unchecked message, get a word* pointing at the location of the pointer.  This
  // word* can actually be passed to readUnchecked() to read the designated sub-object later.  If
  // this isn't an unchecked message, throws an exception.
454

455 456
  bool isPointerFieldNull(WirePointerCount ptrIndex) const;

457 458 459 460 461 462 463
  WordCount64 totalSize() const;
  // Return the total size of the struct and everything to which it points.  Does not count far
  // pointer overhead.  This is useful for deciding how much space is needed to copy the struct
  // into a flat array.  However, the caller is advised NOT to treat this value as secure.  Instead,
  // use the result as a hint for allocating the first segment, do the copy, and then throw an
  // exception if it overruns.

464
private:
Kenton Varda's avatar
Kenton Varda committed
465
  SegmentReader* segment;  // Memory segment in which the struct resides.
466

467
  const void* data;
468
  const WirePointer* pointers;
469

470
  BitCount32 dataSize;
471
  // Size of data section.  We use a bit count rather than a word count to more easily handle the
472 473
  // case of struct lists encoded with less than a word per element.

474
  WirePointerCount16 pointerCount;  // Size of the pointer section.
475

476 477 478 479 480 481 482 483 484 485
  BitCount8 bit0Offset;
  // A special hack:  If dataSize == 1 bit, then bit0Offset is the offset of that bit within the
  // byte pointed to by `data`.  In all other cases, this is zero.  This is needed to implement
  // struct lists where each struct is one bit.
  //
  // TODO(someday):  Consider packing this together with dataSize, since we have 10 extra bits
  //   there doing nothing -- or arguably 12 bits, if you consider that 2-bit and 4-bit sizes
  //   aren't allowed.  Consider that we could have a method like getDataSizeIn<T>() which is
  //   specialized to perform the correct shifts for each size.

486
  int nestingLimit;
487 488
  // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
  // Once this reaches zero, further pointers will be pruned.
489
  // TODO(perf):  Limit to 8 bits for better alignment?
490

491 492
  inline StructReader(SegmentReader* segment, const void* data, const WirePointer* pointers,
                      BitCount dataSize, WirePointerCount pointerCount, BitCount8 bit0Offset,
493
                      int nestingLimit)
494 495
      : segment(segment), data(data), pointers(pointers),
        dataSize(dataSize), pointerCount(pointerCount), bit0Offset(bit0Offset),
496
        nestingLimit(nestingLimit) {}
497

498 499
  friend class ListReader;
  friend class StructBuilder;
500 501 502 503 504
  friend struct WireHelpers;
};

// -------------------------------------------------------------------

505
class ListBuilder: public kj::DisallowConstCopy {
506
public:
507
  inline ListBuilder()
508
      : segment(nullptr), ptr(nullptr), elementCount(0 * ELEMENTS),
509
        step(0 * BITS / ELEMENTS) {}
510

511
  inline ElementCount size() const;
512 513
  // The number of elements in the list.

514 515 516 517
  Text::Builder asText();
  Data::Builder asData();
  // Reinterpret the list as a blob.  Throws an exception if the elements are not byte-sized.

518
  template <typename T>
519
  KJ_ALWAYS_INLINE(T getDataElement(ElementCount index));
520 521 522
  // Get the element of the given type at the given index.

  template <typename T>
523
  KJ_ALWAYS_INLINE(void setDataElement(
524
      ElementCount index, kj::NoInfer<T> value));
525
  // Set the element at the given index.
526

527
  StructBuilder getStructElement(ElementCount index);
528
  // Get the struct element at the given index.
529

530
  ListBuilder initListElement(
531
      ElementCount index, FieldSize elementSize, ElementCount elementCount);
532 533 534
  // Create a new list element of the given size at the given index.  All elements are initialized
  // to zero.

535
  ListBuilder initStructListElement(ElementCount index, ElementCount elementCount,
536
                                    StructSize size);
537
  // Allocates a new list of the given size for the field at the given index in the pointer
538
  // segment, and return a pointer to it.  Each element is initialized to its empty state.
539

540
  ListBuilder getListElement(ElementCount index, FieldSize elementSize);
541 542 543 544
  // Get the existing list element at the given index, making sure it is suitable for storing
  // non-struct elements of the given size.  Returns an empty list if the element is not
  // initialized.

545
  ListBuilder getStructListElement(ElementCount index, StructSize elementSize);
546 547 548
  // Get the existing list element at the given index, making sure it is suitable for storing
  // struct elements of the given size.  Returns an empty list if the element is not
  // initialized.
549

550
  template <typename T>
551
  typename T::Builder initBlobElement(ElementCount index, ByteCount size);
552 553
  // Initialize a Text or Data element to the given size in bytes (not including NUL terminator for
  // Text) and return a Text::Builder which can be used to fill in the content.
Kenton Varda's avatar
Kenton Varda committed
554

555
  template <typename T>
556
  void setBlobElement(ElementCount index, typename T::Reader value);
557
  // Set the blob element to a copy of the given blob.
Kenton Varda's avatar
Kenton Varda committed
558

559
  template <typename T>
560
  typename T::Builder getBlobElement(ElementCount index);
561
  // Get the blob element.  If it is not initialized, return an empty blob builder.
Kenton Varda's avatar
Kenton Varda committed
562

563
  ObjectBuilder getObjectElement(ElementCount index);
564 565
  // Gets a pointer element of arbitrary type.

566 567
  void setListElement(ElementCount index, ListReader value);
  void setObjectElement(ElementCount index, ObjectReader value);
568 569
  // Sets a pointer element to a deep copy of the given value.

570 571 572 573 574 575 576 577
  void adopt(ElementCount index, OrphanBuilder&& orphan);
  // Adopt the orphaned object as the value of the given pointer field.  The orphan must reside in
  // the same message as the new parent.  No copying occurs.

  OrphanBuilder disown(ElementCount index);
  // Detach the given pointer field from this object.  The pointer becomes null, and the child
  // object is returned as an orphan.

578 579
  ListReader asReader() const;
  // Get a ListReader pointing at the same memory.
580

581 582 583
  BuilderArena* getArena();
  // Gets the arena in which this object is allocated.

584
private:
Kenton Varda's avatar
Kenton Varda committed
585
  SegmentBuilder* segment;  // Memory segment in which the list resides.
586

587
  byte* ptr;  // Pointer to list content.
588

589
  ElementCount elementCount;  // Number of elements in the list.
590

591
  decltype(BITS / ELEMENTS) step;
592
  // The distance between elements.
593 594

  BitCount32 structDataSize;
595
  WirePointerCount16 structPointerCount;
596 597
  // The struct properties to use when interpreting the elements as structs.  All lists can be
  // interpreted as struct lists, so these are always filled in.
598

599
  inline ListBuilder(SegmentBuilder* segment, void* ptr,
600
                     decltype(BITS / ELEMENTS) step, ElementCount size,
601
                     BitCount structDataSize, WirePointerCount structPointerCount)
602
      : segment(segment), ptr(reinterpret_cast<byte*>(ptr)),
603
        elementCount(size), step(step), structDataSize(structDataSize),
604
        structPointerCount(structPointerCount) {}
605

606
  friend class StructBuilder;
607
  friend struct WireHelpers;
608
  friend class OrphanBuilder;
609 610
};

611
class ListReader {
612
public:
613
  inline ListReader()
614
      : segment(nullptr), ptr(nullptr), elementCount(0), step(0 * BITS / ELEMENTS),
615
        structDataSize(0), structPointerCount(0), nestingLimit(0x7fffffff) {}
616

617
  inline ElementCount size() const;
618 619
  // The number of elements in the list.

620 621 622 623
  Text::Reader asText();
  Data::Reader asData();
  // Reinterpret the list as a blob.  Throws an exception if the elements are not byte-sized.

624
  template <typename T>
625
  KJ_ALWAYS_INLINE(T getDataElement(ElementCount index) const);
626 627
  // Get the element of the given type at the given index.

628
  StructReader getStructElement(ElementCount index) const;
629 630
  // Get the struct element at the given index.

631
  ListReader getListElement(ElementCount index, FieldSize expectedElementSize) const;
632 633
  // Get the list element at the given index.

634 635 636
  template <typename T>
  typename T::Reader getBlobElement(ElementCount index) const;
  // Gets the text or data field.  If it is not initialized, returns an empty blob reader.
Kenton Varda's avatar
Kenton Varda committed
637

Kenton Varda's avatar
Kenton Varda committed
638
  ObjectReader getObjectElement(ElementCount index) const;
639 640
  // Gets a pointer element of arbitrary type.

641
private:
Kenton Varda's avatar
Kenton Varda committed
642
  SegmentReader* segment;  // Memory segment in which the list resides.
643

644
  const byte* ptr;  // Pointer to list content.
645

646
  ElementCount elementCount;  // Number of elements in the list.
647

648
  decltype(BITS / ELEMENTS) step;
649
  // The distance between elements.
650

651
  BitCount32 structDataSize;
652
  WirePointerCount16 structPointerCount;
653 654
  // The struct properties to use when interpreting the elements as structs.  All lists can be
  // interpreted as struct lists, so these are always filled in.
655

656
  int nestingLimit;
657 658 659
  // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
  // Once this reaches zero, further pointers will be pruned.

660
  inline ListReader(SegmentReader* segment, const void* ptr,
661
                    ElementCount elementCount, decltype(BITS / ELEMENTS) step,
662
                    BitCount structDataSize, WirePointerCount structPointerCount,
663 664
                    int nestingLimit)
      : segment(segment), ptr(reinterpret_cast<const byte*>(ptr)), elementCount(elementCount),
665
        step(step), structDataSize(structDataSize),
666
        structPointerCount(structPointerCount), nestingLimit(nestingLimit) {}
667

668 669
  friend class StructReader;
  friend class ListBuilder;
670
  friend struct WireHelpers;
671
  friend class OrphanBuilder;
672 673
};

674 675
// -------------------------------------------------------------------

676 677 678 679 680 681
enum class ObjectKind {
  NULL_POINTER,   // Object was read from a null pointer.
  STRUCT,
  LIST
};

682 683 684
struct ObjectBuilder {
  // A reader for any kind of object.

685
  ObjectKind kind;
686 687 688 689 690 691

  union {
    StructBuilder structBuilder;
    ListBuilder listBuilder;
  };

692
  ObjectBuilder(): kind(ObjectKind::NULL_POINTER), structBuilder() {}
693
  ObjectBuilder(StructBuilder structBuilder)
694
      : kind(ObjectKind::STRUCT), structBuilder(structBuilder) {}
Kenton Varda's avatar
Kenton Varda committed
695
  ObjectBuilder(ListBuilder listBuilder)
696
      : kind(ObjectKind::LIST), listBuilder(listBuilder) {}
697 698 699 700 701
};

struct ObjectReader {
  // A reader for any kind of object.

702
  ObjectKind kind;
703 704 705 706 707 708

  union {
    StructReader structReader;
    ListReader listReader;
  };

709
  ObjectReader(): kind(ObjectKind::NULL_POINTER), structReader() {}
710
  ObjectReader(StructReader structReader)
711
      : kind(ObjectKind::STRUCT), structReader(structReader) {}
712
  ObjectReader(ListReader listReader)
713
      : kind(ObjectKind::LIST), listReader(listReader) {}
714 715
};

716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
// -------------------------------------------------------------------

class OrphanBuilder {
public:
  inline OrphanBuilder(): segment(nullptr), location(nullptr) { memset(&tag, 0, sizeof(tag)); }
  OrphanBuilder(const OrphanBuilder& other) = delete;
  inline OrphanBuilder(OrphanBuilder&& other);
  inline ~OrphanBuilder();

  static OrphanBuilder initStruct(BuilderArena* arena, StructSize size);
  static OrphanBuilder initList(BuilderArena* arena, ElementCount elementCount,
                                FieldSize elementSize);
  static OrphanBuilder initStructList(BuilderArena* arena, ElementCount elementCount,
                                      StructSize elementSize);
  static OrphanBuilder initText(BuilderArena* arena, ByteCount size);
  static OrphanBuilder initData(BuilderArena* arena, ByteCount size);

  static OrphanBuilder copy(BuilderArena* arena, StructReader copyFrom);
  static OrphanBuilder copy(BuilderArena* arena, ListReader copyFrom);
  static OrphanBuilder copy(BuilderArena* arena, Text::Reader copyFrom);
  static OrphanBuilder copy(BuilderArena* arena, Data::Reader copyFrom);

  OrphanBuilder& operator=(const OrphanBuilder& other) = delete;
  inline OrphanBuilder& operator=(OrphanBuilder&& other);

  inline bool operator==(decltype(nullptr)) { return location == nullptr; }
  inline bool operator!=(decltype(nullptr)) { return location != nullptr; }

  StructBuilder asStruct(StructSize size);
  // Interpret as a struct, or throw an exception if not a struct.

  ListBuilder asList(FieldSize elementSize);
  // Interpret as a list, or throw an exception if not a list.  elementSize cannot be
  // INLINE_COMPOSITE -- use asStructList() instead.

  ListBuilder asStructList(StructSize elementSize);
  // Interpret as a struct list, or throw an exception if not a list.

  Text::Builder asText();
  Data::Builder asData();
  // Interpret as a blob, or throw an exception if not a blob.

  ObjectBuilder asObject();
  // Interpret as an arbitrary object.

761 762 763 764 765 766
  StructReader asStructReader(StructSize size) const;
  ListReader asListReader(FieldSize elementSize) const;
  Text::Reader asTextReader() const;
  Data::Reader asDataReader() const;
  ObjectReader asObjectReader() const;

767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
private:
  static_assert(1 * POINTERS * WORDS_PER_POINTER == 1 * WORDS,
                "This struct assumes a pointer is one word.");
  word tag;
  // Contains an encoded WirePointer representing this object.  WirePointer is defined in
  // layout.c++, but fits in a word.
  //
  // If the pointer is a FAR pointer, then the tag is a complete pointer, `location` is null, and
  // `segment` is any arbitrary segment in the message.  Otherwise, the tag's offset is garbage,
  // `location` points at the actual object, and `segment` points at the segment where `location`
  // resides.

  SegmentBuilder* segment;
  // Segment in which the object resides, or an arbitrary segment in the message if the tag is a
  // FAR pointer.

  word* location;
  // Pointer to the object, or null if the tag is a FAR pointer.

  inline OrphanBuilder(const void* tagPtr, SegmentBuilder* segment, word* location)
      : segment(segment), location(location) {
    memcpy(&tag, tagPtr, sizeof(tag));
  }

  inline WirePointer* tagAsPtr() { return reinterpret_cast<WirePointer*>(&tag); }
792
  inline const WirePointer* tagAsPtr() const { return reinterpret_cast<const WirePointer*>(&tag); }
793 794 795 796 797 798 799 800

  void euthanize();
  // Erase the target object, zeroing it out and possibly reclaiming the memory.  Called when
  // the OrphanBuilder is being destroyed or overwritten and it is non-null.

  friend struct WireHelpers;
};

801 802 803
// =======================================================================================
// Internal implementation details...

804
inline Data::Builder StructBuilder::getDataSectionAsBlob() {
805
  return Data::Builder(reinterpret_cast<byte*>(data), dataSize / BITS_PER_BYTE / BYTES);
806 807
}

808
template <typename T>
809
inline T StructBuilder::getDataField(ElementCount offset) {
810
  return reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].get();
811 812 813
}

template <>
814
inline bool StructBuilder::getDataField<bool>(ElementCount offset) {
815 816 817
  // This branch should be compiled out whenever this is inlined with a constant offset.
  BitCount boffset = (offset == 0 * ELEMENTS) ?
      BitCount(bit0Offset) : offset * (1 * BITS / ELEMENTS);
818
  byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
819
  return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
820 821
}

822
template <>
823
inline Void StructBuilder::getDataField<Void>(ElementCount offset) {
824 825 826
  return Void::VOID;
}

827
template <typename T>
828
inline T StructBuilder::getDataField(ElementCount offset, Mask<T> mask) {
829
  return unmask<T>(getDataField<Mask<T> >(offset), mask);
830 831
}

832
template <typename T>
833
inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value) {
834
  reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].set(value);
835 836 837
}

template <>
838
inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) {
839 840 841
  // This branch should be compiled out whenever this is inlined with a constant offset.
  BitCount boffset = (offset == 0 * ELEMENTS) ?
      BitCount(bit0Offset) : offset * (1 * BITS / ELEMENTS);
842
  byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
843 844 845
  uint bitnum = boffset % BITS_PER_BYTE / BITS;
  *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
                                 | (static_cast<uint8_t>(value) << bitnum);
846 847
}

848
template <>
849
inline void StructBuilder::setDataField<Void>(ElementCount offset, Void value) {}
850

851
template <typename T>
852
inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value, Mask<T> m) {
853
  setDataField<Mask<T> >(offset, mask<T>(value, m));
854 855
}

856 857
// -------------------------------------------------------------------

858
inline Data::Reader StructReader::getDataSectionAsBlob() {
859
  return Data::Reader(reinterpret_cast<const byte*>(data), dataSize / BITS_PER_BYTE / BYTES);
860 861
}

862
template <typename T>
863
T StructReader::getDataField(ElementCount offset) const {
864
  if ((offset + 1 * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) {
865
    return reinterpret_cast<const WireValue<T>*>(data)[offset / ELEMENTS].get();
866
  } else {
867
    return static_cast<T>(0);
868
  }
869 870 871
}

template <>
872
inline bool StructReader::getDataField<bool>(ElementCount offset) const {
873
  BitCount boffset = offset * (1 * BITS / ELEMENTS);
874 875 876 877 878
  if (boffset < dataSize) {
    // This branch should be compiled out whenever this is inlined with a constant offset.
    if (offset == 0 * ELEMENTS) {
      boffset = bit0Offset;
    }
879
    const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE;
880 881
    return (*reinterpret_cast<const uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
  } else {
882
    return false;
883
  }
884 885
}

886
template <>
887
inline Void StructReader::getDataField<Void>(ElementCount offset) const {
888 889 890
  return Void::VOID;
}

891
template <typename T>
892 893
T StructReader::getDataField(ElementCount offset, Mask<T> mask) const {
  return unmask<T>(getDataField<Mask<T> >(offset), mask);
894 895
}

896 897
// -------------------------------------------------------------------

898
inline ElementCount ListBuilder::size() const { return elementCount; }
899 900

template <typename T>
901
inline T ListBuilder::getDataElement(ElementCount index) {
902 903 904 905 906 907 908
  return reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get();

  // TODO(soon):  Benchmark this alternate implementation, which I suspect may make better use of
  //   the x86 SIB byte.  Also use it for all the other getData/setData implementations below, and
  //   the various non-inline methods that look up pointers.
  //   Also if using this, consider changing ptr back to void* instead of byte*.
//  return reinterpret_cast<WireValue<T>*>(ptr)[
909
//      index / ELEMENTS * (step / capnp::bitsPerElement<T>())].get();
910 911 912
}

template <>
913
inline bool ListBuilder::getDataElement<bool>(ElementCount index) {
914
  // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
915
  BitCount bindex = index * step;
916
  byte* b = ptr + bindex / BITS_PER_BYTE;
917
  return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
918 919
}

920
template <>
921
inline Void ListBuilder::getDataElement<Void>(ElementCount index) {
922 923 924
  return Void::VOID;
}

925
template <typename T>
926
inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer<T> value) {
927
  reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->set(value);
928 929 930
}

template <>
931
inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) {
932 933
  // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
  BitCount bindex = index * (1 * BITS / ELEMENTS);
934
  byte* b = ptr + bindex / BITS_PER_BYTE;
935 936 937
  uint bitnum = bindex % BITS_PER_BYTE / BITS;
  *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
                                 | (static_cast<uint8_t>(value) << bitnum);
938 939
}

940
template <>
941
inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) {}
942

943 944
// -------------------------------------------------------------------

945
inline ElementCount ListReader::size() const { return elementCount; }
946 947

template <typename T>
948
inline T ListReader::getDataElement(ElementCount index) const {
949
  return reinterpret_cast<const WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get();
950 951 952
}

template <>
953
inline bool ListReader::getDataElement<bool>(ElementCount index) const {
954
  // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
955
  BitCount bindex = index * step;
956
  const byte* b = ptr + bindex / BITS_PER_BYTE;
957
  return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
958 959
}

960 961 962 963 964
template <>
inline Void ListReader::getDataElement<Void>(ElementCount index) const {
  return Void::VOID;
}

965
// These are defined in the source file.
966 967 968
template <> typename Text::Builder StructBuilder::initBlobField<Text>(WirePointerCount ptrIndex, ByteCount size);
template <> void StructBuilder::setBlobField<Text>(WirePointerCount ptrIndex, typename Text::Reader value);
template <> typename Text::Builder StructBuilder::getBlobField<Text>(WirePointerCount ptrIndex, const void* defaultValue, ByteCount defaultSize);
969
template <> typename Text::Reader StructReader::getBlobField<Text>(WirePointerCount ptrIndex, const void* defaultValue, ByteCount defaultSize) const;
970 971 972
template <> typename Text::Builder ListBuilder::initBlobElement<Text>(ElementCount index, ByteCount size);
template <> void ListBuilder::setBlobElement<Text>(ElementCount index, typename Text::Reader value);
template <> typename Text::Builder ListBuilder::getBlobElement<Text>(ElementCount index);
973 974
template <> typename Text::Reader ListReader::getBlobElement<Text>(ElementCount index) const;

975 976 977
template <> typename Data::Builder StructBuilder::initBlobField<Data>(WirePointerCount ptrIndex, ByteCount size);
template <> void StructBuilder::setBlobField<Data>(WirePointerCount ptrIndex, typename Data::Reader value);
template <> typename Data::Builder StructBuilder::getBlobField<Data>(WirePointerCount ptrIndex, const void* defaultValue, ByteCount defaultSize);
978
template <> typename Data::Reader StructReader::getBlobField<Data>(WirePointerCount ptrIndex, const void* defaultValue, ByteCount defaultSize) const;
979 980 981
template <> typename Data::Builder ListBuilder::initBlobElement<Data>(ElementCount index, ByteCount size);
template <> void ListBuilder::setBlobElement<Data>(ElementCount index, typename Data::Reader value);
template <> typename Data::Builder ListBuilder::getBlobElement<Data>(ElementCount index);
982 983
template <> typename Data::Reader ListReader::getBlobElement<Data>(ElementCount index) const;

984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
// -------------------------------------------------------------------

inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other)
    : segment(other.segment), location(other.location) {
  memcpy(&tag, &other.tag, sizeof(tag));  // Needs memcpy to comply with aliasing rules.
  other.segment = nullptr;
  other.location = nullptr;
}

inline OrphanBuilder::~OrphanBuilder() {
  if (segment != nullptr) euthanize();
}

inline OrphanBuilder& OrphanBuilder::operator=(OrphanBuilder&& other) {
  // With normal smart pointers, it's important to handle the case where the incoming pointer
  // is actually transitively owned by this one.  In this case, euthanize() would destroy `other`
  // before we copied it.  This isn't possible in the case of `OrphanBuilder` because it only
  // owns message objects, and `other` is not itself a message object, therefore cannot possibly
  // be transitively owned by `this`.

  if (segment != nullptr) euthanize();
  segment = other.segment;
  location = other.location;
  memcpy(&tag, &other.tag, sizeof(tag));  // Needs memcpy to comply with aliasing rules.
  other.segment = nullptr;
  other.location = nullptr;
  return *this;
}

1013
}  // namespace _ (private)
1014
}  // namespace capnp
1015

Kenton Varda's avatar
Kenton Varda committed
1016
#endif  // CAPNP_LAYOUT_H_