1// Copyright (c) 2013-2016 Sandstorm Development Group, Inc. and contributors
2// Licensed under the MIT License:
3//
4// Permission is hereby granted, free of charge, to any person obtaining a copy
5// of this software and associated documentation files (the "Software"), to deal
6// in the Software without restriction, including without limitation the rights
7// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8// copies of the Software, and to permit persons to whom the Software is
9// furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20// THE SOFTWARE.
21
22// This file is NOT intended for use by clients, except in generated code.
23//
24// This file defines low-level, non-type-safe classes for traversing the Cap'n Proto memory layout
25// (which is also its wire format). Code generated by the Cap'n Proto compiler uses these classes,
26// as does other parts of the Cap'n proto library which provide a higher-level interface for
27// dynamic introspection.
28
29#pragma once
30
31#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
32#pragma GCC system_header
33#endif
34
35#include <kj/common.h>
36#include <kj/memory.h>
37#include "common.h"
38#include "blob.h"
39#include "endian.h"
40#include <kj/windows-sanity.h> // work-around macro conflict with `VOID`
41
42#if (defined(__mips__) || defined(__hppa__)) && !defined(CAPNP_CANONICALIZE_NAN)
43#define CAPNP_CANONICALIZE_NAN 1
44// Explicitly detect NaNs and canonicalize them to the quiet NaN value as would be returned by
45// __builtin_nan("") on systems implementing the IEEE-754 recommended (but not required) NaN
46// signalling/quiet differentiation (such as x86). Unfortunately, some architectures -- in
47// particular, MIPS -- represent quiet vs. signalling nans differently than the rest of the world.
48// Canonicalizing them makes output consistent (which is important!), but hurts performance
49// slightly.
50//
51// Note that trying to convert MIPS NaNs to standard NaNs without losing data doesn't work.
52// Signaling vs. quiet is indicated by a bit, with the meaning being the opposite on MIPS vs.
53// everyone else. It would be great if we could just flip that bit, but we can't, because if the
54// significand is all-zero, then the value is infinity rather than NaN. This means that on most
55// machines, where the bit indicates quietness, there is one more quiet NaN value than signalling
56// NaN value, whereas on MIPS there is one more sNaN than qNaN, and thus there is no isomorphic
57// mapping that properly preserves quietness. Instead of doing something hacky, we just give up
58// and blow away NaN payloads, because no one uses them anyway.
59#endif
60
61namespace capnp {
62
63#if !CAPNP_LITE
64class ClientHook;
65#endif // !CAPNP_LITE
66
67namespace _ { // private
68
69class PointerBuilder;
70class PointerReader;
71class StructBuilder;
72class StructReader;
73class ListBuilder;
74class ListReader;
75class OrphanBuilder;
76struct WirePointer;
77struct WireHelpers;
78class SegmentReader;
79class SegmentBuilder;
80class Arena;
81class BuilderArena;
82
83// =============================================================================
84
85#if CAPNP_DEBUG_TYPES
86typedef kj::UnitRatio<kj::Bounded<64, uint>, BitLabel, ElementLabel> BitsPerElementTableType;
87#else
88typedef uint BitsPerElementTableType;
89#endif
90
91static constexpr BitsPerElementTableType BITS_PER_ELEMENT_TABLE[8] = {
92 bounded< 0>() * BITS / ELEMENTS,
93 bounded< 1>() * BITS / ELEMENTS,
94 bounded< 8>() * BITS / ELEMENTS,
95 bounded<16>() * BITS / ELEMENTS,
96 bounded<32>() * BITS / ELEMENTS,
97 bounded<64>() * BITS / ELEMENTS,
98 bounded< 0>() * BITS / ELEMENTS,
99 bounded< 0>() * BITS / ELEMENTS
100};
101
102inline KJ_CONSTEXPR() BitsPerElementTableType dataBitsPerElement(ElementSize size) {
103 return _::BITS_PER_ELEMENT_TABLE[static_cast<int>(size)];
104}
105
106inline constexpr PointersPerElementN<1> pointersPerElement(ElementSize size) {
107 return size == ElementSize::POINTER
108 ? PointersPerElementN<1>(ONE * POINTERS / ELEMENTS)
109 : PointersPerElementN<1>(ZERO * POINTERS / ELEMENTS);
110}
111
112static 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
123inline KJ_CONSTEXPR() BitsPerElementTableType bitsPerElementIncludingPointers(ElementSize size) {
124 return _::BITS_PER_ELEMENT_INCLUDING_PONITERS_TABLE[static_cast<int>(size)];
125}
126
127template <size_t size> struct ElementSizeForByteSize;
128template <> struct ElementSizeForByteSize<1> { static constexpr ElementSize value = ElementSize::BYTE; };
129template <> struct ElementSizeForByteSize<2> { static constexpr ElementSize value = ElementSize::TWO_BYTES; };
130template <> struct ElementSizeForByteSize<4> { static constexpr ElementSize value = ElementSize::FOUR_BYTES; };
131template <> struct ElementSizeForByteSize<8> { static constexpr ElementSize value = ElementSize::EIGHT_BYTES; };
132
133template <typename T> struct ElementSizeForType {
134 static constexpr ElementSize value =
135 // Primitive types that aren't special-cased below can be determined from sizeof().
136 CAPNP_KIND(T) == Kind::PRIMITIVE ? ElementSizeForByteSize<sizeof(T)>::value :
137 CAPNP_KIND(T) == Kind::ENUM ? ElementSize::TWO_BYTES :
138 CAPNP_KIND(T) == Kind::STRUCT ? ElementSize::INLINE_COMPOSITE :
139
140 // Everything else is a pointer.
141 ElementSize::POINTER;
142};
143
144// Void and bool are special.
145template <> struct ElementSizeForType<Void> { static constexpr ElementSize value = ElementSize::VOID; };
146template <> struct ElementSizeForType<bool> { static constexpr ElementSize value = ElementSize::BIT; };
147
148// Lists and blobs are pointers, not structs.
149template <typename T, Kind K> struct ElementSizeForType<List<T, K>> {
150 static constexpr ElementSize value = ElementSize::POINTER;
151};
152template <> struct ElementSizeForType<Text> {
153 static constexpr ElementSize value = ElementSize::POINTER;
154};
155template <> struct ElementSizeForType<Data> {
156 static constexpr ElementSize value = ElementSize::POINTER;
157};
158
159template <typename T>
160inline constexpr ElementSize elementSizeForType() {
161 return ElementSizeForType<T>::value;
162}
163
164struct MessageSizeCounts {
165 WordCountN<61, uint64_t> wordCount; // 2^64 bytes
166 uint capCount;
167
168 MessageSizeCounts& operator+=(const MessageSizeCounts& other) {
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);
172 capCount += other.capCount;
173 return *this;
174 }
175
176 void addWords(WordCountN<61, uint64_t> other) {
177 wordCount = assumeBits<61>(wordCount + other);
178 }
179
180 MessageSize asPublic() {
181 return MessageSize { unbound(wordCount / WORDS), capCount };
182 }
183};
184
185// =============================================================================
186
187template <int wordCount>
188union AlignedData {
189 // Useful for declaring static constant data blobs as an array of bytes, but forcing those
190 // bytes to be word-aligned.
191
192 uint8_t bytes[wordCount * sizeof(word)];
193 word words[wordCount];
194};
195
196struct StructSize {
197 StructDataWordCount data;
198 StructPointerCount pointers;
199
200 inline constexpr WordCountN<17> total() const { return data + pointers * WORDS_PER_POINTER; }
201
202 StructSize() = default;
203 inline constexpr StructSize(StructDataWordCount data, StructPointerCount pointers)
204 : data(data), pointers(pointers) {}
205};
206
207template <typename T, typename CapnpPrivate = typename T::_capnpPrivate>
208inline constexpr StructSize structSize() {
209 return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS,
210 bounded(CapnpPrivate::pointerCount) * POINTERS);
211}
212
213template <typename T, typename CapnpPrivate = typename T::_capnpPrivate,
214 typename = kj::EnableIf<CAPNP_KIND(T) == Kind::STRUCT>>
215inline constexpr StructSize minStructSizeForElement() {
216 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough
217 // to hold a T.
218
219 return StructSize(bounded(CapnpPrivate::dataWordSize) * WORDS,
220 bounded(CapnpPrivate::pointerCount) * POINTERS);
221}
222
223template <typename T, typename = kj::EnableIf<CAPNP_KIND(T) != Kind::STRUCT>>
224inline constexpr StructSize minStructSizeForElement() {
225 // If T is a struct, return its struct size. Otherwise return the minimum struct size big enough
226 // to hold a T.
227
228 return StructSize(
229 dataBitsPerElement(elementSizeForType<T>()) * ELEMENTS > ZERO * BITS
230 ? StructDataWordCount(ONE * WORDS) : StructDataWordCount(ZERO * WORDS),
231 pointersPerElement(elementSizeForType<T>()) * ELEMENTS);
232}
233
234// -------------------------------------------------------------------
235// Masking of default values
236
237template <typename T, Kind kind = CAPNP_KIND(T)> struct Mask_;
238template <typename T> struct Mask_<T, Kind::PRIMITIVE> { typedef T Type; };
239template <typename T> struct Mask_<T, Kind::ENUM> { typedef uint16_t Type; };
240template <> struct Mask_<float, Kind::PRIMITIVE> { typedef uint32_t Type; };
241template <> struct Mask_<double, Kind::PRIMITIVE> { typedef uint64_t Type; };
242
243template <typename T> struct Mask_<T, Kind::OTHER> {
244 // Union discriminants end up here.
245 static_assert(sizeof(T) == 2, "Don't know how to mask this type.");
246 typedef uint16_t Type;
247};
248
249template <typename T>
250using Mask = typename Mask_<T>::Type;
251
252template <typename T>
253KJ_ALWAYS_INLINE(Mask<T> mask(T value, Mask<T> mask));
254template <typename T>
255KJ_ALWAYS_INLINE(T unmask(Mask<T> value, Mask<T> mask));
256
257template <typename T>
258inline Mask<T> mask(T value, Mask<T> mask) {
259 return static_cast<Mask<T> >(value) ^ mask;
260}
261
262template <>
263inline uint32_t mask<float>(float value, uint32_t mask) {
264#if CAPNP_CANONICALIZE_NAN
265 if (value != value) {
266 return 0x7fc00000u ^ mask;
267 }
268#endif
269
270 uint32_t i;
271 static_assert(sizeof(i) == sizeof(value), "float is not 32 bits?");
272 memcpy(&i, &value, sizeof(value));
273 return i ^ mask;
274}
275
276template <>
277inline uint64_t mask<double>(double value, uint64_t mask) {
278#if CAPNP_CANONICALIZE_NAN
279 if (value != value) {
280 return 0x7ff8000000000000ull ^ mask;
281 }
282#endif
283
284 uint64_t i;
285 static_assert(sizeof(i) == sizeof(value), "double is not 64 bits?");
286 memcpy(&i, &value, sizeof(value));
287 return i ^ mask;
288}
289
290template <typename T>
291inline T unmask(Mask<T> value, Mask<T> mask) {
292 return static_cast<T>(value ^ mask);
293}
294
295template <>
296inline float unmask<float>(uint32_t value, uint32_t mask) {
297 value ^= mask;
298 float result;
299 static_assert(sizeof(result) == sizeof(value), "float is not 32 bits?");
300 memcpy(&result, &value, sizeof(value));
301 return result;
302}
303
304template <>
305inline double unmask<double>(uint64_t value, uint64_t mask) {
306 value ^= mask;
307 double result;
308 static_assert(sizeof(result) == sizeof(value), "double is not 64 bits?");
309 memcpy(&result, &value, sizeof(value));
310 return result;
311}
312
313// -------------------------------------------------------------------
314
315class CapTableReader {
316public:
317#if !CAPNP_LITE
318 virtual kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) = 0;
319 // Extract the capability at the given index. If the index is invalid, returns null.
320#endif // !CAPNP_LITE
321};
322
323class CapTableBuilder: public CapTableReader {
324public:
325#if !CAPNP_LITE
326 virtual uint injectCap(kj::Own<ClientHook>&& cap) = 0;
327 // Add the capability to the message and return its index. If the same ClientHook is injected
328 // twice, this may return the same index both times, but in this case dropCap() needs to be
329 // called an equal number of times to actually remove the cap.
330
331 virtual void dropCap(uint index) = 0;
332 // Remove a capability injected earlier. Called when the pointer is overwritten or zero'd out.
333#endif // !CAPNP_LITE
334};
335
336// -------------------------------------------------------------------
337
338class PointerBuilder: public kj::DisallowConstCopy {
339 // Represents a single pointer, usually embedded in a struct or a list.
340
341public:
342 inline PointerBuilder(): segment(nullptr), capTable(nullptr), pointer(nullptr) {}
343
344 static inline PointerBuilder getRoot(
345 SegmentBuilder* segment, CapTableBuilder* capTable, word* location);
346 // Get a PointerBuilder representing a message root located in the given segment at the given
347 // location.
348
349 inline bool isNull() { return getPointerType() == PointerType::NULL_; }
350 PointerType getPointerType() const;
351
352 StructBuilder getStruct(StructSize size, const word* defaultValue);
353 ListBuilder getList(ElementSize elementSize, const word* defaultValue);
354 ListBuilder getStructList(StructSize elementSize, const word* defaultValue);
355 ListBuilder getListAnySize(const word* defaultValue);
356 template <typename T> typename T::Builder getBlob(
357 const void* defaultValue, ByteCount defaultSize);
358#if !CAPNP_LITE
359 kj::Own<ClientHook> getCapability();
360#endif // !CAPNP_LITE
361 // Get methods: Get the value. If it is null, initialize it to a copy of the default value.
362 // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
363 // simple byte array for blobs.
364
365 StructBuilder initStruct(StructSize size);
366 ListBuilder initList(ElementSize elementSize, ElementCount elementCount);
367 ListBuilder initStructList(ElementCount elementCount, StructSize size);
368 template <typename T> typename T::Builder initBlob(ByteCount size);
369 // Init methods: Initialize the pointer to a newly-allocated object, discarding the existing
370 // object.
371
372 void setStruct(const StructReader& value, bool canonical = false);
373 void setList(const ListReader& value, bool canonical = false);
374 template <typename T> void setBlob(typename T::Reader value);
375#if !CAPNP_LITE
376 void setCapability(kj::Own<ClientHook>&& cap);
377#endif // !CAPNP_LITE
378 // Set methods: Initialize the pointer to a newly-allocated copy of the given value, discarding
379 // the existing object.
380
381 void adopt(OrphanBuilder&& orphan);
382 // Set the pointer to point at the given orphaned value.
383
384 OrphanBuilder disown();
385 // Set the pointer to null and return its previous value as an orphan.
386
387 void clear();
388 // Clear the pointer to null, discarding its previous value.
389
390 void transferFrom(PointerBuilder other);
391 // Equivalent to `adopt(other.disown())`.
392
393 void copyFrom(PointerReader other, bool canonical = false);
394 // Equivalent to `set(other.get())`.
395 // If you set the canonical flag, it will attempt to lay the target out
396 // canonically, provided enough space is available.
397
398 PointerReader asReader() const;
399
400 BuilderArena* getArena() const;
401 // Get the arena containing this pointer.
402
403 CapTableBuilder* getCapTable();
404 // Gets the capability context in which this object is operating.
405
406 PointerBuilder imbue(CapTableBuilder* capTable);
407 // Return a copy of this builder except using the given capability context.
408
409private:
410 SegmentBuilder* segment; // Memory segment in which the pointer resides.
411 CapTableBuilder* capTable; // Table of capability indexes.
412 WirePointer* pointer; // Pointer to the pointer.
413
414 inline PointerBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, WirePointer* pointer)
415 : segment(segment), capTable(capTable), pointer(pointer) {}
416
417 friend class StructBuilder;
418 friend class ListBuilder;
419 friend class OrphanBuilder;
420};
421
422class PointerReader {
423public:
424 inline PointerReader()
425 : segment(nullptr), capTable(nullptr), pointer(nullptr), nestingLimit(0x7fffffff) {}
426
427 static PointerReader getRoot(SegmentReader* segment, CapTableReader* capTable,
428 const word* location, int nestingLimit);
429 // Get a PointerReader representing a message root located in the given segment at the given
430 // location.
431
432 static inline PointerReader getRootUnchecked(const word* location);
433 // Get a PointerReader for an unchecked message.
434
435 MessageSizeCounts targetSize() const;
436 // Return the total size of the target object and everything to which it points. Does not count
437 // far pointer overhead. This is useful for deciding how much space is needed to copy the object
438 // into a flat array. However, the caller is advised NOT to treat this value as secure. Instead,
439 // use the result as a hint for allocating the first segment, do the copy, and then throw an
440 // exception if it overruns.
441
442 inline bool isNull() const { return getPointerType() == PointerType::NULL_; }
443 PointerType getPointerType() const;
444
445 StructReader getStruct(const word* defaultValue) const;
446 ListReader getList(ElementSize expectedElementSize, const word* defaultValue) const;
447 ListReader getListAnySize(const word* defaultValue) const;
448 template <typename T>
449 typename T::Reader getBlob(const void* defaultValue, ByteCount defaultSize) const;
450#if !CAPNP_LITE
451 kj::Own<ClientHook> getCapability() const;
452#endif // !CAPNP_LITE
453 // Get methods: Get the value. If it is null, return the default value instead.
454 // The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
455 // simple byte array for blobs.
456
457 const word* getUnchecked() const;
458 // If this is an unchecked message, get a word* pointing at the location of the pointer. This
459 // word* can actually be passed to readUnchecked() to read the designated sub-object later. If
460 // this isn't an unchecked message, throws an exception.
461
462 kj::Maybe<Arena&> getArena() const;
463 // Get the arena containing this pointer.
464
465 CapTableReader* getCapTable();
466 // Gets the capability context in which this object is operating.
467
468 PointerReader imbue(CapTableReader* capTable) const;
469 // Return a copy of this reader except using the given capability context.
470
471 bool isCanonical(const word **readHead);
472 // Validate this pointer's canonicity, subject to the conditions:
473 // * All data to the left of readHead has been read thus far (for pointer
474 // ordering)
475 // * All pointers in preorder have already been checked
476 // * This pointer is in the first and only segment of the message
477
478private:
479 SegmentReader* segment; // Memory segment in which the pointer resides.
480 CapTableReader* capTable; // Table of capability indexes.
481 const WirePointer* pointer; // Pointer to the pointer. null = treat as null pointer.
482
483 int nestingLimit;
484 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
485 // Once this reaches zero, further pointers will be pruned.
486
487 inline PointerReader(SegmentReader* segment, CapTableReader* capTable,
488 const WirePointer* pointer, int nestingLimit)
489 : segment(segment), capTable(capTable), pointer(pointer), nestingLimit(nestingLimit) {}
490
491 friend class StructReader;
492 friend class ListReader;
493 friend class PointerBuilder;
494 friend class OrphanBuilder;
495};
496
497// -------------------------------------------------------------------
498
499class StructBuilder: public kj::DisallowConstCopy {
500public:
501 inline StructBuilder(): segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr) {}
502
503 inline word* getLocation() { return reinterpret_cast<word*>(data); }
504 // Get the object's location. Only valid for independently-allocated objects (i.e. not list
505 // elements).
506
507 inline StructDataBitCount getDataSectionSize() const { return dataSize; }
508 inline StructPointerCount getPointerSectionSize() const { return pointerCount; }
509 inline kj::ArrayPtr<byte> getDataSectionAsBlob();
510 inline _::ListBuilder getPointerSectionAsList();
511
512 template <typename T>
513 KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset));
514 // Return true if the field is set to something other than its default value.
515
516 template <typename T>
517 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset));
518 // Gets the data field value of the given type at the given offset. The offset is measured in
519 // multiples of the field size, determined by the type.
520
521 template <typename T>
522 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask<T> mask));
523 // Like getDataField() but applies the given XOR mask to the data on load. Used for reading
524 // fields with non-zero default values.
525
526 template <typename T>
527 KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset, kj::NoInfer<T> value));
528 // Sets the data field value at the given offset.
529
530 template <typename T>
531 KJ_ALWAYS_INLINE(void setDataField(StructDataOffset offset,
532 kj::NoInfer<T> value, Mask<T> mask));
533 // Like setDataField() but applies the given XOR mask before storing. Used for writing fields
534 // with non-zero default values.
535
536 KJ_ALWAYS_INLINE(PointerBuilder getPointerField(StructPointerOffset ptrIndex));
537 // Get a builder for a pointer field given the index within the pointer section.
538
539 void clearAll();
540 // Clear all pointers and data.
541
542 void transferContentFrom(StructBuilder other);
543 // Adopt all pointers from `other`, and also copy all data. If `other`'s sections are larger
544 // than this, the extra data is not transferred, meaning there is a risk of data loss when
545 // transferring from messages built with future versions of the protocol.
546
547 void copyContentFrom(StructReader other);
548 // Copy content from `other`. If `other`'s sections are larger than this, the extra data is not
549 // copied, meaning there is a risk of data loss when copying from messages built with future
550 // versions of the protocol.
551
552 StructReader asReader() const;
553 // Gets a StructReader pointing at the same memory.
554
555 BuilderArena* getArena();
556 // Gets the arena in which this object is allocated.
557
558 CapTableBuilder* getCapTable();
559 // Gets the capability context in which this object is operating.
560
561 StructBuilder imbue(CapTableBuilder* capTable);
562 // Return a copy of this builder except using the given capability context.
563
564private:
565 SegmentBuilder* segment; // Memory segment in which the struct resides.
566 CapTableBuilder* capTable; // Table of capability indexes.
567 void* data; // Pointer to the encoded data.
568 WirePointer* pointers; // Pointer to the encoded pointers.
569
570 StructDataBitCount dataSize;
571 // Size of data section. We use a bit count rather than a word count to more easily handle the
572 // case of struct lists encoded with less than a word per element.
573
574 StructPointerCount pointerCount; // Size of the pointer section.
575
576 inline StructBuilder(SegmentBuilder* segment, CapTableBuilder* capTable,
577 void* data, WirePointer* pointers,
578 StructDataBitCount dataSize, StructPointerCount pointerCount)
579 : segment(segment), capTable(capTable), data(data), pointers(pointers),
580 dataSize(dataSize), pointerCount(pointerCount) {}
581
582 friend class ListBuilder;
583 friend struct WireHelpers;
584 friend class OrphanBuilder;
585};
586
587class StructReader {
588public:
589 inline StructReader()
590 : segment(nullptr), capTable(nullptr), data(nullptr), pointers(nullptr),
591 dataSize(ZERO * BITS), pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {}
592 inline StructReader(kj::ArrayPtr<const word> data)
593 : segment(nullptr), capTable(nullptr), data(data.begin()), pointers(nullptr),
594 dataSize(assumeBits<STRUCT_DATA_WORD_COUNT_BITS>(data.size()) * WORDS * BITS_PER_WORD),
595 pointerCount(ZERO * POINTERS), nestingLimit(0x7fffffff) {}
596
597 const void* getLocation() const { return data; }
598
599 inline StructDataBitCount getDataSectionSize() const { return dataSize; }
600 inline StructPointerCount getPointerSectionSize() const { return pointerCount; }
601 inline kj::ArrayPtr<const byte> getDataSectionAsBlob() const;
602 inline _::ListReader getPointerSectionAsList() const;
603
604 kj::Array<word> canonicalize();
605
606 template <typename T>
607 KJ_ALWAYS_INLINE(bool hasDataField(StructDataOffset offset) const);
608 // Return true if the field is set to something other than its default value.
609
610 template <typename T>
611 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset) const);
612 // Get the data field value of the given type at the given offset. The offset is measured in
613 // multiples of the field size, determined by the type. Returns zero if the offset is past the
614 // end of the struct's data section.
615
616 template <typename T>
617 KJ_ALWAYS_INLINE(T getDataField(StructDataOffset offset, Mask<T> mask) const);
618 // Like getDataField(offset), but applies the given XOR mask to the result. Used for reading
619 // fields with non-zero default values.
620
621 KJ_ALWAYS_INLINE(PointerReader getPointerField(StructPointerOffset ptrIndex) const);
622 // Get a reader for a pointer field given the index within the pointer section. If the index
623 // is out-of-bounds, returns a null pointer.
624
625 MessageSizeCounts totalSize() const;
626 // Return the total size of the struct and everything to which it points. Does not count far
627 // pointer overhead. This is useful for deciding how much space is needed to copy the struct
628 // into a flat array.
629
630 CapTableReader* getCapTable();
631 // Gets the capability context in which this object is operating.
632
633 StructReader imbue(CapTableReader* capTable) const;
634 // Return a copy of this reader except using the given capability context.
635
636 bool isCanonical(const word **readHead, const word **ptrHead,
637 bool *dataTrunc, bool *ptrTrunc);
638 // Validate this pointer's canonicity, subject to the conditions:
639 // * All data to the left of readHead has been read thus far (for pointer
640 // ordering)
641 // * All pointers in preorder have already been checked
642 // * This pointer is in the first and only segment of the message
643 //
644 // If this function returns false, the struct is non-canonical. If it
645 // returns true, then:
646 // * If it is a composite in a list, it is canonical if at least one struct
647 // in the list outputs dataTrunc = 1, and at least one outputs ptrTrunc = 1
648 // * If it is derived from a struct pointer, it is canonical if
649 // dataTrunc = 1 AND ptrTrunc = 1
650
651private:
652 SegmentReader* segment; // Memory segment in which the struct resides.
653 CapTableReader* capTable; // Table of capability indexes.
654
655 const void* data;
656 const WirePointer* pointers;
657
658 StructDataBitCount dataSize;
659 // Size of data section. We use a bit count rather than a word count to more easily handle the
660 // case of struct lists encoded with less than a word per element.
661
662 StructPointerCount pointerCount; // Size of the pointer section.
663
664 int nestingLimit;
665 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
666 // Once this reaches zero, further pointers will be pruned.
667 // TODO(perf): Limit to 16 bits for better packing?
668
669 inline StructReader(SegmentReader* segment, CapTableReader* capTable,
670 const void* data, const WirePointer* pointers,
671 StructDataBitCount dataSize, StructPointerCount pointerCount,
672 int nestingLimit)
673 : segment(segment), capTable(capTable), data(data), pointers(pointers),
674 dataSize(dataSize), pointerCount(pointerCount),
675 nestingLimit(nestingLimit) {}
676
677 friend class ListReader;
678 friend class StructBuilder;
679 friend struct WireHelpers;
680};
681
682// -------------------------------------------------------------------
683
684class ListBuilder: public kj::DisallowConstCopy {
685public:
686 inline explicit ListBuilder(ElementSize elementSize)
687 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS),
688 step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS),
689 structPointerCount(ZERO * POINTERS), elementSize(elementSize) {}
690
691 inline word* getLocation() {
692 // Get the object's location.
693
694 if (elementSize == ElementSize::INLINE_COMPOSITE && ptr != nullptr) {
695 return reinterpret_cast<word*>(ptr) - POINTER_SIZE_IN_WORDS;
696 } else {
697 return reinterpret_cast<word*>(ptr);
698 }
699 }
700
701 inline ElementSize getElementSize() const { return elementSize; }
702
703 inline ListElementCount size() const;
704 // The number of elements in the list.
705
706 Text::Builder asText();
707 Data::Builder asData();
708 // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized.
709
710 template <typename T>
711 KJ_ALWAYS_INLINE(T getDataElement(ElementCount index));
712 // Get the element of the given type at the given index.
713
714 template <typename T>
715 KJ_ALWAYS_INLINE(void setDataElement(ElementCount index, kj::NoInfer<T> value));
716 // Set the element at the given index.
717
718 KJ_ALWAYS_INLINE(PointerBuilder getPointerElement(ElementCount index));
719
720 StructBuilder getStructElement(ElementCount index);
721
722 ListReader asReader() const;
723 // Get a ListReader pointing at the same memory.
724
725 BuilderArena* getArena();
726 // Gets the arena in which this object is allocated.
727
728 CapTableBuilder* getCapTable();
729 // Gets the capability context in which this object is operating.
730
731 ListBuilder imbue(CapTableBuilder* capTable);
732 // Return a copy of this builder except using the given capability context.
733
734private:
735 SegmentBuilder* segment; // Memory segment in which the list resides.
736 CapTableBuilder* capTable; // Table of capability indexes.
737
738 byte* ptr; // Pointer to list content.
739
740 ListElementCount elementCount; // Number of elements in the list.
741
742 BitsPerElementN<23> step;
743 // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data
744 // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 128 bits.
745
746 StructDataBitCount structDataSize;
747 StructPointerCount structPointerCount;
748 // The struct properties to use when interpreting the elements as structs. All lists can be
749 // interpreted as struct lists, so these are always filled in.
750
751 ElementSize elementSize;
752 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE
753 // from other types when the overall size is exactly zero or one words.
754
755 inline ListBuilder(SegmentBuilder* segment, CapTableBuilder* capTable, void* ptr,
756 BitsPerElementN<23> step, ListElementCount size,
757 StructDataBitCount structDataSize, StructPointerCount structPointerCount,
758 ElementSize elementSize)
759 : segment(segment), capTable(capTable), ptr(reinterpret_cast<byte*>(ptr)),
760 elementCount(size), step(step), structDataSize(structDataSize),
761 structPointerCount(structPointerCount), elementSize(elementSize) {}
762
763 friend class StructBuilder;
764 friend struct WireHelpers;
765 friend class OrphanBuilder;
766};
767
768class ListReader {
769public:
770 inline explicit ListReader(ElementSize elementSize)
771 : segment(nullptr), capTable(nullptr), ptr(nullptr), elementCount(ZERO * ELEMENTS),
772 step(ZERO * BITS / ELEMENTS), structDataSize(ZERO * BITS),
773 structPointerCount(ZERO * POINTERS), elementSize(elementSize), nestingLimit(0x7fffffff) {}
774
775 inline ListElementCount size() const;
776 // The number of elements in the list.
777
778 inline ElementSize getElementSize() const { return elementSize; }
779
780 Text::Reader asText();
781 Data::Reader asData();
782 // Reinterpret the list as a blob. Throws an exception if the elements are not byte-sized.
783
784 kj::ArrayPtr<const byte> asRawBytes() const;
785
786 template <typename T>
787 KJ_ALWAYS_INLINE(T getDataElement(ElementCount index) const);
788 // Get the element of the given type at the given index.
789
790 KJ_ALWAYS_INLINE(PointerReader getPointerElement(ElementCount index) const);
791
792 StructReader getStructElement(ElementCount index) const;
793
794 MessageSizeCounts totalSize() const;
795 // Like StructReader::totalSize(). Note that for struct lists, the size includes the list tag.
796
797 CapTableReader* getCapTable();
798 // Gets the capability context in which this object is operating.
799
800 ListReader imbue(CapTableReader* capTable) const;
801 // Return a copy of this reader except using the given capability context.
802
803 bool isCanonical(const word **readHead, const WirePointer* ref);
804 // Validate this pointer's canonicity, subject to the conditions:
805 // * All data to the left of readHead has been read thus far (for pointer
806 // ordering)
807 // * All pointers in preorder have already been checked
808 // * This pointer is in the first and only segment of the message
809
810private:
811 SegmentReader* segment; // Memory segment in which the list resides.
812 CapTableReader* capTable; // Table of capability indexes.
813
814 const byte* ptr; // Pointer to list content.
815
816 ListElementCount elementCount; // Number of elements in the list.
817
818 BitsPerElementN<23> step;
819 // The distance between elements. The maximum value occurs when a struct contains 2^16-1 data
820 // words and 2^16-1 pointers, i.e. 2^17 - 2 words, or 2^23 - 2 bits.
821
822 StructDataBitCount structDataSize;
823 StructPointerCount structPointerCount;
824 // The struct properties to use when interpreting the elements as structs. All lists can be
825 // interpreted as struct lists, so these are always filled in.
826
827 ElementSize elementSize;
828 // The element size as a ElementSize. This is only really needed to disambiguate INLINE_COMPOSITE
829 // from other types when the overall size is exactly zero or one words.
830
831 int nestingLimit;
832 // Limits the depth of message structures to guard against stack-overflow-based DoS attacks.
833 // Once this reaches zero, further pointers will be pruned.
834
835 inline ListReader(SegmentReader* segment, CapTableReader* capTable, const void* ptr,
836 ListElementCount elementCount, BitsPerElementN<23> step,
837 StructDataBitCount structDataSize, StructPointerCount structPointerCount,
838 ElementSize elementSize, int nestingLimit)
839 : segment(segment), capTable(capTable), ptr(reinterpret_cast<const byte*>(ptr)),
840 elementCount(elementCount), step(step), structDataSize(structDataSize),
841 structPointerCount(structPointerCount), elementSize(elementSize),
842 nestingLimit(nestingLimit) {}
843
844 friend class StructReader;
845 friend class ListBuilder;
846 friend struct WireHelpers;
847 friend class OrphanBuilder;
848};
849
850// -------------------------------------------------------------------
851
852class OrphanBuilder {
853public:
854 inline OrphanBuilder(): segment(nullptr), capTable(nullptr), location(nullptr) {
855 memset(&tag, 0, sizeof(tag));
856 }
857 OrphanBuilder(const OrphanBuilder& other) = delete;
858 inline OrphanBuilder(OrphanBuilder&& other) noexcept;
859 inline ~OrphanBuilder() noexcept(false);
860
861 static OrphanBuilder initStruct(BuilderArena* arena, CapTableBuilder* capTable, StructSize size);
862 static OrphanBuilder initList(BuilderArena* arena, CapTableBuilder* capTable,
863 ElementCount elementCount, ElementSize elementSize);
864 static OrphanBuilder initStructList(BuilderArena* arena, CapTableBuilder* capTable,
865 ElementCount elementCount, StructSize elementSize);
866 static OrphanBuilder initText(BuilderArena* arena, CapTableBuilder* capTable, ByteCount size);
867 static OrphanBuilder initData(BuilderArena* arena, CapTableBuilder* capTable, ByteCount size);
868
869 static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, StructReader copyFrom);
870 static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, ListReader copyFrom);
871 static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, PointerReader copyFrom);
872 static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, Text::Reader copyFrom);
873 static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable, Data::Reader copyFrom);
874#if !CAPNP_LITE
875 static OrphanBuilder copy(BuilderArena* arena, CapTableBuilder* capTable,
876 kj::Own<ClientHook> copyFrom);
877#endif // !CAPNP_LITE
878
879 static OrphanBuilder concat(BuilderArena* arena, CapTableBuilder* capTable,
880 ElementSize expectedElementSize, StructSize expectedStructSize,
881 kj::ArrayPtr<const ListReader> lists);
882
883 static OrphanBuilder referenceExternalData(BuilderArena* arena, Data::Reader data);
884
885 OrphanBuilder& operator=(const OrphanBuilder& other) = delete;
886 inline OrphanBuilder& operator=(OrphanBuilder&& other);
887
888 inline bool operator==(decltype(nullptr)) const { return location == nullptr; }
889 inline bool operator!=(decltype(nullptr)) const { return location != nullptr; }
890
891 StructBuilder asStruct(StructSize size);
892 // Interpret as a struct, or throw an exception if not a struct.
893
894 ListBuilder asList(ElementSize elementSize);
895 // Interpret as a list, or throw an exception if not a list. elementSize cannot be
896 // INLINE_COMPOSITE -- use asStructList() instead.
897
898 ListBuilder asStructList(StructSize elementSize);
899 // Interpret as a struct list, or throw an exception if not a list.
900
901 ListBuilder asListAnySize();
902 // For AnyList.
903
904 Text::Builder asText();
905 Data::Builder asData();
906 // Interpret as a blob, or throw an exception if not a blob.
907
908 StructReader asStructReader(StructSize size) const;
909 ListReader asListReader(ElementSize elementSize) const;
910 ListReader asListReaderAnySize() const;
911#if !CAPNP_LITE
912 kj::Own<ClientHook> asCapability() const;
913#endif // !CAPNP_LITE
914 Text::Reader asTextReader() const;
915 Data::Reader asDataReader() const;
916
917 bool truncate(ElementCount size, bool isText) KJ_WARN_UNUSED_RESULT;
918 // Resize the orphan list to the given size. Returns false if the list is currently empty but
919 // the requested size is non-zero, in which case the caller will need to allocate a new list.
920
921 void truncate(ElementCount size, ElementSize elementSize);
922 void truncate(ElementCount size, StructSize elementSize);
923 void truncateText(ElementCount size);
924 // Versions of truncate() that know how to allocate a new list if needed.
925
926private:
927 static_assert(ONE * POINTERS * WORDS_PER_POINTER == ONE * WORDS,
928 "This struct assumes a pointer is one word.");
929 word tag;
930 // Contains an encoded WirePointer representing this object. WirePointer is defined in
931 // layout.c++, but fits in a word.
932 //
933 // This may be a FAR pointer. Even in that case, `location` points to the eventual destination
934 // of that far pointer. The reason we keep the far pointer around rather than just making `tag`
935 // represent the final destination is because if the eventual adopter of the pointer is not in
936 // the target's segment then it may be useful to reuse the far pointer landing pad.
937 //
938 // If `tag` is not a far pointer, its offset is garbage; only `location` points to the actual
939 // target.
940
941 SegmentBuilder* segment;
942 // Segment in which the object resides.
943
944 CapTableBuilder* capTable;
945 // Table of capability indexes.
946
947 word* location;
948 // Pointer to the object, or nullptr if the pointer is null. For capabilities, we make this
949 // 0x1 just so that it is non-null for operator==, but it is never used.
950
951 inline OrphanBuilder(const void* tagPtr, SegmentBuilder* segment,
952 CapTableBuilder* capTable, word* location)
953 : segment(segment), capTable(capTable), location(location) {
954 memcpy(&tag, tagPtr, sizeof(tag));
955 }
956
957 inline WirePointer* tagAsPtr() { return reinterpret_cast<WirePointer*>(&tag); }
958 inline const WirePointer* tagAsPtr() const { return reinterpret_cast<const WirePointer*>(&tag); }
959
960 void euthanize();
961 // Erase the target object, zeroing it out and possibly reclaiming the memory. Called when
962 // the OrphanBuilder is being destroyed or overwritten and it is non-null.
963
964 friend struct WireHelpers;
965};
966
967// =======================================================================================
968// Internal implementation details...
969
970// These are defined in the source file.
971template <> typename Text::Builder PointerBuilder::initBlob<Text>(ByteCount size);
972template <> void PointerBuilder::setBlob<Text>(typename Text::Reader value);
973template <> typename Text::Builder PointerBuilder::getBlob<Text>(
974 const void* defaultValue, ByteCount defaultSize);
975template <> typename Text::Reader PointerReader::getBlob<Text>(
976 const void* defaultValue, ByteCount defaultSize) const;
977
978template <> typename Data::Builder PointerBuilder::initBlob<Data>(ByteCount size);
979template <> void PointerBuilder::setBlob<Data>(typename Data::Reader value);
980template <> typename Data::Builder PointerBuilder::getBlob<Data>(
981 const void* defaultValue, ByteCount defaultSize);
982template <> typename Data::Reader PointerReader::getBlob<Data>(
983 const void* defaultValue, ByteCount defaultSize) const;
984
985inline PointerBuilder PointerBuilder::getRoot(
986 SegmentBuilder* segment, CapTableBuilder* capTable, word* location) {
987 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(location));
988}
989
990inline PointerReader PointerReader::getRootUnchecked(const word* location) {
991 return PointerReader(nullptr, nullptr,
992 reinterpret_cast<const WirePointer*>(location), 0x7fffffff);
993}
994
995// -------------------------------------------------------------------
996
997inline kj::ArrayPtr<byte> StructBuilder::getDataSectionAsBlob() {
998 return kj::ArrayPtr<byte>(reinterpret_cast<byte*>(data),
999 unbound(dataSize / BITS_PER_BYTE / BYTES));
1000}
1001
1002inline _::ListBuilder StructBuilder::getPointerSectionAsList() {
1003 return _::ListBuilder(segment, capTable, pointers, ONE * POINTERS * BITS_PER_POINTER / ELEMENTS,
1004 pointerCount * (ONE * ELEMENTS / POINTERS),
1005 ZERO * BITS, ONE * POINTERS, ElementSize::POINTER);
1006}
1007
1008template <typename T>
1009inline bool StructBuilder::hasDataField(StructDataOffset offset) {
1010 return getDataField<Mask<T>>(offset) != 0;
1011}
1012
1013template <>
1014inline bool StructBuilder::hasDataField<Void>(StructDataOffset offset) {
1015 return false;
1016}
1017
1018template <typename T>
1019inline T StructBuilder::getDataField(StructDataOffset offset) {
1020 return reinterpret_cast<WireValue<T>*>(data)[unbound(offset / ELEMENTS)].get();
1021}
1022
1023template <>
1024inline bool StructBuilder::getDataField<bool>(StructDataOffset offset) {
1025 BitCount32 boffset = offset * (ONE * BITS / ELEMENTS);
1026 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
1027 return (*reinterpret_cast<uint8_t*>(b) &
1028 unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0;
1029}
1030
1031template <>
1032inline Void StructBuilder::getDataField<Void>(StructDataOffset offset) {
1033 return VOID;
1034}
1035
1036template <typename T>
1037inline T StructBuilder::getDataField(StructDataOffset offset, Mask<T> mask) {
1038 return unmask<T>(getDataField<Mask<T> >(offset), mask);
1039}
1040
1041template <typename T>
1042inline void StructBuilder::setDataField(StructDataOffset offset, kj::NoInfer<T> value) {
1043 reinterpret_cast<WireValue<T>*>(data)[unbound(offset / ELEMENTS)].set(value);
1044}
1045
1046#if CAPNP_CANONICALIZE_NAN
1047// Use mask() on floats and doubles to make sure we canonicalize NaNs.
1048template <>
1049inline void StructBuilder::setDataField<float>(StructDataOffset offset, float value) {
1050 setDataField<uint32_t>(offset, mask<float>(value, 0));
1051}
1052template <>
1053inline void StructBuilder::setDataField<double>(StructDataOffset offset, double value) {
1054 setDataField<uint64_t>(offset, mask<double>(value, 0));
1055}
1056#endif
1057
1058template <>
1059inline void StructBuilder::setDataField<bool>(StructDataOffset offset, bool value) {
1060 auto boffset = offset * (ONE * BITS / ELEMENTS);
1061 byte* b = reinterpret_cast<byte*>(data) + boffset / BITS_PER_BYTE;
1062 uint bitnum = unboundMaxBits<3>(boffset % BITS_PER_BYTE / BITS);
1063 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << bitnum))
1064 | (static_cast<uint8_t>(value) << bitnum);
1065}
1066
1067template <>
1068inline void StructBuilder::setDataField<Void>(StructDataOffset offset, Void value) {}
1069
1070template <typename T>
1071inline void StructBuilder::setDataField(StructDataOffset offset,
1072 kj::NoInfer<T> value, Mask<T> m) {
1073 setDataField<Mask<T> >(offset, mask<T>(value, m));
1074}
1075
1076inline PointerBuilder StructBuilder::getPointerField(StructPointerOffset ptrIndex) {
1077 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here).
1078 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(
1079 reinterpret_cast<word*>(pointers) + ptrIndex * WORDS_PER_POINTER));
1080}
1081
1082// -------------------------------------------------------------------
1083
1084inline kj::ArrayPtr<const byte> StructReader::getDataSectionAsBlob() const {
1085 return kj::ArrayPtr<const byte>(reinterpret_cast<const byte*>(data),
1086 unbound(dataSize / BITS_PER_BYTE / BYTES));
1087}
1088
1089inline _::ListReader StructReader::getPointerSectionAsList() const {
1090 return _::ListReader(segment, capTable, pointers, pointerCount * (ONE * ELEMENTS / POINTERS),
1091 ONE * POINTERS * BITS_PER_POINTER / ELEMENTS, ZERO * BITS, ONE * POINTERS,
1092 ElementSize::POINTER, nestingLimit);
1093}
1094
1095template <typename T>
1096inline bool StructReader::hasDataField(StructDataOffset offset) const {
1097 return getDataField<Mask<T>>(offset) != 0;
1098}
1099
1100template <>
1101inline bool StructReader::hasDataField<Void>(StructDataOffset offset) const {
1102 return false;
1103}
1104
1105template <typename T>
1106inline T StructReader::getDataField(StructDataOffset offset) const {
1107 if ((offset + ONE * ELEMENTS) * capnp::bitsPerElement<T>() <= dataSize) {
1108 return reinterpret_cast<const WireValue<T>*>(data)[unbound(offset / ELEMENTS)].get();
1109 } else {
1110 return static_cast<T>(0);
1111 }
1112}
1113
1114template <>
1115inline bool StructReader::getDataField<bool>(StructDataOffset offset) const {
1116 auto boffset = offset * (ONE * BITS / ELEMENTS);
1117 if (boffset < dataSize) {
1118 const byte* b = reinterpret_cast<const byte*>(data) + boffset / BITS_PER_BYTE;
1119 return (*reinterpret_cast<const uint8_t*>(b) &
1120 unbound(ONE << (boffset % BITS_PER_BYTE / BITS))) != 0;
1121 } else {
1122 return false;
1123 }
1124}
1125
1126template <>
1127inline Void StructReader::getDataField<Void>(StructDataOffset offset) const {
1128 return VOID;
1129}
1130
1131template <typename T>
1132T StructReader::getDataField(StructDataOffset offset, Mask<T> mask) const {
1133 return unmask<T>(getDataField<Mask<T> >(offset), mask);
1134}
1135
1136inline PointerReader StructReader::getPointerField(StructPointerOffset ptrIndex) const {
1137 if (ptrIndex < pointerCount) {
1138 // Hacky because WirePointer is defined in the .c++ file (so is incomplete here).
1139 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>(
1140 reinterpret_cast<const word*>(pointers) + ptrIndex * WORDS_PER_POINTER), nestingLimit);
1141 } else{
1142 return PointerReader();
1143 }
1144}
1145
1146// -------------------------------------------------------------------
1147
1148inline ListElementCount ListBuilder::size() const { return elementCount; }
1149
1150template <typename T>
1151inline T ListBuilder::getDataElement(ElementCount index) {
1152 return reinterpret_cast<WireValue<T>*>(
1153 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->get();
1154
1155 // TODO(perf): Benchmark this alternate implementation, which I suspect may make better use of
1156 // the x86 SIB byte. Also use it for all the other getData/setData implementations below, and
1157 // the various non-inline methods that look up pointers.
1158 // Also if using this, consider changing ptr back to void* instead of byte*.
1159// return reinterpret_cast<WireValue<T>*>(ptr)[
1160// index / ELEMENTS * (step / capnp::bitsPerElement<T>())].get();
1161}
1162
1163template <>
1164inline bool ListBuilder::getDataElement<bool>(ElementCount index) {
1165 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists.
1166 auto bindex = index * (ONE * BITS / ELEMENTS);
1167 byte* b = ptr + bindex / BITS_PER_BYTE;
1168 return (*reinterpret_cast<uint8_t*>(b) &
1169 unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0;
1170}
1171
1172template <>
1173inline Void ListBuilder::getDataElement<Void>(ElementCount index) {
1174 return VOID;
1175}
1176
1177template <typename T>
1178inline void ListBuilder::setDataElement(ElementCount index, kj::NoInfer<T> value) {
1179 reinterpret_cast<WireValue<T>*>(
1180 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->set(value);
1181}
1182
1183#if CAPNP_CANONICALIZE_NAN
1184// Use mask() on floats and doubles to make sure we canonicalize NaNs.
1185template <>
1186inline void ListBuilder::setDataElement<float>(ElementCount index, float value) {
1187 setDataElement<uint32_t>(index, mask<float>(value, 0));
1188}
1189template <>
1190inline void ListBuilder::setDataElement<double>(ElementCount index, double value) {
1191 setDataElement<uint64_t>(index, mask<double>(value, 0));
1192}
1193#endif
1194
1195template <>
1196inline void ListBuilder::setDataElement<bool>(ElementCount index, bool value) {
1197 // Ignore stepBytes for bit lists because bit lists cannot be upgraded to struct lists.
1198 auto bindex = index * (ONE * BITS / ELEMENTS);
1199 byte* b = ptr + bindex / BITS_PER_BYTE;
1200 auto bitnum = bindex % BITS_PER_BYTE / BITS;
1201 *reinterpret_cast<uint8_t*>(b) = (*reinterpret_cast<uint8_t*>(b) & ~(1 << unbound(bitnum)))
1202 | (static_cast<uint8_t>(value) << unbound(bitnum));
1203}
1204
1205template <>
1206inline void ListBuilder::setDataElement<Void>(ElementCount index, Void value) {}
1207
1208inline PointerBuilder ListBuilder::getPointerElement(ElementCount index) {
1209 return PointerBuilder(segment, capTable, reinterpret_cast<WirePointer*>(ptr +
1210 upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE));
1211}
1212
1213// -------------------------------------------------------------------
1214
1215inline ListElementCount ListReader::size() const { return elementCount; }
1216
1217template <typename T>
1218inline T ListReader::getDataElement(ElementCount index) const {
1219 return reinterpret_cast<const WireValue<T>*>(
1220 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE)->get();
1221}
1222
1223template <>
1224inline bool ListReader::getDataElement<bool>(ElementCount index) const {
1225 // Ignore step for bit lists because bit lists cannot be upgraded to struct lists.
1226 auto bindex = index * (ONE * BITS / ELEMENTS);
1227 const byte* b = ptr + bindex / BITS_PER_BYTE;
1228 return (*reinterpret_cast<const uint8_t*>(b) &
1229 unbound(ONE << (bindex % BITS_PER_BYTE / BITS))) != 0;
1230}
1231
1232template <>
1233inline Void ListReader::getDataElement<Void>(ElementCount index) const {
1234 return VOID;
1235}
1236
1237inline PointerReader ListReader::getPointerElement(ElementCount index) const {
1238 return PointerReader(segment, capTable, reinterpret_cast<const WirePointer*>(
1239 ptr + upgradeBound<uint64_t>(index) * step / BITS_PER_BYTE), nestingLimit);
1240}
1241
1242// -------------------------------------------------------------------
1243
1244inline OrphanBuilder::OrphanBuilder(OrphanBuilder&& other) noexcept
1245 : segment(other.segment), capTable(other.capTable), location(other.location) {
1246 memcpy(&tag, &other.tag, sizeof(tag)); // Needs memcpy to comply with aliasing rules.
1247 other.segment = nullptr;
1248 other.location = nullptr;
1249}
1250
1251inline OrphanBuilder::~OrphanBuilder() noexcept(false) {
1252 if (segment != nullptr) euthanize();
1253}
1254
1255inline OrphanBuilder& OrphanBuilder::operator=(OrphanBuilder&& other) {
1256 // With normal smart pointers, it's important to handle the case where the incoming pointer
1257 // is actually transitively owned by this one. In this case, euthanize() would destroy `other`
1258 // before we copied it. This isn't possible in the case of `OrphanBuilder` because it only
1259 // owns message objects, and `other` is not itself a message object, therefore cannot possibly
1260 // be transitively owned by `this`.
1261
1262 if (segment != nullptr) euthanize();
1263 segment = other.segment;
1264 capTable = other.capTable;
1265 location = other.location;
1266 memcpy(&tag, &other.tag, sizeof(tag)); // Needs memcpy to comply with aliasing rules.
1267 other.segment = nullptr;
1268 other.location = nullptr;
1269 return *this;
1270}
1271
1272} // namespace _ (private)
1273} // namespace capnp
1274