layout.h 48.5 KB
Newer Older
1
// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
Kenton Varda's avatar
Kenton Varda committed
2
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
21

Kenton Varda's avatar
Kenton Varda committed
22 23
// This file is NOT intended for use by clients, except in generated code.
//
Kenton Varda's avatar
Kenton Varda committed
24 25 26 27
// 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
28

Kenton Varda's avatar
Kenton Varda committed
29 30
#ifndef CAPNP_LAYOUT_H_
#define CAPNP_LAYOUT_H_
31

32
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
33 34 35
#pragma GCC system_header
#endif

Kenton Varda's avatar
Kenton Varda committed
36
#include <kj/common.h>
37
#include <kj/memory.h>
38
#include "common.h"
Kenton Varda's avatar
Kenton Varda committed
39
#include "blob.h"
40
#include "endian.h"
41

42
#if (defined(__mips__) || defined(__hppa__)) && !defined(CAPNP_CANONICALIZE_NAN)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#define CAPNP_CANONICALIZE_NAN 1
// Explicitly detect NaNs and canonicalize them to the quiet NaN value as would be returned by
// __builtin_nan("") on systems implementing the IEEE-754 recommended (but not required) NaN
// signalling/quiet differentiation (such as x86).  Unfortunately, some architectures -- in
// particular, MIPS -- represent quiet vs. signalling nans differently than the rest of the world.
// Canonicalizing them makes output consistent (which is important!), but hurts performance
// slightly.
//
// Note that trying to convert MIPS NaNs to standard NaNs without losing data doesn't work.
// Signaling vs. quiet is indicated by a bit, with the meaning being the opposite on MIPS vs.
// everyone else.  It would be great if we could just flip that bit, but we can't, because if the
// significand is all-zero, then the value is infinity rather than NaN.  This means that on most
// machines, where the bit indicates quietness, there is one more quiet NaN value than signalling
// NaN value, whereas on MIPS there is one more sNaN than qNaN, and thus there is no isomorphic
// mapping that properly preserves quietness.  Instead of doing something hacky, we just give up
// and blow away NaN payloads, because no one uses them anyway.
#endif

61
namespace capnp {
62

63
#if !CAPNP_LITE
64
class ClientHook;
65
#endif  // !CAPNP_LITE
66

67
namespace _ {  // private
Kenton Varda's avatar
Kenton Varda committed
68

69 70
class PointerBuilder;
class PointerReader;
71 72 73 74
class StructBuilder;
class StructReader;
class ListBuilder;
class ListReader;
75
class OrphanBuilder;
76
struct WirePointer;
77
struct WireHelpers;
78 79
class SegmentReader;
class SegmentBuilder;
80
class Arena;
81
class BuilderArena;
82

83
// =============================================================================
84 85

typedef decltype(BITS / ELEMENTS) BitsPerElement;
86
typedef decltype(POINTERS / ELEMENTS) PointersPerElement;
87

Kenton Varda's avatar
Kenton Varda committed
88 89 90 91 92 93 94 95 96 97
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
};
98

99
inline KJ_CONSTEXPR() BitsPerElement dataBitsPerElement(ElementSize size) {
100
  return _::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)];
101 102
}

103 104
inline constexpr PointersPerElement pointersPerElement(ElementSize size) {
  return size == ElementSize::POINTER ? 1 * POINTERS / ELEMENTS : 0 * POINTERS / ELEMENTS;
105 106
}

107
template <size_t size> struct ElementSizeForByteSize;
108 109 110 111
template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; };
template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; };
template <> struct ElementSizeForByteSize<4> { static constexpr ElementSize value = ElementSize::FOUR_BYTES; };
template <> struct ElementSizeForByteSize<8> { static constexpr ElementSize value = ElementSize::EIGHT_BYTES; };
112 113

template <typename T> struct ElementSizeForType {
114
  static constexpr ElementSize value =
115
      // Primitive types that aren't special-cased below can be determined from sizeof().
116
      CAPNP_KIND(T) == Kind::PRIMITIVE ? ElementSizeForByteSize<sizeof(T)>::value :
117 118
      CAPNP_KIND(T) == Kind::ENUM ? ElementSize::TWO_BYTES :
      CAPNP_KIND(T) == Kind::STRUCT ? ElementSize::INLINE_COMPOSITE :
119 120

      // Everything else is a pointer.
121
      ElementSize::POINTER;
122 123
};

124
// Void and bool are special.
125 126
template <> struct ElementSizeForType<Void> { static constexpr ElementSize value = ElementSize::VOID; };
template <> struct ElementSizeForType<bool> { static constexpr ElementSize value = ElementSize::BIT; };
127

128
// Lists and blobs are pointers, not structs.
129
template <typename T, Kind K> struct ElementSizeForType<List<T, K>> {
130
  static constexpr ElementSize value = ElementSize::POINTER;
131 132
};
template <> struct ElementSizeForType<Text> {
133
  static constexpr ElementSize value = ElementSize::POINTER;
134 135
};
template <> struct ElementSizeForType<Data> {
136
  static constexpr ElementSize value = ElementSize::POINTER;
137
};
138

139
template <typename T>
140
inline constexpr ElementSize elementSizeForType() {
141 142 143
  return ElementSizeForType<T>::value;
}

144 145 146 147 148 149 150 151 152 153 154 155 156 157
struct MessageSizeCounts {
  WordCount64 wordCount;
  uint capCount;

  MessageSizeCounts& operator+=(const MessageSizeCounts& other) {
    wordCount += other.wordCount;
    capCount += other.capCount;
    return *this;
  }

  MessageSize asPublic() {
    return MessageSize { wordCount / WORDS, capCount };
  }
};
158 159 160

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

161 162 163 164 165 166 167 168 169
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];
};

170 171
struct StructSize {
  WordCount16 data;
172
  WirePointerCount16 pointers;
173

174
  inline constexpr WordCount total() const { return data + pointers * WORDS_PER_POINTER; }
175 176

  StructSize() = default;
177 178
  inline constexpr StructSize(WordCount data, WirePointerCount pointers)
      : data(data), pointers(pointers) {}
179 180
};

181
template <typename T, typename CapnpPrivate = typename T::_capnpPrivate>
182
inline constexpr StructSize structSize() {
183
  return StructSize(CapnpPrivate::dataWordSize * WORDS, CapnpPrivate::pointerCount * POINTERS);
184
}
185

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
template <typename T, typename CapnpPrivate = typename T::_capnpPrivate,
          typename = kj::EnableIf<CAPNP_KIND(T) == Kind::STRUCT>>
inline constexpr StructSize minStructSizeForElement() {
  // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough
  // to hold a T.

  return StructSize(CapnpPrivate::dataWordSize * WORDS, CapnpPrivate::pointerCount * POINTERS);
}

template <typename T, typename = kj::EnableIf<CAPNP_KIND(T) != Kind::STRUCT>>
inline constexpr StructSize minStructSizeForElement() {
  // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough
  // to hold a T.

  return StructSize(
      dataBitsPerElement(elementSizeForType<T>()) * ELEMENTS > 0 * BITS ? 1 * WORDS : 0 * WORDS,
      pointersPerElement(elementSizeForType<T>()) * ELEMENTS);
}

205 206
// -------------------------------------------------------------------
// Masking of default values
207

208
template <typename T, Kind kind = CAPNP_KIND(T)> struct Mask_;
209 210 211 212
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; };
213

214
template <typename T> struct Mask_<T, Kind::OTHER> {
215 216 217
  // Union discriminants end up here.
  static_assert(sizeof(T) == 2, "Don't know how to mask this type.");
  typedef uint16_t Type;
218 219
};

220
template <typename T>
221
using Mask = typename Mask_<T>::Type;
222 223

template <typename T>
224
KJ_ALWAYS_INLINE(Mask<T> mask(T value, Mask<T> mask));
225
template <typename T>
226
KJ_ALWAYS_INLINE(T unmask(Mask<T> value, Mask<T> mask));
227 228

template <typename T>
229 230
inline Mask<T> mask(T value, Mask<T> mask) {
  return static_cast<Mask<T> >(value) ^ mask;
231 232 233 234
}

template <>
inline uint32_t mask<float>(float value, uint32_t mask) {
235 236
#if CAPNP_CANONICALIZE_NAN
  if (value != value) {
237
    return 0x7fc00000u ^ mask;
238 239 240
  }
#endif

241 242 243 244 245 246 247 248
  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) {
249 250
#if CAPNP_CANONICALIZE_NAN
  if (value != value) {
251
    return 0x7ff8000000000000ull ^ mask;
252 253 254
  }
#endif

255 256 257 258 259 260 261
  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>
262
inline T unmask(Mask<T> value, Mask<T> mask) {
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
  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;
}

284 285
// -------------------------------------------------------------------

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
class CapTableReader {
public:
#if !CAPNP_LITE
  virtual kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) = 0;
  // Extract the capability at the given index.  If the index is invalid, returns null.
#endif  // !CAPNP_LITE
};

class CapTableBuilder: public CapTableReader {
public:
#if !CAPNP_LITE
  virtual uint injectCap(kj::Own<ClientHook>&& cap) = 0;
  // Add the capability to the message and return its index.  If the same ClientHook is injected
  // twice, this may return the same index both times, but in this case dropCap() needs to be
  // called an equal number of times to actually remove the cap.

  virtual void dropCap(uint index) = 0;
  // Remove a capability injected earlier.  Called when the pointer is overwritten or zero'd out.
#endif  // !CAPNP_LITE
};

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

309 310 311 312
class PointerBuilder: public kj::DisallowConstCopy {
  // Represents a single pointer, usually embedded in a struct or a list.

public:
313
  inline PointerBuilder(): segment(nullptr), capTable(nullptr), pointer(nullptr) {}
314

315 316
  static inline PointerBuilder getRoot(
      SegmentBuilder* segment, CapTableBuilder* capTable, word* location);
Kenton Varda's avatar
Kenton Varda committed
317 318 319
  // Get a PointerBuilder representing a message root located in the given segment at the given
  // location.

320
  inline bool isNull() { return getPointerType() == PointerType::NULL_; }
321
  PointerType getPointerType() const;
322 323

  StructBuilder getStruct(StructSize size, const word* defaultValue);
324
  ListBuilder getList(ElementSize elementSize, const word* defaultValue);
325
  ListBuilder getStructList(StructSize elementSize, const word* defaultValue);
326
  ListBuilder getListAnySize(const word* defaultValue);
327
  template <typename T> typename T::Builder getBlob(const void* defaultValue,ByteCount defaultSize);
328
#if !CAPNP_LITE
329
  kj::Own<ClientHook> getCapability();
330
#endif  // !CAPNP_LITE
331 332 333 334 335
  // Get methods:  Get the value.  If it is null, initialize it to a copy of the default value.
  // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
  // simple byte array for blobs.

  StructBuilder initStruct(StructSize size);
336
  ListBuilder initList(ElementSize elementSize, ElementCount elementCount);
337 338 339 340 341
  ListBuilder initStructList(ElementCount elementCount, StructSize size);
  template <typename T> typename T::Builder initBlob(ByteCount size);
  // Init methods:  Initialize the pointer to a newly-allocated object, discarding the existing
  // object.

Matthew Maurer's avatar
Matthew Maurer committed
342 343
  void setStruct(const StructReader& value, bool canonical = false);
  void setList(const ListReader& value, bool canonical = false);
344
  template <typename T> void setBlob(typename T::Reader value);
345
#if !CAPNP_LITE
346
  void setCapability(kj::Own<ClientHook>&& cap);
347
#endif  // !CAPNP_LITE
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
  // Set methods:  Initialize the pointer to a newly-allocated copy of the given value, discarding
  // the existing object.

  void adopt(OrphanBuilder&& orphan);
  // Set the pointer to point at the given orphaned value.

  OrphanBuilder disown();
  // Set the pointer to null and return its previous value as an orphan.

  void clear();
  // Clear the pointer to null, discarding its previous value.

  void transferFrom(PointerBuilder other);
  // Equivalent to `adopt(other.disown())`.

Matthew Maurer's avatar
Matthew Maurer committed
363
  void copyFrom(PointerReader other, bool canonical = false);
364
  // Equivalent to `set(other.get())`.
Matthew Maurer's avatar
Matthew Maurer committed
365 366
  // If you set the canonical flag, it will attempt to lay the target out
  // canonically, provided enough space is available.
367

368 369
  PointerReader asReader() const;

370
  BuilderArena* getArena() const;
371 372
  // Get the arena containing this pointer.

373 374 375 376 377 378
  CapTableBuilder* getCapTable();
  // Gets the capability context in which this object is operating.

  PointerBuilder imbue(CapTableBuilder* capTable);
  // Return a copy of this builder except using the given capability context.

379 380
private:
  SegmentBuilder* segment;     // Memory segment in which the pointer resides.
381
  CapTableBuilder* capTable;   // Table of capability indexes.
382 383
  WirePointer* pointer;        // Pointer to the pointer.

384 385
  inline PointerBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* pointer)
      : segment(segment), capTable(capTable), pointer(pointer) {}
386 387 388

  friend class StructBuilder;
  friend class ListBuilder;
389
  friend class OrphanBuilder;
390 391 392 393
};

class PointerReader {
public:
394 395
  inline PointerReader()
      : segment(nullptr), capTable(nullptr), pointer(nullptr), nestingLimit(0x7fffffff) {}
396

397 398
  static PointerReader getRoot(SegmentReader* segment, CapTableReader* capTable,
                               const word* location, int nestingLimit);
Kenton Varda's avatar
Kenton Varda committed
399 400 401 402 403 404
  // Get a PointerReader representing a message root located in the given segment at the given
  // location.

  static inline PointerReader getRootUnchecked(const word* location);
  // Get a PointerReader for an unchecked message.

405
  MessageSizeCounts targetSize() const;
Kenton Varda's avatar
Kenton Varda committed
406 407 408 409 410 411
  // Return the total size of the target object 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 object
  // 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.

412 413
  inline bool isNull() const { return getPointerType() == PointerType::NULL_; }
  PointerType getPointerType() const;
414 415

  StructReader getStruct(const word* defaultValue) const;
416
  ListReader getList(ElementSize expectedElementSize, const word* defaultValue) const;
417
  ListReader getListAnySize(const word* defaultValue) const;
418 419
  template <typename T>
  typename T::Reader getBlob(const void* defaultValue, ByteCount defaultSize) const;
420
#if !CAPNP_LITE
421
  kj::Own<ClientHook> getCapability() const;
422
#endif  // !CAPNP_LITE
423 424 425 426 427 428 429 430 431
  // Get methods:  Get the value.  If it is null, return the default value instead.
  // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
  // simple byte array for blobs.

  const word* getUnchecked() 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.

432 433 434
  kj::Maybe<Arena&> getArena() const;
  // Get the arena containing this pointer.

435 436 437
  CapTableReader* getCapTable();
  // Gets the capability context in which this object is operating.

438 439 440
  PointerReader imbue(CapTableReader* capTable) const;
  // Return a copy of this reader except using the given capability context.

Matthew Maurer's avatar
Matthew Maurer committed
441 442 443 444 445 446 447
  bool isCanonical(const word **readHead);
  // Validate this pointer's canonicity, subject to the conditions:
  // * All data to the left of readHead has been read thus far (for pointer
  //   ordering)
  // * All pointers in preorder have already been checked
  // * This pointer is in the first and only segment of the message

448 449
private:
  SegmentReader* segment;      // Memory segment in which the pointer resides.
450
  CapTableReader* capTable;    // Table of capability indexes.
451 452 453 454 455 456
  const WirePointer* pointer;  // Pointer to the pointer.  null = treat as null pointer.

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

457 458 459
  inline PointerReader(SegmentReader* segment, CapTableReader* capTable,
                       const WirePointer* pointer, int nestingLimit)
      : segment(segment), capTable(capTable), pointer(pointer), nestingLimit(nestingLimit) {}
460 461 462

  friend class StructReader;
  friend class ListReader;
463
  friend class PointerBuilder;
464
  friend class OrphanBuilder;
465 466
};

467
// -------------------------------------------------------------------
Kenton Varda's avatar
Kenton Varda committed
468

469
class StructBuilder: public kj::DisallowConstCopy {
470
public:
471
  inline StructBuilder(): segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr) {}
472

473 474 475 476
  inline word* getLocation() { return reinterpret_cast<word*>(data); }
  // Get the object's location.  Only valid for independently-allocated objects (i.e. not list
  // elements).

477
  inline BitCount getDataSectionSize() const { return dataSize; }
478
  inline WirePointerCount getPointerSectionSize() const { return pointerCount; }
479
  inline kj::ArrayPtr<byte> getDataSectionAsBlob();
480
  inline _::ListBuilder getPointerSectionAsList();
481

482 483 484 485
  template <typename T>
  KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset));
  // Return true if the field is set to something other than its default value.

486
  template <typename T>
487
  KJ_ALWAYS_INLINE(T getDataField(ElementCount offset));
488
  // Gets the data field value of the given type at the given offset.  The offset is measured in
489 490
  // multiples of the field size, determined by the type.

491
  template <typename T>
492
  KJ_ALWAYS_INLINE(T getDataField(ElementCount offset, Mask<T> mask));
493 494 495
  // Like getDataField() but applies the given XOR mask to the data on load.  Used for reading
  // fields with non-zero default values.

496
  template <typename T>
497
  KJ_ALWAYS_INLINE(void setDataField(
498
      ElementCount offset, kj::NoInfer<T> value));
499 500
  // Sets the data field value at the given offset.

501
  template <typename T>
502
  KJ_ALWAYS_INLINE(void setDataField(
503
      ElementCount offset, kj::NoInfer<T> value, Mask<T> mask));
504 505 506
  // Like setDataField() but applies the given XOR mask before storing.  Used for writing fields
  // with non-zero default values.

507 508
  KJ_ALWAYS_INLINE(PointerBuilder getPointerField(WirePointerCount ptrIndex));
  // Get a builder for a pointer field given the index within the pointer section.
509

510 511 512
  void clearAll();
  // Clear all pointers and data.

513 514 515 516 517
  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.

518 519 520 521 522
  void copyContentFrom(StructReader other);
  // Copy content from `other`.  If `other`'s sections are larger than this, the extra data is not
  // copied, meaning there is a risk of data loss when copying from messages built with future
  // versions of the protocol.

523
  StructReader asReader() const;
524
  // Gets a StructReader pointing at the same memory.
525

526 527 528
  BuilderArena* getArena();
  // Gets the arena in which this object is allocated.

529 530 531 532 533 534
  CapTableBuilder* getCapTable();
  // Gets the capability context in which this object is operating.

  StructBuilder imbue(CapTableBuilder* capTable);
  // Return a copy of this builder except using the given capability context.

535
private:
536
  SegmentBuilder* segment;     // Memory segment in which the struct resides.
537
  CapTableBuilder* capTable;   // Table of capability indexes.
Kenton Varda's avatar
Kenton Varda committed
538
  void* data;                  // Pointer to the encoded data.
539
  WirePointer* pointers;   // Pointer to the encoded pointers.
540

541
  BitCount32 dataSize;
542
  // Size of data section.  We use a bit count rather than a word count to more easily handle the
543 544
  // case of struct lists encoded with less than a word per element.

545
  WirePointerCount16 pointerCount;  // Size of the pointer section.
546

547 548
  inline StructBuilder(SegmentBuilder* segment, CapTableBuilder* capTable,
                       void* data, WirePointer* pointers,
549
                       BitCount dataSize, WirePointerCount pointerCount)
550
      : segment(segment), capTable(capTable), data(data), pointers(pointers),
551
        dataSize(dataSize), pointerCount(pointerCount) {}
552

553
  friend class ListBuilder;
554
  friend struct WireHelpers;
555
  friend class OrphanBuilder;
556 557
};

558
class StructReader {
559
public:
560
  inline StructReader()
561
      : segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr), dataSize(0),
562
        pointerCount(0), nestingLimit(0x7fffffff) {}
563 564 565
  inline StructReader(kj::ArrayPtr<const word> data)
      : segment(nullptr), capTable(nullptr), data(data.begin()), pointers(nullptr),
        dataSize(data.size() * WORDS * BITS_PER_WORD), pointerCount(0), nestingLimit(0x7fffffff) {}
566

Kenton Varda's avatar
Kenton Varda committed
567 568
  const void* getLocation() const { return data; }

569
  inline BitCount getDataSectionSize() const { return dataSize; }
570
  inline WirePointerCount getPointerSectionSize() const { return pointerCount; }
571
  inline kj::ArrayPtr<const byte> getDataSectionAsBlob();
572
  inline _::ListReader getPointerSectionAsList();
573

574 575
  kj::Array<word> canonicalize();

576 577 578 579
  template <typename T>
  KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset) const);
  // Return true if the field is set to something other than its default value.

580
  template <typename T>
581
  KJ_ALWAYS_INLINE(T getDataField(ElementCount offset) const);
582
  // Get the data field value of the given type at the given offset.  The offset is measured in
583
  // multiples of the field size, determined by the type.  Returns zero if the offset is past the
584
  // end of the struct's data section.
585 586

  template <typename T>
587
  KJ_ALWAYS_INLINE(
588
      T getDataField(ElementCount offset, Mask<T> mask) const);
589 590
  // Like getDataField(offset), but applies the given XOR mask to the result.  Used for reading
  // fields with non-zero default values.
591

592 593 594
  KJ_ALWAYS_INLINE(PointerReader getPointerField(WirePointerCount ptrIndex) const);
  // Get a reader for a pointer field given the index within the pointer section.  If the index
  // is out-of-bounds, returns a null pointer.
595

596
  MessageSizeCounts totalSize() const;
597 598 599 600 601 602
  // 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.

603 604 605
  CapTableReader* getCapTable();
  // Gets the capability context in which this object is operating.

606 607 608
  StructReader imbue(CapTableReader* capTable) const;
  // Return a copy of this reader except using the given capability context.

Matthew Maurer's avatar
Matthew Maurer committed
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
  bool isCanonical(const word **readHead, const word **ptrHead,
                   bool *dataTrunc, bool *ptrTrunc);
  // Validate this pointer's canonicity, subject to the conditions:
  // * All data to the left of readHead has been read thus far (for pointer
  //   ordering)
  // * All pointers in preorder have already been checked
  // * This pointer is in the first and only segment of the message
  //
  // If this function returns false, the struct is non-canonical. If it
  // returns true, then:
  // * If it is a composite in a list, it is canonical if at least one struct
  //   in the list outputs dataTrunc = 1, and at least one outputs ptrTrunc = 1
  // * If it is derived from a struct pointer, it is canonical if
  //   dataTrunc = 1 AND ptrTrunc = 1

624
private:
625 626
  SegmentReader* segment;    // Memory segment in which the struct resides.
  CapTableReader* capTable;  // Table of capability indexes.
627

628
  const void* data;
629
  const WirePointer* pointers;
630

631
  BitCount32 dataSize;
632
  // Size of data section.  We use a bit count rather than a word count to more easily handle the
633 634
  // case of struct lists encoded with less than a word per element.

635
  WirePointerCount16 pointerCount;  // Size of the pointer section.
636

637
  int nestingLimit;
638 639
  // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
  // Once this reaches zero, further pointers will be pruned.
640
  // TODO(perf):  Limit to 16 bits for better packing?
641

642 643
  inline StructReader(SegmentReader* segment, CapTableReader* capTable,
                      const void* data, const WirePointer* pointers,
644
                      BitCount dataSize, WirePointerCount pointerCount, int nestingLimit)
645
      : segment(segment), capTable(capTable), data(data), pointers(pointers),
646
        dataSize(dataSize), pointerCount(pointerCount),
647
        nestingLimit(nestingLimit) {}
648

649 650
  friend class ListReader;
  friend class StructBuilder;
651 652 653 654 655
  friend struct WireHelpers;
};

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

656
class ListBuilder: public kj::DisallowConstCopy {
657
public:
658
  inline explicit ListBuilder(ElementSize elementSize)
659
      : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(0 * ELEMENTS),
660 661
        step(0 * BITS / ELEMENTS), structDataSize(0 * BITS), structPointerCount(0 * POINTERS),
        elementSize(elementSize) {}
662

663
  inline word* getLocation() {
664
    // Get the object's location.
665

666
    if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) {
667
      return reinterpret_cast<word*>(ptr) - POINTER_SIZE_IN_WORDS;
668 669
    } else {
      return reinterpret_cast<word*>(ptr);
670 671 672
    }
  }

673 674
  inline ElementSize getElementSize() const { return elementSize; }

675
  inline ElementCount size() const;
676 677
  // The number of elements in the list.

678 679 680 681
  Text::Builder asText();
  Data::Builder asData();
  // Reinterpret the list as a blob.  Throws an exception if the elements are not byte-sized.

682
  template <typename T>
683
  KJ_ALWAYS_INLINE(T getDataElement(ElementCount index));
684 685 686
  // Get the element of the given type at the given index.

  template <typename T>
687
  KJ_ALWAYS_INLINE(void setDataElement(
688
      ElementCount index, kj::NoInfer<T> value));
689
  // Set the element at the given index.
690

691
  KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index));
Kenton Varda's avatar
Kenton Varda committed
692

693
  StructBuilder getStructElement(ElementCount index);
694

695 696
  ListReader asReader() const;
  // Get a ListReader pointing at the same memory.
697

698 699 700
  BuilderArena* getArena();
  // Gets the arena in which this object is allocated.

701 702 703 704 705 706
  CapTableBuilder* getCapTable();
  // Gets the capability context in which this object is operating.

  ListBuilder imbue(CapTableBuilder* capTable);
  // Return a copy of this builder except using the given capability context.

707
private:
708 709
  SegmentBuilder* segment;    // Memory segment in which the list resides.
  CapTableBuilder* capTable;  // Table of capability indexes.
710

711
  byte* ptr;  // Pointer to list content.
712

713
  ElementCount elementCount;  // Number of elements in the list.
714

715
  decltype(BITS / ELEMENTS) step;
716
  // The distance between elements.
717 718

  BitCount32 structDataSize;
719
  WirePointerCount16 structPointerCount;
720 721
  // 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.
722

723 724
  ElementSize elementSize;
  // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE
725 726
  // from other types when the overall size is exactly zero or one words.

727
  inline ListBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* ptr,
728
                     decltype(BITS / ELEMENTS) step, ElementCount size,
729
                     BitCount structDataSize, WirePointerCount structPointerCount,
730
                     ElementSize elementSize)
731
      : segment(segment), capTable(capTable), ptr(reinterpret_cast<byte*>(ptr)),
732
        elementCount(size), step(step), structDataSize(structDataSize),
733
        structPointerCount(structPointerCount), elementSize(elementSize) {}
734

735
  friend class StructBuilder;
736
  friend struct WireHelpers;
737
  friend class OrphanBuilder;
738 739
};

740
class ListReader {
741
public:
742
  inline explicit ListReader(ElementSize elementSize)
743 744 745
      : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(0),
        step(0 * BITS / ELEMENTS), structDataSize(0), structPointerCount(0),
        elementSize(elementSize), nestingLimit(0x7fffffff) {}
746

747
  inline ElementCount size() const;
748 749
  // The number of elements in the list.

750 751
  inline ElementSize getElementSize() const { return elementSize; }

752 753 754 755
  Text::Reader asText();
  Data::Reader asData();
  // Reinterpret the list as a blob.  Throws an exception if the elements are not byte-sized.

756
  kj::ArrayPtr<const byte> asRawBytes();
757

758
  template <typename T>
759
  KJ_ALWAYS_INLINE(T getDataElement(ElementCount index) const);
760 761
  // Get the element of the given type at the given index.

762
  KJ_ALWAYS_INLINE(PointerReader getPointerElement(ElementCount index) const);
763

764
  StructReader getStructElement(ElementCount index) const;
765

766 767 768
  CapTableReader* getCapTable();
  // Gets the capability context in which this object is operating.

769 770 771
  ListReader imbue(CapTableReader* capTable) const;
  // Return a copy of this reader except using the given capability context.

772
  bool isCanonical(const word **readHead, const WirePointer* ref);
Matthew Maurer's avatar
Matthew Maurer committed
773 774 775 776 777 778
  // Validate this pointer's canonicity, subject to the conditions:
  // * All data to the left of readHead has been read thus far (for pointer
  //   ordering)
  // * All pointers in preorder have already been checked
  // * This pointer is in the first and only segment of the message

779
private:
780 781
  SegmentReader* segment;    // Memory segment in which the list resides.
  CapTableReader* capTable;  // Table of capability indexes.
782

783
  const byte* ptr;  // Pointer to list content.
784

785
  ElementCount elementCount;  // Number of elements in the list.
786

787
  decltype(BITS / ELEMENTS) step;
788
  // The distance between elements.
789

790
  BitCount32 structDataSize;
791
  WirePointerCount16 structPointerCount;
792 793
  // 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.
794

795 796
  ElementSize elementSize;
  // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE
797 798
  // from other types when the overall size is exactly zero or one words.

799
  int nestingLimit;
800 801 802
  // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
  // Once this reaches zero, further pointers will be pruned.

803
  inline ListReader(SegmentReader* segment, CapTableReader* capTable, const void* ptr,
804
                    ElementCount elementCount, decltype(BITS / ELEMENTS) step,
805
                    BitCount structDataSize, WirePointerCount structPointerCount,
806
                    ElementSize elementSize, int nestingLimit)
807 808
      : segment(segment), capTable(capTable), ptr(reinterpret_cast<const byte*>(ptr)),
        elementCount(elementCount), step(step), structDataSize(structDataSize),
809 810
        structPointerCount(structPointerCount), elementSize(elementSize),
        nestingLimit(nestingLimit) {}
811

812 813
  friend class StructReader;
  friend class ListBuilder;
814
  friend struct WireHelpers;
815
  friend class OrphanBuilder;
816 817
};

818 819
// -------------------------------------------------------------------

820 821
class OrphanBuilder {
public:
822 823 824
  inline OrphanBuilder(): segment(nullptr), capTable(nullptr), location(nullptr) {
    memset(&tag, 0, sizeof(tag));
  }
825
  OrphanBuilder(const OrphanBuilder& other) = delete;
826
  inline OrphanBuilder(OrphanBuilder&& other) noexcept;
827
  inline ~OrphanBuilder() noexcept(false);
828

829 830 831 832 833 834 835 836 837 838 839 840 841
  static OrphanBuilder initStruct(BuilderArena* arena, CapTableBuilder* capTable, StructSize size);
  static OrphanBuilder initList(BuilderArena* arena, CapTableBuilder* capTable,
                                ElementCount elementCount, ElementSize elementSize);
  static OrphanBuilder initStructList(BuilderArena* arena, CapTableBuilder* capTable,
                                      ElementCount elementCount, StructSize elementSize);
  static OrphanBuilder initText(BuilderArena* arena, CapTableBuilder* capTable, ByteCount size);
  static OrphanBuilder initData(BuilderArena* arena, CapTableBuilder* capTable, ByteCount size);

  static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, StructReader copyFrom);
  static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, ListReader copyFrom);
  static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, PointerReader copyFrom);
  static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, Text::Reader copyFrom);
  static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, Data::Reader copyFrom);
842
#if !CAPNP_LITE
843 844
  static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable,
                            kj::Own<ClientHook> copyFrom);
845
#endif  // !CAPNP_LITE
846

847 848 849 850
  static OrphanBuilder concat(BuilderArena* arena, CapTableBuilder* capTable,
                              ElementSize expectedElementSize, StructSize expectedStructSize,
                              kj::ArrayPtr<const ListReader> lists);

851 852
  static OrphanBuilder referenceExternalData(BuilderArena* arena, Data::Reader data);

853 854 855
  OrphanBuilder& operator=(const OrphanBuilder& other) = delete;
  inline OrphanBuilder& operator=(OrphanBuilder&& other);

856 857
  inline bool operator==(decltype(nullptr)) const { return location == nullptr; }
  inline bool operator!=(decltype(nullptr)) const { return location != nullptr; }
858 859 860 861

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

862
  ListBuilder asList(ElementSize elementSize);
863 864 865 866 867 868 869 870 871 872
  // 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.

873
  StructReader asStructReader(StructSize size) const;
874
  ListReader asListReader(ElementSize elementSize) const;
875
#if !CAPNP_LITE
876
  kj::Own<ClientHook> asCapability() const;
877
#endif  // !CAPNP_LITE
878 879 880
  Text::Reader asTextReader() const;
  Data::Reader asDataReader() const;

881 882 883 884 885 886 887 888
  bool truncate(ElementCount size, bool isText) KJ_WARN_UNUSED_RESULT;
  // Resize the orphan list to the given size. Returns false if the list is currently empty but
  // the requested size is non-zero, in which case the caller will need to allocate a new list.

  void truncate(ElementCount size, ElementSize elementSize);
  void truncate(ElementCount size, StructSize elementSize);
  void truncateText(ElementCount size);
  // Versions of truncate() that know how to allocate a new list if needed.
889

890 891 892 893 894 895 896
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.
  //
897 898 899 900 901 902 903
  // This may be a FAR pointer.  Even in that case, `location` points to the eventual destination
  // of that far pointer.  The reason we keep the far pointer around rather than just making `tag`
  // represent the final destination is because if the eventual adopter of the pointer is not in
  // the target's segment then it may be useful to reuse the far pointer landing pad.
  //
  // If `tag` is not a far pointer, its offset is garbage; only `location` points to the actual
  // target.
904 905

  SegmentBuilder* segment;
906
  // Segment in which the object resides.
907

908 909 910
  CapTableBuilder* capTable;
  // Table of capability indexes.

911
  word* location;
912
  // Pointer to the object, or nullptr if the pointer is null.  For capabilities, we make this
913
  // 0x1 just so that it is non-null for operator==, but it is never used.
914

915 916 917
  inline OrphanBuilder(const void* tagPtr, SegmentBuilder* segment,
                       CapTableBuilder* capTable, word* location)
      : segment(segment), capTable(capTable), location(location) {
918 919 920 921
    memcpy(&tag, tagPtr, sizeof(tag));
  }

  inline WirePointer* tagAsPtr() { return reinterpret_cast<WirePointer*>(&tag); }
922
  inline const WirePointer* tagAsPtr() const { return reinterpret_cast<const WirePointer*>(&tag); }
923 924 925 926 927 928 929 930

  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;
};

931 932 933
// =======================================================================================
// Internal implementation details...

934 935
// These are defined in the source file.
template <> typename Text::Builder PointerBuilder::initBlob<Text>(ByteCount size);
936
template <> void PointerBuilder::setBlob<Text>(typename Text::Reader value);
937 938 939 940
template <> typename Text::Builder PointerBuilder::getBlob<Text>(const void* defaultValue, ByteCount defaultSize);
template <> typename Text::Reader PointerReader::getBlob<Text>(const void* defaultValue, ByteCount defaultSize) const;

template <> typename Data::Builder PointerBuilder::initBlob<Data>(ByteCount size);
941
template <> void PointerBuilder::setBlob<Data>(typename Data::Reader value);
942 943 944
template <> typename Data::Builder PointerBuilder::getBlob<Data>(const void* defaultValue, ByteCount defaultSize);
template <> typename Data::Reader PointerReader::getBlob<Data>(const void* defaultValue, ByteCount defaultSize) const;

945 946 947
inline PointerBuilder PointerBuilder::getRoot(
    SegmentBuilder* segment, CapTableBuilder* capTable, word* location) {
  return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(location));
Kenton Varda's avatar
Kenton Varda committed
948 949 950
}

inline PointerReader PointerReader::getRootUnchecked(const word* location) {
951 952
  return PointerReader(nullptr, nullptr,
                       reinterpret_cast<const WirePointer*>(location), 0x7fffffff);
Kenton Varda's avatar
Kenton Varda committed
953 954
}

955 956
// -------------------------------------------------------------------

957 958
inline kj::ArrayPtr<byte> StructBuilder::getDataSectionAsBlob() {
  return kj::ArrayPtr<byte>(reinterpret_cast<byte*>(data), dataSize / BITS_PER_BYTE / BYTES);
959 960
}

961
inline _::ListBuilder StructBuilder::getPointerSectionAsList() {
962
  return _::ListBuilder(segment, capTable, pointers, 1 * POINTERS * BITS_PER_POINTER / ELEMENTS,
963
                        pointerCount * (1 * ELEMENTS / POINTERS),
964
                        0 * BITS, 1 * POINTERS, ElementSize::POINTER);
965 966
}

967 968 969 970 971 972 973 974 975 976
template <typename T>
inline bool StructBuilder::hasDataField(ElementCount offset) {
  return getDataField<Mask<T>>(offset) != 0;
}

template <>
inline bool StructBuilder::hasDataField<Void>(ElementCount offset) {
  return false;
}

977
template <typename T>
978
inline T StructBuilder::getDataField(ElementCount offset) {
979
  return reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].get();
980 981 982
}

template <>
983
inline bool StructBuilder::getDataField<bool>(ElementCount offset) {
984
  BitCount boffset = offset * (1 * BITS / ELEMENTS);
985
  byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
986
  return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
987 988
}

989
template <>
990
inline Void StructBuilder::getDataField<Void>(ElementCount offset) {
991
  return VOID;
992 993
}

994
template <typename T>
995
inline T StructBuilder::getDataField(ElementCount offset, Mask<T> mask) {
996
  return unmask<T>(getDataField<Mask<T> >(offset), mask);
997 998
}

999
template <typename T>
1000
inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value) {
1001
  reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].set(value);
1002 1003
}

1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
#if CAPNP_CANONICALIZE_NAN
// Use mask() on floats and doubles to make sure we canonicalize NaNs.
template <>
inline void StructBuilder::setDataField<float>(ElementCount offset, float value) {
  setDataField<uint32_t>(offset, mask<float>(value, 0));
}
template <>
inline void StructBuilder::setDataField<double>(ElementCount offset, double value) {
  setDataField<uint64_t>(offset, mask<double>(value, 0));
}
#endif

1016
template <>
1017
inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) {
1018
  BitCount boffset = offset * (1 * BITS / ELEMENTS);
1019
  byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
1020 1021 1022
  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);
1023 1024
}

1025
template <>
1026
inline void StructBuilder::setDataField<Void>(ElementCount offset, Void value) {}
1027

1028
template <typename T>
1029
inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value, Mask<T> m) {
1030
  setDataField<Mask<T> >(offset, mask<T>(value, m));
1031 1032
}

1033 1034
inline PointerBuilder StructBuilder::getPointerField(WirePointerCount ptrIndex) {
  // Hacky because WirePointer is defined in the .c++ file (so is incomplete here).
1035
  return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(
1036 1037 1038
      reinterpret_cast<word*>(pointers) + ptrIndex * WORDS_PER_POINTER));
}

1039 1040
// -------------------------------------------------------------------

1041 1042
inline kj::ArrayPtr<const byte> StructReader::getDataSectionAsBlob() {
  return kj::ArrayPtr<const byte>(reinterpret_cast<const byte*>(data), dataSize / BITS_PER_BYTE / BYTES);
1043 1044
}

1045
inline _::ListReader StructReader::getPointerSectionAsList() {
1046
  return _::ListReader(segment, capTable, pointers, pointerCount * (1 * ELEMENTS / POINTERS),
1047 1048
                       1 * POINTERS * BITS_PER_POINTER / ELEMENTS, 0 * BITS, 1 * POINTERS,
                       ElementSize::POINTER, nestingLimit);
1049 1050
}

1051
template <typename T>
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
inline bool StructReader::hasDataField(ElementCount offset) const {
  return getDataField<Mask<T>>(offset) != 0;
}

template <>
inline bool StructReader::hasDataField<Void>(ElementCount offset) const {
  return false;
}

template <typename T>
inline T StructReader::getDataField(ElementCount offset) const {
1063
  if ((offset + 1 * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) {
1064
    return reinterpret_cast<const WireValue<T>*>(data)[offset / ELEMENTS].get();
1065
  } else {
1066
    return static_cast<T>(0);
1067
  }
1068 1069 1070
}

template <>
1071
inline bool StructReader::getDataField<bool>(ElementCount offset) const {
1072
  BitCount boffset = offset * (1 * BITS / ELEMENTS);
1073
  if (boffset < dataSize) {
1074
    const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE;
1075 1076
    return (*reinterpret_cast<const uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0;
  } else {
1077
    return false;
1078
  }
1079 1080
}

1081
template <>
1082
inline Void StructReader::getDataField<Void>(ElementCount offset) const {
1083
  return VOID;
1084 1085
}

1086
template <typename T>
1087 1088
T StructReader::getDataField(ElementCount offset, Mask<T> mask) const {
  return unmask<T>(getDataField<Mask<T> >(offset), mask);
1089 1090
}

1091 1092 1093
inline PointerReader StructReader::getPointerField(WirePointerCount ptrIndex) const {
  if (ptrIndex < pointerCount) {
    // Hacky because WirePointer is defined in the .c++ file (so is incomplete here).
1094
    return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>(
1095 1096 1097 1098 1099 1100
        reinterpret_cast<const word*>(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit);
  } else{
    return PointerReader();
  }
}

1101 1102
// -------------------------------------------------------------------

1103
inline ElementCount ListBuilder::size() const { return elementCount; }
1104 1105

template <typename T>
1106
inline T ListBuilder::getDataElement(ElementCount index) {
1107 1108
  return reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get();

Kenton Varda's avatar
Kenton Varda committed
1109
  // TODO(perf):  Benchmark this alternate implementation, which I suspect may make better use of
1110 1111 1112 1113
  //   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)[
1114
//      index / ELEMENTS * (step / capnp::bitsPerElement<T>())].get();
1115 1116 1117
}

template <>
1118
inline bool ListBuilder::getDataElement<bool>(ElementCount index) {
1119 1120
  // Ignore step for bit lists because bit lists cannot be upgraded to struct lists.
  BitCount bindex = index * (1 * BITS / ELEMENTS);
1121
  byte* b = ptr + bindex / BITS_PER_BYTE;
1122
  return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
1123 1124
}

1125
template <>
1126
inline Void ListBuilder::getDataElement<Void>(ElementCount index) {
1127
  return VOID;
1128 1129
}

1130
template <typename T>
1131
inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer<T> value) {
1132
  reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->set(value);
1133 1134
}

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
#if CAPNP_CANONICALIZE_NAN
// Use mask() on floats and doubles to make sure we canonicalize NaNs.
template <>
inline void ListBuilder::setDataElement<float>(ElementCount index, float value) {
  setDataElement<uint32_t>(index, mask<float>(value, 0));
}
template <>
inline void ListBuilder::setDataElement<double>(ElementCount index, double value) {
  setDataElement<uint64_t>(index, mask<double>(value, 0));
}
#endif

1147
template <>
1148
inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) {
1149 1150
  // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
  BitCount bindex = index * (1 * BITS / ELEMENTS);
1151
  byte* b = ptr + bindex / BITS_PER_BYTE;
1152 1153 1154
  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);
1155 1156
}

1157
template <>
1158
inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) {}
1159

1160
inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) {
1161
  return PointerBuilder(segment, capTable,
1162 1163 1164
      reinterpret_cast<WirePointer*>(ptr + index * step / BITS_PER_BYTE));
}

1165 1166
// -------------------------------------------------------------------

1167
inline ElementCount ListReader::size() const { return elementCount; }
1168 1169

template <typename T>
1170
inline T ListReader::getDataElement(ElementCount index) const {
1171
  return reinterpret_cast<const WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get();
1172 1173 1174
}

template <>
1175
inline bool ListReader::getDataElement<bool>(ElementCount index) const {
1176 1177
  // Ignore step for bit lists because bit lists cannot be upgraded to struct lists.
  BitCount bindex = index * (1 * BITS / ELEMENTS);
1178
  const byte* b = ptr + bindex / BITS_PER_BYTE;
1179
  return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0;
1180 1181
}

1182 1183
template <>
inline Void ListReader::getDataElement<Void>(ElementCount index) const {
1184
  return VOID;
1185 1186
}

1187
inline PointerReader ListReader::getPointerElement(ElementCount index) const {
1188
  return PointerReader(segment, capTable,
1189 1190
      reinterpret_cast<const WirePointer*>(ptr + index * step / BITS_PER_BYTE), nestingLimit);
}
1191

1192 1193
// -------------------------------------------------------------------

1194
inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept
1195
    : segment(other.segment), capTable(other.capTable), location(other.location) {
1196 1197 1198 1199 1200
  memcpy(&tag, &other.tag, sizeof(tag));  // Needs memcpy to comply with aliasing rules.
  other.segment = nullptr;
  other.location = nullptr;
}

1201
inline OrphanBuilder::~OrphanBuilder() noexcept(false) {
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
  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;
1214
  capTable = other.capTable;
1215 1216 1217 1218 1219 1220 1221
  location = other.location;
  memcpy(&tag, &other.tag, sizeof(tag));  // Needs memcpy to comply with aliasing rules.
  other.segment = nullptr;
  other.location = nullptr;
  return *this;
}

1222
}  // namespace _ (private)
1223
}  // namespace capnp
1224

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