comparison osx/include/capnp/layout.h @ 49:3ab5a40c4e3b

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