comparison osx/include/capnp/layout.h @ 147:45360b968bf4

Cap'n Proto v0.6 + build for OSX
author Chris Cannam <cannam@all-day-breakfast.com>
date Mon, 22 May 2017 10:01:37 +0100
parents 41e769c91eca
children
comparison
equal deleted inserted replaced
146:206f0eb279b8 147:45360b968bf4
80 class Arena; 80 class Arena;
81 class BuilderArena; 81 class BuilderArena;
82 82
83 // ============================================================================= 83 // =============================================================================
84 84
85 typedef decltype(BITS / ELEMENTS) BitsPerElement; 85 #if CAPNP_DEBUG_TYPES
86 typedef decltype(POINTERS / ELEMENTS) PointersPerElement; 86 typedef kj::UnitRatio<kj::Bounded<64, uint>, BitLabel, ElementLabel> BitsPerElementTableType;
87 87 #else
88 static constexpr BitsPerElement BITS_PER_ELEMENT_TABLE[8] = { 88 typedef uint BitsPerElementTableType;
89 0 * BITS / ELEMENTS, 89 #endif
90 1 * BITS / ELEMENTS, 90
91 8 * BITS / ELEMENTS, 91 static constexpr BitsPerElementTableType BITS_PER_ELEMENT_TABLE[8] = {
92 16 * BITS / ELEMENTS, 92 bounded< 0>() * BITS / ELEMENTS,
93 32 * BITS / ELEMENTS, 93 bounded< 1>() * BITS / ELEMENTS,
94 64 * BITS / ELEMENTS, 94 bounded< 8>() * BITS / ELEMENTS,
95 0 * BITS / ELEMENTS, 95 bounded<16>() * BITS / ELEMENTS,
96 0 * BITS / ELEMENTS 96 bounded<32>() * BITS / ELEMENTS,
97 }; 97 bounded<64>() * BITS / ELEMENTS,
98 98 bounded< 0>() * BITS / ELEMENTS,
99 inline KJ_CONSTEXPR() BitsPerElement dataBitsPerElement(ElementSize size) { 99 bounded< 0>() * BITS / ELEMENTS
100 };
101
102 inline KJ_CONSTEXPR() BitsPerElementTableType dataBitsPerElement(ElementSize size) {
100 return _::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)]; 103 return _::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)];
101 } 104 }
102 105
103 inline constexpr PointersPerElement pointersPerElement(ElementSize size) { 106 inline constexpr PointersPerElementN<1> pointersPerElement(ElementSize size) {
104 return size == ElementSize::POINTER ? 1 * POINTERS / ELEMENTS : 0 * POINTERS / ELEMENTS; 107 return size == ElementSize::POINTER
108 ? PointersPerElementN<1>(ONE * POINTERS / ELEMENTS)
109 : PointersPerElementN<1>(ZERO * POINTERS / ELEMENTS);
110 }
111
112 static constexpr BitsPerElementTableType BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[8] = {
113 bounded< 0>() * BITS / ELEMENTS,
114 bounded< 1>() * BITS / ELEMENTS,
115 bounded< 8>() * BITS / ELEMENTS,
116 bounded<16>() * BITS / ELEMENTS,
117 bounded<32>() * BITS / ELEMENTS,
118 bounded<64>() * BITS / ELEMENTS,
119 bounded<64>() * BITS / ELEMENTS,
120 bounded< 0>() * BITS / ELEMENTS
121 };
122
123 inline KJ_CONSTEXPR() BitsPerElementTableType bitsPerElementIncludingPointers(ElementSize size) {
124 return _::BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[static_cast<int>(size)];
105 } 125 }
106 126
107 template <size_t size> struct ElementSizeForByteSize; 127 template <size_t size> struct ElementSizeForByteSize;
108 template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; }; 128 template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; };
109 template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; }; 129 template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; };
124 // Void and bool are special. 144 // Void and bool are special.
125 template <> struct ElementSizeForType<Void> { static constexpr ElementSize value = ElementSize::VOID; }; 145 template <> struct ElementSizeForType<Void> { static constexpr ElementSize value = ElementSize::VOID; };
126 template <> struct ElementSizeForType<bool> { static constexpr ElementSize value = ElementSize::BIT; }; 146 template <> struct ElementSizeForType<bool> { static constexpr ElementSize value = ElementSize::BIT; };
127 147
128 // Lists and blobs are pointers, not structs. 148 // Lists and blobs are pointers, not structs.
129 template <typename T, bool b> struct ElementSizeForType<List<T, b>> { 149 template <typename T, Kind K> struct ElementSizeForType<List<T, K>> {
130 static constexpr ElementSize value = ElementSize::POINTER; 150 static constexpr ElementSize value = ElementSize::POINTER;
131 }; 151 };
132 template <> struct ElementSizeForType<Text> { 152 template <> struct ElementSizeForType<Text> {
133 static constexpr ElementSize value = ElementSize::POINTER; 153 static constexpr ElementSize value = ElementSize::POINTER;
134 }; 154 };
140 inline constexpr ElementSize elementSizeForType() { 160 inline constexpr ElementSize elementSizeForType() {
141 return ElementSizeForType<T>::value; 161 return ElementSizeForType<T>::value;
142 } 162 }
143 163
144 struct MessageSizeCounts { 164 struct MessageSizeCounts {
145 WordCount64 wordCount; 165 WordCountN<61, uint64_t> wordCount; // 2^64 bytes
146 uint capCount; 166 uint capCount;
147 167
148 MessageSizeCounts& operator+=(const MessageSizeCounts& other) { 168 MessageSizeCounts& operator+=(const MessageSizeCounts& other) {
149 wordCount += other.wordCount; 169 // OK to truncate unchecked because this class is used to count actual stuff in memory, and
170 // we couldn't possibly have anywhere near 2^61 words.
171 wordCount = assumeBits<61>(wordCount + other.wordCount);
150 capCount += other.capCount; 172 capCount += other.capCount;
151 return *this; 173 return *this;
152 } 174 }
153 175
176 void addWords(WordCountN<61, uint64_t> other) {
177 wordCount = assumeBits<61>(wordCount + other);
178 }
179
154 MessageSize asPublic() { 180 MessageSize asPublic() {
155 return MessageSize { wordCount / WORDS, capCount }; 181 return MessageSize { unbound(wordCount / WORDS), capCount };
156 } 182 }
157 }; 183 };
158 184
159 // ============================================================================= 185 // =============================================================================
160 186
166 uint8_t bytes[wordCount * sizeof(word)]; 192 uint8_t bytes[wordCount * sizeof(word)];
167 word words[wordCount]; 193 word words[wordCount];
168 }; 194 };
169 195
170 struct StructSize { 196 struct StructSize {
171 WordCount16 data; 197 StructDataWordCount data;
172 WirePointerCount16 pointers; 198 StructPointerCount pointers;
173 199
174 inline constexpr WordCount total() const { return data + pointers * WORDS_PER_POINTER; } 200 inline constexpr WordCountN<17> total() const { return data + pointers * WORDS_PER_POINTER; }
175 201
176 StructSize() = default; 202 StructSize() = default;
177 inline constexpr StructSize(WordCount data, WirePointerCount pointers) 203 inline constexpr StructSize(StructDataWordCount data, StructPointerCount pointers)
178 : data(data), pointers(pointers) {} 204 : data(data), pointers(pointers) {}
179 }; 205 };
180 206
181 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate> 207 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate>
182 inline constexpr StructSize structSize() { 208 inline constexpr StructSize structSize() {
183 return StructSize(CapnpPrivate::dataWordSize * WORDS, CapnpPrivate::pointerCount * POINTERS); 209 return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS,
210 bounded(CapnpPrivate::pointerCount) * POINTERS);
184 } 211 }
185 212
186 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate, 213 template <typename T, typename CapnpPrivate = typename T::_capnpPrivate,
187 typename = kj::EnableIf<CAPNP_KIND(T) == Kind::STRUCT>> 214 typename = kj::EnableIf<CAPNP_KIND(T) == Kind::STRUCT>>
188 inline constexpr StructSize minStructSizeForElement() { 215 inline constexpr StructSize minStructSizeForElement() {
189 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough 216 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough
190 // to hold a T. 217 // to hold a T.
191 218
192 return StructSize(CapnpPrivate::dataWordSize * WORDS, CapnpPrivate::pointerCount * POINTERS); 219 return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS,
220 bounded(CapnpPrivate::pointerCount) * POINTERS);
193 } 221 }
194 222
195 template <typename T, typename = kj::EnableIf<CAPNP_KIND(T) != Kind::STRUCT>> 223 template <typename T, typename = kj::EnableIf<CAPNP_KIND(T) != Kind::STRUCT>>
196 inline constexpr StructSize minStructSizeForElement() { 224 inline constexpr StructSize minStructSizeForElement() {
197 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough 225 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough
198 // to hold a T. 226 // to hold a T.
199 227
200 return StructSize( 228 return StructSize(
201 dataBitsPerElement(elementSizeForType<T>()) * ELEMENTS > 0 * BITS ? 1 * WORDS : 0 * WORDS, 229 dataBitsPerElement(elementSizeForType<T>()) * ELEMENTS > ZERO * BITS
230 ? StructDataWordCount(ONE * WORDS) : StructDataWordCount(ZERO * WORDS),
202 pointersPerElement(elementSizeForType<T>()) * ELEMENTS); 231 pointersPerElement(elementSizeForType<T>()) * ELEMENTS);
203 } 232 }
204 233
205 // ------------------------------------------------------------------- 234 // -------------------------------------------------------------------
206 // Masking of default values 235 // Masking of default values
316 SegmentBuilder* segment, CapTableBuilder* capTable, word* location); 345 SegmentBuilder* segment, CapTableBuilder* capTable, word* location);
317 // Get a PointerBuilder representing a message root located in the given segment at the given 346 // Get a PointerBuilder representing a message root located in the given segment at the given
318 // location. 347 // location.
319 348
320 inline bool isNull() { return getPointerType() == PointerType::NULL_; } 349 inline bool isNull() { return getPointerType() == PointerType::NULL_; }
321 PointerType getPointerType(); 350 PointerType getPointerType() const;
322 351
323 StructBuilder getStruct(StructSize size, const word* defaultValue); 352 StructBuilder getStruct(StructSize size, const word* defaultValue);
324 ListBuilder getList(ElementSize elementSize, const word* defaultValue); 353 ListBuilder getList(ElementSize elementSize, const word* defaultValue);
325 ListBuilder getStructList(StructSize elementSize, const word* defaultValue); 354 ListBuilder getStructList(StructSize elementSize, const word* defaultValue);
326 ListBuilder getListAnySize(const word* defaultValue); 355 ListBuilder getListAnySize(const word* defaultValue);
327 template <typename T> typename T::Builder getBlob(const void* defaultValue,ByteCount defaultSize); 356 template <typename T> typename T::Builder getBlob(
357 const void* defaultValue, ByteCount defaultSize);
328 #if !CAPNP_LITE 358 #if !CAPNP_LITE
329 kj::Own<ClientHook> getCapability(); 359 kj::Own<ClientHook> getCapability();
330 #endif // !CAPNP_LITE 360 #endif // !CAPNP_LITE
331 // Get methods: Get the value. If it is null, initialize it to a copy of the default value. 361 // Get methods: Get the value. If it is null, initialize it to a copy of the default value.
332 // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a 362 // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
472 502
473 inline word* getLocation() { return reinterpret_cast<word*>(data); } 503 inline word* getLocation() { return reinterpret_cast<word*>(data); }
474 // Get the object's location. Only valid for independently-allocated objects (i.e. not list 504 // Get the object's location. Only valid for independently-allocated objects (i.e. not list
475 // elements). 505 // elements).
476 506
477 inline BitCount getDataSectionSize() const { return dataSize; } 507 inline StructDataBitCount getDataSectionSize() const { return dataSize; }
478 inline WirePointerCount getPointerSectionSize() const { return pointerCount; } 508 inline StructPointerCount getPointerSectionSize() const { return pointerCount; }
479 inline kj::ArrayPtr<byte> getDataSectionAsBlob(); 509 inline kj::ArrayPtr<byte> getDataSectionAsBlob();
480 inline _::ListBuilder getPointerSectionAsList(); 510 inline _::ListBuilder getPointerSectionAsList();
481 511
482 template <typename T> 512 template <typename T>
483 KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset)); 513 KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset));
484 // Return true if the field is set to something other than its default value. 514 // Return true if the field is set to something other than its default value.
485 515
486 template <typename T> 516 template <typename T>
487 KJ_ALWAYS_INLINE(T getDataField(ElementCount offset)); 517 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset));
488 // Gets the data field value of the given type at the given offset. The offset is measured in 518 // Gets the data field value of the given type at the given offset. The offset is measured in
489 // multiples of the field size, determined by the type. 519 // multiples of the field size, determined by the type.
490 520
491 template <typename T> 521 template <typename T>
492 KJ_ALWAYS_INLINE(T getDataField(ElementCount offset, Mask<T> mask)); 522 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask<T> mask));
493 // Like getDataField() but applies the given XOR mask to the data on load. Used for reading 523 // Like getDataField() but applies the given XOR mask to the data on load. Used for reading
494 // fields with non-zero default values. 524 // fields with non-zero default values.
495 525
496 template <typename T> 526 template <typename T>
497 KJ_ALWAYS_INLINE(void setDataField( 527 KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, kj::NoInfer<T> value));
498 ElementCount offset, kj::NoInfer<T> value));
499 // Sets the data field value at the given offset. 528 // Sets the data field value at the given offset.
500 529
501 template <typename T> 530 template <typename T>
502 KJ_ALWAYS_INLINE(void setDataField( 531 KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset,
503 ElementCount offset, kj::NoInfer<T> value, Mask<T> mask)); 532 kj::NoInfer<T> value, Mask<T> mask));
504 // Like setDataField() but applies the given XOR mask before storing. Used for writing fields 533 // Like setDataField() but applies the given XOR mask before storing. Used for writing fields
505 // with non-zero default values. 534 // with non-zero default values.
506 535
507 KJ_ALWAYS_INLINE(PointerBuilder getPointerField(WirePointerCount ptrIndex)); 536 KJ_ALWAYS_INLINE(PointerBuilder getPointerField(StructPointerOffset ptrIndex));
508 // Get a builder for a pointer field given the index within the pointer section. 537 // Get a builder for a pointer field given the index within the pointer section.
509 538
510 void clearAll(); 539 void clearAll();
511 // Clear all pointers and data. 540 // Clear all pointers and data.
512 541
536 SegmentBuilder* segment; // Memory segment in which the struct resides. 565 SegmentBuilder* segment; // Memory segment in which the struct resides.
537 CapTableBuilder* capTable; // Table of capability indexes. 566 CapTableBuilder* capTable; // Table of capability indexes.
538 void* data; // Pointer to the encoded data. 567 void* data; // Pointer to the encoded data.
539 WirePointer* pointers; // Pointer to the encoded pointers. 568 WirePointer* pointers; // Pointer to the encoded pointers.
540 569
541 BitCount32 dataSize; 570 StructDataBitCount dataSize;
542 // Size of data section. We use a bit count rather than a word count to more easily handle the 571 // Size of data section. We use a bit count rather than a word count to more easily handle the
543 // case of struct lists encoded with less than a word per element. 572 // case of struct lists encoded with less than a word per element.
544 573
545 WirePointerCount16 pointerCount; // Size of the pointer section. 574 StructPointerCount pointerCount; // Size of the pointer section.
546 575
547 inline StructBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, 576 inline StructBuilder(SegmentBuilder* segment, CapTableBuilder* capTable,
548 void* data, WirePointer* pointers, 577 void* data, WirePointer* pointers,
549 BitCount dataSize, WirePointerCount pointerCount) 578 StructDataBitCount dataSize, StructPointerCount pointerCount)
550 : segment(segment), capTable(capTable), data(data), pointers(pointers), 579 : segment(segment), capTable(capTable), data(data), pointers(pointers),
551 dataSize(dataSize), pointerCount(pointerCount) {} 580 dataSize(dataSize), pointerCount(pointerCount) {}
552 581
553 friend class ListBuilder; 582 friend class ListBuilder;
554 friend struct WireHelpers; 583 friend struct WireHelpers;
556 }; 585 };
557 586
558 class StructReader { 587 class StructReader {
559 public: 588 public:
560 inline StructReader() 589 inline StructReader()
561 : segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr), dataSize(0), 590 : segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr),
562 pointerCount(0), nestingLimit(0x7fffffff) {} 591 dataSize(ZERO * BITS), pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {}
563 inline StructReader(kj::ArrayPtr<const word> data) 592 inline StructReader(kj::ArrayPtr<const word> data)
564 : segment(nullptr), capTable(nullptr), data(data.begin()), pointers(nullptr), 593 : segment(nullptr), capTable(nullptr), data(data.begin()), pointers(nullptr),
565 dataSize(data.size() * WORDS * BITS_PER_WORD), pointerCount(0), nestingLimit(0x7fffffff) {} 594 dataSize(assumeBits<STRUCT_DATA_WORD_COUNT_BITS>(data.size()) * WORDS * BITS_PER_WORD),
595 pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {}
566 596
567 const void* getLocation() const { return data; } 597 const void* getLocation() const { return data; }
568 598
569 inline BitCount getDataSectionSize() const { return dataSize; } 599 inline StructDataBitCount getDataSectionSize() const { return dataSize; }
570 inline WirePointerCount getPointerSectionSize() const { return pointerCount; } 600 inline StructPointerCount getPointerSectionSize() const { return pointerCount; }
571 inline kj::ArrayPtr<const byte> getDataSectionAsBlob(); 601 inline kj::ArrayPtr<const byte> getDataSectionAsBlob();
572 inline _::ListReader getPointerSectionAsList(); 602 inline _::ListReader getPointerSectionAsList();
573 603
574 kj::Array<word> canonicalize(); 604 kj::Array<word> canonicalize();
575 605
576 template <typename T> 606 template <typename T>
577 KJ_ALWAYS_INLINE(bool hasDataField(ElementCount offset) const); 607 KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset) const);
578 // Return true if the field is set to something other than its default value. 608 // Return true if the field is set to something other than its default value.
579 609
580 template <typename T> 610 template <typename T>
581 KJ_ALWAYS_INLINE(T getDataField(ElementCount offset) const); 611 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset) const);
582 // Get the data field value of the given type at the given offset. The offset is measured in 612 // 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 613 // 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. 614 // end of the struct's data section.
585 615
586 template <typename T> 616 template <typename T>
587 KJ_ALWAYS_INLINE( 617 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask<T> mask) const);
588 T getDataField(ElementCount offset, Mask<T> mask) const);
589 // Like getDataField(offset), but applies the given XOR mask to the result. Used for reading 618 // Like getDataField(offset), but applies the given XOR mask to the result. Used for reading
590 // fields with non-zero default values. 619 // fields with non-zero default values.
591 620
592 KJ_ALWAYS_INLINE(PointerReader getPointerField(WirePointerCount ptrIndex) const); 621 KJ_ALWAYS_INLINE(PointerReader getPointerField(StructPointerOffset ptrIndex) const);
593 // Get a reader for a pointer field given the index within the pointer section. If the index 622 // Get a reader for a pointer field given the index within the pointer section. If the index
594 // is out-of-bounds, returns a null pointer. 623 // is out-of-bounds, returns a null pointer.
595 624
596 MessageSizeCounts totalSize() const; 625 MessageSizeCounts totalSize() const;
597 // Return the total size of the struct and everything to which it points. Does not count far 626 // Return the total size of the struct and everything to which it points. Does not count far
626 CapTableReader* capTable; // Table of capability indexes. 655 CapTableReader* capTable; // Table of capability indexes.
627 656
628 const void* data; 657 const void* data;
629 const WirePointer* pointers; 658 const WirePointer* pointers;
630 659
631 BitCount32 dataSize; 660 StructDataBitCount dataSize;
632 // Size of data section. We use a bit count rather than a word count to more easily handle the 661 // Size of data section. We use a bit count rather than a word count to more easily handle the
633 // case of struct lists encoded with less than a word per element. 662 // case of struct lists encoded with less than a word per element.
634 663
635 WirePointerCount16 pointerCount; // Size of the pointer section. 664 StructPointerCount pointerCount; // Size of the pointer section.
636 665
637 int nestingLimit; 666 int nestingLimit;
638 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. 667 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
639 // Once this reaches zero, further pointers will be pruned. 668 // Once this reaches zero, further pointers will be pruned.
640 // TODO(perf): Limit to 16 bits for better packing? 669 // TODO(perf): Limit to 16 bits for better packing?
641 670
642 inline StructReader(SegmentReader* segment, CapTableReader* capTable, 671 inline StructReader(SegmentReader* segment, CapTableReader* capTable,
643 const void* data, const WirePointer* pointers, 672 const void* data, const WirePointer* pointers,
644 BitCount dataSize, WirePointerCount pointerCount, int nestingLimit) 673 StructDataBitCount dataSize, StructPointerCount pointerCount,
674 int nestingLimit)
645 : segment(segment), capTable(capTable), data(data), pointers(pointers), 675 : segment(segment), capTable(capTable), data(data), pointers(pointers),
646 dataSize(dataSize), pointerCount(pointerCount), 676 dataSize(dataSize), pointerCount(pointerCount),
647 nestingLimit(nestingLimit) {} 677 nestingLimit(nestingLimit) {}
648 678
649 friend class ListReader; 679 friend class ListReader;
654 // ------------------------------------------------------------------- 684 // -------------------------------------------------------------------
655 685
656 class ListBuilder: public kj::DisallowConstCopy { 686 class ListBuilder: public kj::DisallowConstCopy {
657 public: 687 public:
658 inline explicit ListBuilder(ElementSize elementSize) 688 inline explicit ListBuilder(ElementSize elementSize)
659 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(0 * ELEMENTS), 689 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS),
660 step(0 * BITS / ELEMENTS), structDataSize(0 * BITS), structPointerCount(0 * POINTERS), 690 step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS),
661 elementSize(elementSize) {} 691 structPointerCount(ZERO * POINTERS), elementSize(elementSize) {}
662 692
663 inline word* getLocation() { 693 inline word* getLocation() {
664 // Get the object's location. 694 // Get the object's location.
665 695
666 if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) { 696 if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) {
670 } 700 }
671 } 701 }
672 702
673 inline ElementSize getElementSize() const { return elementSize; } 703 inline ElementSize getElementSize() const { return elementSize; }
674 704
675 inline ElementCount size() const; 705 inline ListElementCount size() const;
676 // The number of elements in the list. 706 // The number of elements in the list.
677 707
678 Text::Builder asText(); 708 Text::Builder asText();
679 Data::Builder asData(); 709 Data::Builder asData();
680 // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized. 710 // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized.
682 template <typename T> 712 template <typename T>
683 KJ_ALWAYS_INLINE(T getDataElement(ElementCount index)); 713 KJ_ALWAYS_INLINE(T getDataElement(ElementCount index));
684 // Get the element of the given type at the given index. 714 // Get the element of the given type at the given index.
685 715
686 template <typename T> 716 template <typename T>
687 KJ_ALWAYS_INLINE(void setDataElement( 717 KJ_ALWAYS_INLINE(void setDataElement(ElementCount index, kj::NoInfer<T> value));
688 ElementCount index, kj::NoInfer<T> value));
689 // Set the element at the given index. 718 // Set the element at the given index.
690 719
691 KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index)); 720 KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index));
692 721
693 StructBuilder getStructElement(ElementCount index); 722 StructBuilder getStructElement(ElementCount index);
708 SegmentBuilder* segment; // Memory segment in which the list resides. 737 SegmentBuilder* segment; // Memory segment in which the list resides.
709 CapTableBuilder* capTable; // Table of capability indexes. 738 CapTableBuilder* capTable; // Table of capability indexes.
710 739
711 byte* ptr; // Pointer to list content. 740 byte* ptr; // Pointer to list content.
712 741
713 ElementCount elementCount; // Number of elements in the list. 742 ListElementCount elementCount; // Number of elements in the list.
714 743
715 decltype(BITS / ELEMENTS) step; 744 BitsPerElementN<23> step;
716 // The distance between elements. 745 // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data
717 746 // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 128 bits.
718 BitCount32 structDataSize; 747
719 WirePointerCount16 structPointerCount; 748 StructDataBitCount structDataSize;
749 StructPointerCount structPointerCount;
720 // The struct properties to use when interpreting the elements as structs. All lists can be 750 // The struct properties to use when interpreting the elements as structs. All lists can be
721 // interpreted as struct lists, so these are always filled in. 751 // interpreted as struct lists, so these are always filled in.
722 752
723 ElementSize elementSize; 753 ElementSize elementSize;
724 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE 754 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE
725 // from other types when the overall size is exactly zero or one words. 755 // from other types when the overall size is exactly zero or one words.
726 756
727 inline ListBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* ptr, 757 inline ListBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* ptr,
728 decltype(BITS / ELEMENTS) step, ElementCount size, 758 BitsPerElementN<23> step, ListElementCount size,
729 BitCount structDataSize, WirePointerCount structPointerCount, 759 StructDataBitCount structDataSize, StructPointerCount structPointerCount,
730 ElementSize elementSize) 760 ElementSize elementSize)
731 : segment(segment), capTable(capTable), ptr(reinterpret_cast<byte*>(ptr)), 761 : segment(segment), capTable(capTable), ptr(reinterpret_cast<byte*>(ptr)),
732 elementCount(size), step(step), structDataSize(structDataSize), 762 elementCount(size), step(step), structDataSize(structDataSize),
733 structPointerCount(structPointerCount), elementSize(elementSize) {} 763 structPointerCount(structPointerCount), elementSize(elementSize) {}
734 764
738 }; 768 };
739 769
740 class ListReader { 770 class ListReader {
741 public: 771 public:
742 inline explicit ListReader(ElementSize elementSize) 772 inline explicit ListReader(ElementSize elementSize)
743 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(0), 773 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS),
744 step(0 * BITS / ELEMENTS), structDataSize(0), structPointerCount(0), 774 step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS),
745 elementSize(elementSize), nestingLimit(0x7fffffff) {} 775 structPointerCount(ZERO * POINTERS), elementSize(elementSize), nestingLimit(0x7fffffff) {}
746 776
747 inline ElementCount size() const; 777 inline ListElementCount size() const;
748 // The number of elements in the list. 778 // The number of elements in the list.
749 779
750 inline ElementSize getElementSize() const { return elementSize; } 780 inline ElementSize getElementSize() const { return elementSize; }
751 781
752 Text::Reader asText(); 782 Text::Reader asText();
767 // Gets the capability context in which this object is operating. 797 // Gets the capability context in which this object is operating.
768 798
769 ListReader imbue(CapTableReader* capTable) const; 799 ListReader imbue(CapTableReader* capTable) const;
770 // Return a copy of this reader except using the given capability context. 800 // Return a copy of this reader except using the given capability context.
771 801
772 bool isCanonical(const word **readHead); 802 bool isCanonical(const word **readHead, const WirePointer* ref);
773 // Validate this pointer's canonicity, subject to the conditions: 803 // Validate this pointer's canonicity, subject to the conditions:
774 // * All data to the left of readHead has been read thus far (for pointer 804 // * All data to the left of readHead has been read thus far (for pointer
775 // ordering) 805 // ordering)
776 // * All pointers in preorder have already been checked 806 // * All pointers in preorder have already been checked
777 // * This pointer is in the first and only segment of the message 807 // * This pointer is in the first and only segment of the message
780 SegmentReader* segment; // Memory segment in which the list resides. 810 SegmentReader* segment; // Memory segment in which the list resides.
781 CapTableReader* capTable; // Table of capability indexes. 811 CapTableReader* capTable; // Table of capability indexes.
782 812
783 const byte* ptr; // Pointer to list content. 813 const byte* ptr; // Pointer to list content.
784 814
785 ElementCount elementCount; // Number of elements in the list. 815 ListElementCount elementCount; // Number of elements in the list.
786 816
787 decltype(BITS / ELEMENTS) step; 817 BitsPerElementN<23> step;
788 // The distance between elements. 818 // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data
789 819 // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 2 bits.
790 BitCount32 structDataSize; 820
791 WirePointerCount16 structPointerCount; 821 StructDataBitCount structDataSize;
822 StructPointerCount structPointerCount;
792 // The struct properties to use when interpreting the elements as structs. All lists can be 823 // The struct properties to use when interpreting the elements as structs. All lists can be
793 // interpreted as struct lists, so these are always filled in. 824 // interpreted as struct lists, so these are always filled in.
794 825
795 ElementSize elementSize; 826 ElementSize elementSize;
796 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE 827 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE
799 int nestingLimit; 830 int nestingLimit;
800 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks. 831 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
801 // Once this reaches zero, further pointers will be pruned. 832 // Once this reaches zero, further pointers will be pruned.
802 833
803 inline ListReader(SegmentReader* segment, CapTableReader* capTable, const void* ptr, 834 inline ListReader(SegmentReader* segment, CapTableReader* capTable, const void* ptr,
804 ElementCount elementCount, decltype(BITS / ELEMENTS) step, 835 ListElementCount elementCount, BitsPerElementN<23> step,
805 BitCount structDataSize, WirePointerCount structPointerCount, 836 StructDataBitCount structDataSize, StructPointerCount structPointerCount,
806 ElementSize elementSize, int nestingLimit) 837 ElementSize elementSize, int nestingLimit)
807 : segment(segment), capTable(capTable), ptr(reinterpret_cast<const byte*>(ptr)), 838 : segment(segment), capTable(capTable), ptr(reinterpret_cast<const byte*>(ptr)),
808 elementCount(elementCount), step(step), structDataSize(structDataSize), 839 elementCount(elementCount), step(step), structDataSize(structDataSize),
809 structPointerCount(structPointerCount), elementSize(elementSize), 840 structPointerCount(structPointerCount), elementSize(elementSize),
810 nestingLimit(nestingLimit) {} 841 nestingLimit(nestingLimit) {}
864 // INLINE_COMPOSITE -- use asStructList() instead. 895 // INLINE_COMPOSITE -- use asStructList() instead.
865 896
866 ListBuilder asStructList(StructSize elementSize); 897 ListBuilder asStructList(StructSize elementSize);
867 // Interpret as a struct list, or throw an exception if not a list. 898 // Interpret as a struct list, or throw an exception if not a list.
868 899
900 ListBuilder asListAnySize();
901 // For AnyList.
902
869 Text::Builder asText(); 903 Text::Builder asText();
870 Data::Builder asData(); 904 Data::Builder asData();
871 // Interpret as a blob, or throw an exception if not a blob. 905 // Interpret as a blob, or throw an exception if not a blob.
872 906
873 StructReader asStructReader(StructSize size) const; 907 StructReader asStructReader(StructSize size) const;
874 ListReader asListReader(ElementSize elementSize) const; 908 ListReader asListReader(ElementSize elementSize) const;
909 ListReader asListReaderAnySize() const;
875 #if !CAPNP_LITE 910 #if !CAPNP_LITE
876 kj::Own<ClientHook> asCapability() const; 911 kj::Own<ClientHook> asCapability() const;
877 #endif // !CAPNP_LITE 912 #endif // !CAPNP_LITE
878 Text::Reader asTextReader() const; 913 Text::Reader asTextReader() const;
879 Data::Reader asDataReader() const; 914 Data::Reader asDataReader() const;
886 void truncate(ElementCount size, StructSize elementSize); 921 void truncate(ElementCount size, StructSize elementSize);
887 void truncateText(ElementCount size); 922 void truncateText(ElementCount size);
888 // Versions of truncate() that know how to allocate a new list if needed. 923 // Versions of truncate() that know how to allocate a new list if needed.
889 924
890 private: 925 private:
891 static_assert(1 * POINTERS * WORDS_PER_POINTER == 1 * WORDS, 926 static_assert(ONE * POINTERS * WORDS_PER_POINTER == ONE * WORDS,
892 "This struct assumes a pointer is one word."); 927 "This struct assumes a pointer is one word.");
893 word tag; 928 word tag;
894 // Contains an encoded WirePointer representing this object. WirePointer is defined in 929 // Contains an encoded WirePointer representing this object. WirePointer is defined in
895 // layout.c++, but fits in a word. 930 // layout.c++, but fits in a word.
896 // 931 //
932 // Internal implementation details... 967 // Internal implementation details...
933 968
934 // These are defined in the source file. 969 // These are defined in the source file.
935 template <> typename Text::Builder PointerBuilder::initBlob<Text>(ByteCount size); 970 template <> typename Text::Builder PointerBuilder::initBlob<Text>(ByteCount size);
936 template <> void PointerBuilder::setBlob<Text>(typename Text::Reader value); 971 template <> void PointerBuilder::setBlob<Text>(typename Text::Reader value);
937 template <> typename Text::Builder PointerBuilder::getBlob<Text>(const void* defaultValue, ByteCount defaultSize); 972 template <> typename Text::Builder PointerBuilder::getBlob<Text>(
938 template <> typename Text::Reader PointerReader::getBlob<Text>(const void* defaultValue, ByteCount defaultSize) const; 973 const void* defaultValue, ByteCount defaultSize);
974 template <> typename Text::Reader PointerReader::getBlob<Text>(
975 const void* defaultValue, ByteCount defaultSize) const;
939 976
940 template <> typename Data::Builder PointerBuilder::initBlob<Data>(ByteCount size); 977 template <> typename Data::Builder PointerBuilder::initBlob<Data>(ByteCount size);
941 template <> void PointerBuilder::setBlob<Data>(typename Data::Reader value); 978 template <> void PointerBuilder::setBlob<Data>(typename Data::Reader value);
942 template <> typename Data::Builder PointerBuilder::getBlob<Data>(const void* defaultValue, ByteCount defaultSize); 979 template <> typename Data::Builder PointerBuilder::getBlob<Data>(
943 template <> typename Data::Reader PointerReader::getBlob<Data>(const void* defaultValue, ByteCount defaultSize) const; 980 const void* defaultValue, ByteCount defaultSize);
981 template <> typename Data::Reader PointerReader::getBlob<Data>(
982 const void* defaultValue, ByteCount defaultSize) const;
944 983
945 inline PointerBuilder PointerBuilder::getRoot( 984 inline PointerBuilder PointerBuilder::getRoot(
946 SegmentBuilder* segment, CapTableBuilder* capTable, word* location) { 985 SegmentBuilder* segment, CapTableBuilder* capTable, word* location) {
947 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(location)); 986 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(location));
948 } 987 }
953 } 992 }
954 993
955 // ------------------------------------------------------------------- 994 // -------------------------------------------------------------------
956 995
957 inline kj::ArrayPtr<byte> StructBuilder::getDataSectionAsBlob() { 996 inline kj::ArrayPtr<byte> StructBuilder::getDataSectionAsBlob() {
958 return kj::ArrayPtr<byte>(reinterpret_cast<byte*>(data), dataSize / BITS_PER_BYTE / BYTES); 997 return kj::ArrayPtr<byte>(reinterpret_cast<byte*>(data),
998 unbound(dataSize / BITS_PER_BYTE / BYTES));
959 } 999 }
960 1000
961 inline _::ListBuilder StructBuilder::getPointerSectionAsList() { 1001 inline _::ListBuilder StructBuilder::getPointerSectionAsList() {
962 return _::ListBuilder(segment, capTable, pointers, 1 * POINTERS * BITS_PER_POINTER / ELEMENTS, 1002 return _::ListBuilder(segment, capTable, pointers, ONE * POINTERS * BITS_PER_POINTER / ELEMENTS,
963 pointerCount * (1 * ELEMENTS / POINTERS), 1003 pointerCount * (ONE * ELEMENTS / POINTERS),
964 0 * BITS, 1 * POINTERS, ElementSize::POINTER); 1004 ZERO * BITS, ONE * POINTERS, ElementSize::POINTER);
965 } 1005 }
966 1006
967 template <typename T> 1007 template <typename T>
968 inline bool StructBuilder::hasDataField(ElementCount offset) { 1008 inline bool StructBuilder::hasDataField(StructDataOffset offset) {
969 return getDataField<Mask<T>>(offset) != 0; 1009 return getDataField<Mask<T>>(offset) != 0;
970 } 1010 }
971 1011
972 template <> 1012 template <>
973 inline bool StructBuilder::hasDataField<Void>(ElementCount offset) { 1013 inline bool StructBuilder::hasDataField<Void>(StructDataOffset offset) {
974 return false; 1014 return false;
975 } 1015 }
976 1016
977 template <typename T> 1017 template <typename T>
978 inline T StructBuilder::getDataField(ElementCount offset) { 1018 inline T StructBuilder::getDataField(StructDataOffset offset) {
979 return reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].get(); 1019 return reinterpret_cast<WireValue<T>*>(data)[unbound(offset / ELEMENTS)].get();
980 } 1020 }
981 1021
982 template <> 1022 template <>
983 inline bool StructBuilder::getDataField<bool>(ElementCount offset) { 1023 inline bool StructBuilder::getDataField<bool>(StructDataOffset offset) {
984 BitCount boffset = offset * (1 * BITS / ELEMENTS); 1024 BitCount32 boffset = offset * (ONE * BITS / ELEMENTS);
985 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; 1025 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
986 return (*reinterpret_cast<uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0; 1026 return (*reinterpret_cast<uint8_t*>(b) &
987 } 1027 unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0;
988 1028 }
989 template <> 1029
990 inline Void StructBuilder::getDataField<Void>(ElementCount offset) { 1030 template <>
1031 inline Void StructBuilder::getDataField<Void>(StructDataOffset offset) {
991 return VOID; 1032 return VOID;
992 } 1033 }
993 1034
994 template <typename T> 1035 template <typename T>
995 inline T StructBuilder::getDataField(ElementCount offset, Mask<T> mask) { 1036 inline T StructBuilder::getDataField(StructDataOffset offset, Mask<T> mask) {
996 return unmask<T>(getDataField<Mask<T> >(offset), mask); 1037 return unmask<T>(getDataField<Mask<T> >(offset), mask);
997 } 1038 }
998 1039
999 template <typename T> 1040 template <typename T>
1000 inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value) { 1041 inline void StructBuilder::setDataField(StructDataOffset offset, kj::NoInfer<T> value) {
1001 reinterpret_cast<WireValue<T>*>(data)[offset / ELEMENTS].set(value); 1042 reinterpret_cast<WireValue<T>*>(data)[unbound(offset / ELEMENTS)].set(value);
1002 } 1043 }
1003 1044
1004 #if CAPNP_CANONICALIZE_NAN 1045 #if CAPNP_CANONICALIZE_NAN
1005 // Use mask() on floats and doubles to make sure we canonicalize NaNs. 1046 // Use mask() on floats and doubles to make sure we canonicalize NaNs.
1006 template <> 1047 template <>
1007 inline void StructBuilder::setDataField<float>(ElementCount offset, float value) { 1048 inline void StructBuilder::setDataField<float>(StructDataOffset offset, float value) {
1008 setDataField<uint32_t>(offset, mask<float>(value, 0)); 1049 setDataField<uint32_t>(offset, mask<float>(value, 0));
1009 } 1050 }
1010 template <> 1051 template <>
1011 inline void StructBuilder::setDataField<double>(ElementCount offset, double value) { 1052 inline void StructBuilder::setDataField<double>(StructDataOffset offset, double value) {
1012 setDataField<uint64_t>(offset, mask<double>(value, 0)); 1053 setDataField<uint64_t>(offset, mask<double>(value, 0));
1013 } 1054 }
1014 #endif 1055 #endif
1015 1056
1016 template <> 1057 template <>
1017 inline void StructBuilder::setDataField<bool>(ElementCount offset, bool value) { 1058 inline void StructBuilder::setDataField<bool>(StructDataOffset offset, bool value) {
1018 BitCount boffset = offset * (1 * BITS / ELEMENTS); 1059 auto boffset = offset * (ONE * BITS / ELEMENTS);
1019 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE; 1060 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
1020 uint bitnum = boffset % BITS_PER_BYTE / BITS; 1061 uint bitnum = unboundMaxBits<3>(boffset % BITS_PER_BYTE / BITS);
1021 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum)) 1062 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
1022 | (static_cast<uint8_t>(value) << bitnum); 1063 | (static_cast<uint8_t>(value) << bitnum);
1023 } 1064 }
1024 1065
1025 template <> 1066 template <>
1026 inline void StructBuilder::setDataField<Void>(ElementCount offset, Void value) {} 1067 inline void StructBuilder::setDataField<Void>(StructDataOffset offset, Void value) {}
1027 1068
1028 template <typename T> 1069 template <typename T>
1029 inline void StructBuilder::setDataField(ElementCount offset, kj::NoInfer<T> value, Mask<T> m) { 1070 inline void StructBuilder::setDataField(StructDataOffset offset,
1071 kj::NoInfer<T> value, Mask<T> m) {
1030 setDataField<Mask<T> >(offset, mask<T>(value, m)); 1072 setDataField<Mask<T> >(offset, mask<T>(value, m));
1031 } 1073 }
1032 1074
1033 inline PointerBuilder StructBuilder::getPointerField(WirePointerCount ptrIndex) { 1075 inline PointerBuilder StructBuilder::getPointerField(StructPointerOffset ptrIndex) {
1034 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). 1076 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here).
1035 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>( 1077 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(
1036 reinterpret_cast<word*>(pointers) + ptrIndex * WORDS_PER_POINTER)); 1078 reinterpret_cast<word*>(pointers) + ptrIndex * WORDS_PER_POINTER));
1037 } 1079 }
1038 1080
1039 // ------------------------------------------------------------------- 1081 // -------------------------------------------------------------------
1040 1082
1041 inline kj::ArrayPtr<const byte> StructReader::getDataSectionAsBlob() { 1083 inline kj::ArrayPtr<const byte> StructReader::getDataSectionAsBlob() {
1042 return kj::ArrayPtr<const byte>(reinterpret_cast<const byte*>(data), dataSize / BITS_PER_BYTE / BYTES); 1084 return kj::ArrayPtr<const byte>(reinterpret_cast<const byte*>(data),
1085 unbound(dataSize / BITS_PER_BYTE / BYTES));
1043 } 1086 }
1044 1087
1045 inline _::ListReader StructReader::getPointerSectionAsList() { 1088 inline _::ListReader StructReader::getPointerSectionAsList() {
1046 return _::ListReader(segment, capTable, pointers, pointerCount * (1 * ELEMENTS / POINTERS), 1089 return _::ListReader(segment, capTable, pointers, pointerCount * (ONE * ELEMENTS / POINTERS),
1047 1 * POINTERS * BITS_PER_POINTER / ELEMENTS, 0 * BITS, 1 * POINTERS, 1090 ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, ZERO * BITS, ONE * POINTERS,
1048 ElementSize::POINTER, nestingLimit); 1091 ElementSize::POINTER, nestingLimit);
1049 } 1092 }
1050 1093
1051 template <typename T> 1094 template <typename T>
1052 inline bool StructReader::hasDataField(ElementCount offset) const { 1095 inline bool StructReader::hasDataField(StructDataOffset offset) const {
1053 return getDataField<Mask<T>>(offset) != 0; 1096 return getDataField<Mask<T>>(offset) != 0;
1054 } 1097 }
1055 1098
1056 template <> 1099 template <>
1057 inline bool StructReader::hasDataField<Void>(ElementCount offset) const { 1100 inline bool StructReader::hasDataField<Void>(StructDataOffset offset) const {
1058 return false; 1101 return false;
1059 } 1102 }
1060 1103
1061 template <typename T> 1104 template <typename T>
1062 inline T StructReader::getDataField(ElementCount offset) const { 1105 inline T StructReader::getDataField(StructDataOffset offset) const {
1063 if ((offset + 1 * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) { 1106 if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) {
1064 return reinterpret_cast<const WireValue<T>*>(data)[offset / ELEMENTS].get(); 1107 return reinterpret_cast<const WireValue<T>*>(data)[unbound(offset / ELEMENTS)].get();
1065 } else { 1108 } else {
1066 return static_cast<T>(0); 1109 return static_cast<T>(0);
1067 } 1110 }
1068 } 1111 }
1069 1112
1070 template <> 1113 template <>
1071 inline bool StructReader::getDataField<bool>(ElementCount offset) const { 1114 inline bool StructReader::getDataField<bool>(StructDataOffset offset) const {
1072 BitCount boffset = offset * (1 * BITS / ELEMENTS); 1115 auto boffset = offset * (ONE * BITS / ELEMENTS);
1073 if (boffset < dataSize) { 1116 if (boffset < dataSize) {
1074 const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE; 1117 const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE;
1075 return (*reinterpret_cast<const uint8_t*>(b) & (1 << (boffset % BITS_PER_BYTE / BITS))) != 0; 1118 return (*reinterpret_cast<const uint8_t*>(b) &
1119 unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0;
1076 } else { 1120 } else {
1077 return false; 1121 return false;
1078 } 1122 }
1079 } 1123 }
1080 1124
1081 template <> 1125 template <>
1082 inline Void StructReader::getDataField<Void>(ElementCount offset) const { 1126 inline Void StructReader::getDataField<Void>(StructDataOffset offset) const {
1083 return VOID; 1127 return VOID;
1084 } 1128 }
1085 1129
1086 template <typename T> 1130 template <typename T>
1087 T StructReader::getDataField(ElementCount offset, Mask<T> mask) const { 1131 T StructReader::getDataField(StructDataOffset offset, Mask<T> mask) const {
1088 return unmask<T>(getDataField<Mask<T> >(offset), mask); 1132 return unmask<T>(getDataField<Mask<T> >(offset), mask);
1089 } 1133 }
1090 1134
1091 inline PointerReader StructReader::getPointerField(WirePointerCount ptrIndex) const { 1135 inline PointerReader StructReader::getPointerField(StructPointerOffset ptrIndex) const {
1092 if (ptrIndex < pointerCount) { 1136 if (ptrIndex < pointerCount) {
1093 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here). 1137 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here).
1094 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>( 1138 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>(
1095 reinterpret_cast<const word*>(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit); 1139 reinterpret_cast<const word*>(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit);
1096 } else{ 1140 } else{
1098 } 1142 }
1099 } 1143 }
1100 1144
1101 // ------------------------------------------------------------------- 1145 // -------------------------------------------------------------------
1102 1146
1103 inline ElementCount ListBuilder::size() const { return elementCount; } 1147 inline ListElementCount ListBuilder::size() const { return elementCount; }
1104 1148
1105 template <typename T> 1149 template <typename T>
1106 inline T ListBuilder::getDataElement(ElementCount index) { 1150 inline T ListBuilder::getDataElement(ElementCount index) {
1107 return reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get(); 1151 return reinterpret_cast<WireValue<T>*>(
1152 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->get();
1108 1153
1109 // TODO(perf): Benchmark this alternate implementation, which I suspect may make better use of 1154 // TODO(perf): Benchmark this alternate implementation, which I suspect may make better use of
1110 // the x86 SIB byte. Also use it for all the other getData/setData implementations below, and 1155 // the x86 SIB byte. Also use it for all the other getData/setData implementations below, and
1111 // the various non-inline methods that look up pointers. 1156 // the various non-inline methods that look up pointers.
1112 // Also if using this, consider changing ptr back to void* instead of byte*. 1157 // Also if using this, consider changing ptr back to void* instead of byte*.
1115 } 1160 }
1116 1161
1117 template <> 1162 template <>
1118 inline bool ListBuilder::getDataElement<bool>(ElementCount index) { 1163 inline bool ListBuilder::getDataElement<bool>(ElementCount index) {
1119 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. 1164 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists.
1120 BitCount bindex = index * (1 * BITS / ELEMENTS); 1165 auto bindex = index * (ONE * BITS / ELEMENTS);
1121 byte* b = ptr + bindex / BITS_PER_BYTE; 1166 byte* b = ptr + bindex / BITS_PER_BYTE;
1122 return (*reinterpret_cast<uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; 1167 return (*reinterpret_cast<uint8_t*>(b) &
1168 unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0;
1123 } 1169 }
1124 1170
1125 template <> 1171 template <>
1126 inline Void ListBuilder::getDataElement<Void>(ElementCount index) { 1172 inline Void ListBuilder::getDataElement<Void>(ElementCount index) {
1127 return VOID; 1173 return VOID;
1128 } 1174 }
1129 1175
1130 template <typename T> 1176 template <typename T>
1131 inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer<T> value) { 1177 inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer<T> value) {
1132 reinterpret_cast<WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->set(value); 1178 reinterpret_cast<WireValue<T>*>(
1179 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->set(value);
1133 } 1180 }
1134 1181
1135 #if CAPNP_CANONICALIZE_NAN 1182 #if CAPNP_CANONICALIZE_NAN
1136 // Use mask() on floats and doubles to make sure we canonicalize NaNs. 1183 // Use mask() on floats and doubles to make sure we canonicalize NaNs.
1137 template <> 1184 template <>
1145 #endif 1192 #endif
1146 1193
1147 template <> 1194 template <>
1148 inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) { 1195 inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) {
1149 // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists. 1196 // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
1150 BitCount bindex = index * (1 * BITS / ELEMENTS); 1197 auto bindex = index * (ONE * BITS / ELEMENTS);
1151 byte* b = ptr + bindex / BITS_PER_BYTE; 1198 byte* b = ptr + bindex / BITS_PER_BYTE;
1152 uint bitnum = bindex % BITS_PER_BYTE / BITS; 1199 auto bitnum = bindex % BITS_PER_BYTE / BITS;
1153 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum)) 1200 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << unbound(bitnum)))
1154 | (static_cast<uint8_t>(value) << bitnum); 1201 | (static_cast<uint8_t>(value) << unbound(bitnum));
1155 } 1202 }
1156 1203
1157 template <> 1204 template <>
1158 inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) {} 1205 inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) {}
1159 1206
1160 inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) { 1207 inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) {
1161 return PointerBuilder(segment, capTable, 1208 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(ptr +
1162 reinterpret_cast<WirePointer*>(ptr + index * step / BITS_PER_BYTE)); 1209 upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE));
1163 } 1210 }
1164 1211
1165 // ------------------------------------------------------------------- 1212 // -------------------------------------------------------------------
1166 1213
1167 inline ElementCount ListReader::size() const { return elementCount; } 1214 inline ListElementCount ListReader::size() const { return elementCount; }
1168 1215
1169 template <typename T> 1216 template <typename T>
1170 inline T ListReader::getDataElement(ElementCount index) const { 1217 inline T ListReader::getDataElement(ElementCount index) const {
1171 return reinterpret_cast<const WireValue<T>*>(ptr + index * step / BITS_PER_BYTE)->get(); 1218 return reinterpret_cast<const WireValue<T>*>(
1219 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->get();
1172 } 1220 }
1173 1221
1174 template <> 1222 template <>
1175 inline bool ListReader::getDataElement<bool>(ElementCount index) const { 1223 inline bool ListReader::getDataElement<bool>(ElementCount index) const {
1176 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists. 1224 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists.
1177 BitCount bindex = index * (1 * BITS / ELEMENTS); 1225 auto bindex = index * (ONE * BITS / ELEMENTS);
1178 const byte* b = ptr + bindex / BITS_PER_BYTE; 1226 const byte* b = ptr + bindex / BITS_PER_BYTE;
1179 return (*reinterpret_cast<const uint8_t*>(b) & (1 << (bindex % BITS_PER_BYTE / BITS))) != 0; 1227 return (*reinterpret_cast<const uint8_t*>(b) &
1228 unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0;
1180 } 1229 }
1181 1230
1182 template <> 1231 template <>
1183 inline Void ListReader::getDataElement<Void>(ElementCount index) const { 1232 inline Void ListReader::getDataElement<Void>(ElementCount index) const {
1184 return VOID; 1233 return VOID;
1185 } 1234 }
1186 1235
1187 inline PointerReader ListReader::getPointerElement(ElementCount index) const { 1236 inline PointerReader ListReader::getPointerElement(ElementCount index) const {
1188 return PointerReader(segment, capTable, 1237 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>(
1189 reinterpret_cast<const WirePointer*>(ptr + index * step / BITS_PER_BYTE), nestingLimit); 1238 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE), nestingLimit);
1190 } 1239 }
1191 1240
1192 // ------------------------------------------------------------------- 1241 // -------------------------------------------------------------------
1193 1242
1194 inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept 1243 inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept