1// Copyright (c) 2013-2014 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 contains types which are intended to help detect incorrect usage at compile
23// time, but should then be optimized down to basic primitives (usually, integers) by the
24// compiler.
25
26#pragma once
27
28#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
29#pragma GCC system_header
30#endif
31
32#include <inttypes.h>
33#include <kj/string.h>
34#include <kj/memory.h>
35#include <kj/windows-sanity.h> // work-around macro conflict with `VOID`
36
37#if CAPNP_DEBUG_TYPES
38#include <kj/units.h>
39#endif
40
41namespace capnp {
42
43#define CAPNP_VERSION_MAJOR 0
44#define CAPNP_VERSION_MINOR 8
45#define CAPNP_VERSION_MICRO 0
46
47#define CAPNP_VERSION \
48 (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO)
49
50#ifndef CAPNP_LITE
51#define CAPNP_LITE 0
52#endif
53
54#if CAPNP_TESTING_CAPNP // defined in Cap'n Proto's own unit tests; others should not define this
55#define CAPNP_DEPRECATED(reason)
56#else
57#define CAPNP_DEPRECATED KJ_DEPRECATED
58#endif
59
60typedef unsigned int uint;
61
62struct Void {
63 // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves
64 // differently from other types.
65
66 inline constexpr bool operator==(Void other) const { return true; }
67 inline constexpr bool operator!=(Void other) const { return false; }
68};
69
70static constexpr Void VOID = Void();
71// Constant value for `Void`, which is an empty struct.
72
73inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; }
74
75struct Text;
76struct Data;
77
78enum class Kind: uint8_t {
79 PRIMITIVE,
80 BLOB,
81 ENUM,
82 STRUCT,
83 UNION,
84 INTERFACE,
85 LIST,
86
87 OTHER
88 // Some other type which is often a type parameter to Cap'n Proto templates, but which needs
89 // special handling. This includes types like AnyPointer, Dynamic*, etc.
90};
91
92enum class Style: uint8_t {
93 PRIMITIVE,
94 POINTER, // other than struct
95 STRUCT,
96 CAPABILITY
97};
98
99enum class ElementSize: uint8_t {
100 // Size of a list element.
101
102 VOID = 0,
103 BIT = 1,
104 BYTE = 2,
105 TWO_BYTES = 3,
106 FOUR_BYTES = 4,
107 EIGHT_BYTES = 5,
108
109 POINTER = 6,
110
111 INLINE_COMPOSITE = 7
112};
113
114enum class PointerType {
115 // Various wire types a pointer field can take
116
117 NULL_,
118 // Should be NULL, but that's #defined in stddef.h
119
120 STRUCT,
121 LIST,
122 CAPABILITY
123};
124
125namespace schemas {
126
127template <typename T>
128struct EnumInfo;
129
130} // namespace schemas
131
132namespace _ { // private
133
134template <typename T, typename = void> struct Kind_;
135
136template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; };
137template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; };
138template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
139template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
140template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
141template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
142template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
143template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
144template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
145template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; };
146template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; };
147template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; };
148template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; };
149template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; };
150
151template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> {
152 static constexpr Kind kind = Kind::STRUCT;
153};
154template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> {
155 static constexpr Kind kind = Kind::INTERFACE;
156};
157template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> {
158 static constexpr Kind kind = Kind::ENUM;
159};
160
161} // namespace _ (private)
162
163template <typename T, Kind k = _::Kind_<T>::kind>
164inline constexpr Kind kind() {
165 // This overload of kind() matches types which have a Kind_ specialization.
166
167 return k;
168}
169
170#if _MSC_VER
171
172#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind
173// Avoid constexpr methods in MSVC (it remains buggy in many situations).
174
175#else // _MSC_VER
176
177#define CAPNP_KIND(T) ::capnp::kind<T>()
178// Use this macro rather than kind<T>() in any code which must work in MSVC.
179
180#endif // _MSC_VER, else
181
182#if !CAPNP_LITE
183
184template <typename T, Kind k = kind<T>()>
185inline constexpr Style style() {
186 return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE
187 : k == Kind::STRUCT ? Style::STRUCT
188 : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER;
189}
190
191#endif // !CAPNP_LITE
192
193template <typename T, Kind k = CAPNP_KIND(T)>
194struct List;
195
196#if _MSC_VER
197
198template <typename T, Kind k>
199struct List {};
200// For some reason, without this declaration, MSVC will error out on some uses of List
201// claiming that "T" -- as used in the default initializer for the second template param, "k" --
202// is not defined. I do not understand this error, but adding this empty default declaration fixes
203// it.
204
205#endif
206
207template <typename T> struct ListElementType_;
208template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
209template <typename T> using ListElementType = typename ListElementType_<T>::Type;
210
211namespace _ { // private
212template <typename T, Kind k> struct Kind_<List<T, k>> {
213 static constexpr Kind kind = Kind::LIST;
214};
215} // namespace _ (private)
216
217template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; };
218template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
219template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; };
220template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
221template <typename T> using ReaderFor = typename ReaderFor_<T>::Type;
222// The type returned by List<T>::Reader::operator[].
223
224template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; };
225template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
226template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; };
227template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
228template <typename T> using BuilderFor = typename BuilderFor_<T>::Type;
229// The type returned by List<T>::Builder::operator[].
230
231template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;};
232template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
233template <typename T> using PipelineFor = typename PipelineFor_<T>::Type;
234
235template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_;
236template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; };
237
238template <typename T>
239using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type;
240
241template <typename T>
242using FromReader = typename kj::Decay<T>::Reads;
243// FromReader<MyType::Reader> = MyType (for any Cap'n Proto type).
244
245template <typename T>
246using FromBuilder = typename kj::Decay<T>::Builds;
247// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type).
248
249template <typename T>
250using FromPipeline = typename kj::Decay<T>::Pipelines;
251// FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type).
252
253template <typename T>
254using FromClient = typename kj::Decay<T>::Calls;
255// FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type).
256
257template <typename T>
258using FromServer = typename kj::Decay<T>::Serves;
259// FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type).
260
261template <typename T, typename = void>
262struct FromAny_;
263
264template <typename T>
265struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> {
266 using Type = FromReader<T>;
267};
268
269template <typename T>
270struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> {
271 using Type = FromBuilder<T>;
272};
273
274template <typename T>
275struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> {
276 using Type = FromPipeline<T>;
277};
278
279// Note that T::Client is covered by FromReader
280
281template <typename T>
282struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> {
283 using Type = FromServer<T>;
284};
285
286template <typename T>
287struct FromAny_<T,
288 kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> {
289 // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC
290 // cannot yet use style<T>() in this constexpr context.
291
292 using Type = kj::Decay<T>;
293};
294
295template <typename T>
296using FromAny = typename FromAny_<T>::Type;
297// Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is:
298//
299// Foo::Reader -> Foo
300// Foo::Builder -> Foo
301// Foo::Pipeline -> Foo
302// Foo::Client -> Foo
303// Own<Foo::Server> -> Foo
304// uint32_t -> uint32_t
305
306namespace _ { // private
307
308template <typename T, Kind k = CAPNP_KIND(T)>
309struct PointerHelpers;
310
311#if _MSC_VER
312
313template <typename T, Kind k>
314struct PointerHelpers {};
315// For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers
316// claiming that "T" -- as used in the default initializer for the second template param, "k" --
317// is not defined. I do not understand this error, but adding this empty default declaration fixes
318// it.
319
320#endif
321
322} // namespace _ (private)
323
324struct MessageSize {
325 // Size of a message. Every struct and list type has a method `.totalSize()` that returns this.
326 uint64_t wordCount;
327 uint capCount;
328
329 inline constexpr MessageSize operator+(const MessageSize& other) const {
330 return { wordCount + other.wordCount, capCount + other.capCount };
331 }
332};
333
334// =======================================================================================
335// Raw memory types and measures
336
337using kj::byte;
338
339class word {
340 // word is an opaque type with size of 64 bits. This type is useful only to make pointer
341 // arithmetic clearer. Since the contents are private, the only way to access them is to first
342 // reinterpret_cast to some other pointer type.
343 //
344 // Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of
345 // aliasing rules.
346 //
347 // A pointer of type word* should always be word-aligned even if won't actually be dereferenced
348 // as that type.
349public:
350 word() = default;
351private:
352 uint64_t content KJ_UNUSED_MEMBER;
353#if __GNUC__ < 8 || __clang__
354 // GCC 8's -Wclass-memaccess complains whenever we try to memcpy() a `word` if we've disallowed
355 // the copy constructor. We don't want to disable the warning becaues it's a useful warning and
356 // we'd have to disable it for all applications that include this header. Instead we allow `word`
357 // to be copyable on GCC.
358 KJ_DISALLOW_COPY(word);
359#endif
360};
361
362static_assert(sizeof(byte) == 1, "uint8_t is not one byte?");
363static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?");
364
365#if CAPNP_DEBUG_TYPES
366// Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are
367// used. All the code should still operate exactly the same, we just lose compile-time checking.
368// Note that this will also change symbol names, so it's important that the library and any clients
369// be compiled with the same setting here.
370//
371// We disable this by default to reduce symbol name size and avoid any possibility of the compiler
372// failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this
373// during development and testing.
374
375namespace _ { class BitLabel; class ElementLabel; struct WirePointer; }
376
377template <uint width, typename T = uint>
378using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>;
379template <uint width, typename T = uint>
380using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>;
381template <uint width, typename T = uint>
382using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>;
383template <uint width, typename T = uint>
384using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>;
385template <uint width, typename T = uint>
386using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>;
387
388typedef BitCountN<8, uint8_t> BitCount8;
389typedef BitCountN<16, uint16_t> BitCount16;
390typedef BitCountN<32, uint32_t> BitCount32;
391typedef BitCountN<64, uint64_t> BitCount64;
392typedef BitCountN<sizeof(uint) * 8, uint> BitCount;
393
394typedef ByteCountN<8, uint8_t> ByteCount8;
395typedef ByteCountN<16, uint16_t> ByteCount16;
396typedef ByteCountN<32, uint32_t> ByteCount32;
397typedef ByteCountN<64, uint64_t> ByteCount64;
398typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;
399
400typedef WordCountN<8, uint8_t> WordCount8;
401typedef WordCountN<16, uint16_t> WordCount16;
402typedef WordCountN<32, uint32_t> WordCount32;
403typedef WordCountN<64, uint64_t> WordCount64;
404typedef WordCountN<sizeof(uint) * 8, uint> WordCount;
405
406typedef ElementCountN<8, uint8_t> ElementCount8;
407typedef ElementCountN<16, uint16_t> ElementCount16;
408typedef ElementCountN<32, uint32_t> ElementCount32;
409typedef ElementCountN<64, uint64_t> ElementCount64;
410typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;
411
412typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
413typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
414typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
415typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
416typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;
417
418template <uint width>
419using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
420template <uint width>
421using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
422template <uint width>
423using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
424template <uint width>
425using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());
426
427using kj::bounded;
428using kj::unbound;
429using kj::unboundAs;
430using kj::unboundMax;
431using kj::unboundMaxBits;
432using kj::assertMax;
433using kj::assertMaxBits;
434using kj::upgradeBound;
435using kj::ThrowOverflow;
436using kj::assumeBits;
437using kj::assumeMax;
438using kj::subtractChecked;
439using kj::trySubtract;
440
441template <typename T, typename U>
442inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) {
443 return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
444}
445template <typename T, typename U>
446inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) {
447 return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
448}
449template <typename T, typename U>
450inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) {
451 return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
452}
453template <typename T, typename U>
454inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) {
455 return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
456}
457
458template <typename T, typename U>
459inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) {
460 return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
461}
462template <typename T, typename U>
463inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) {
464 return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
465}
466template <typename T, typename U>
467inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) {
468 return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
469}
470template <typename T, typename U>
471inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) {
472 return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
473}
474
475constexpr auto BITS = kj::unit<BitCountN<1>>();
476constexpr auto BYTES = kj::unit<ByteCountN<1>>();
477constexpr auto WORDS = kj::unit<WordCountN<1>>();
478constexpr auto ELEMENTS = kj::unit<ElementCountN<1>>();
479constexpr auto POINTERS = kj::unit<WirePointerCountN<1>>();
480
481constexpr auto ZERO = kj::bounded<0>();
482constexpr auto ONE = kj::bounded<1>();
483
484// GCC 4.7 actually gives unused warnings on these constants in opt mode...
485constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES;
486constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS;
487constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS;
488
489constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS;
490constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS;
491constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS;
492
493constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;
494
495constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment.
496constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list.
497constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section.
498constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section.
499constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob.
500
501typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
502typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
503typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
504typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
505typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;
506
507constexpr auto MAX_SEGMENT_WORDS =
508 bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS;
509constexpr auto MAX_LIST_ELEMENTS =
510 bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS;
511constexpr auto MAX_STUCT_DATA_WORDS =
512 bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS;
513constexpr auto MAX_STRUCT_POINTER_COUNT =
514 bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS;
515
516using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD);
517// Number of bits in a Struct data segment (should come out to BitCountN<22>).
518
519using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS));
520using StructPointerOffset = StructPointerCount;
521// Type of a field offset.
522
523inline StructDataOffset assumeDataOffset(uint32_t offset) {
524 return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS),
525 bounded(offset) * ELEMENTS);
526}
527
528inline StructPointerOffset assumePointerOffset(uint32_t offset) {
529 return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS);
530}
531
532constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
533typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize;
534// Not including NUL terminator.
535
536template <typename T>
537inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() {
538 return bounded<sizeof(T)>() * BYTES / ELEMENTS;
539}
540
541template <typename T>
542inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() {
543 return bounded<sizeof(T) * 8>() * BITS / ELEMENTS;
544}
545
546template <typename T, uint maxN>
547inline constexpr kj::Quantity<kj::Bounded<maxN, size_t>, T>
548intervalLength(const T* a, const T* b, kj::Quantity<kj::BoundedConst<maxN>, T>) {
549 return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::BoundedConst<1u>, T>>();
550}
551
552template <typename T, typename U>
553inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) {
554 return kj::ArrayPtr<const U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
555}
556template <typename T, typename U>
557inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) {
558 return kj::ArrayPtr<U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>()));
559}
560
561#else
562
563template <uint width, typename T = uint>
564using BitCountN = T;
565template <uint width, typename T = uint>
566using ByteCountN = T;
567template <uint width, typename T = uint>
568using WordCountN = T;
569template <uint width, typename T = uint>
570using ElementCountN = T;
571template <uint width, typename T = uint>
572using WirePointerCountN = T;
573
574
575// XXX
576typedef BitCountN<8, uint8_t> BitCount8;
577typedef BitCountN<16, uint16_t> BitCount16;
578typedef BitCountN<32, uint32_t> BitCount32;
579typedef BitCountN<64, uint64_t> BitCount64;
580typedef BitCountN<sizeof(uint) * 8, uint> BitCount;
581
582typedef ByteCountN<8, uint8_t> ByteCount8;
583typedef ByteCountN<16, uint16_t> ByteCount16;
584typedef ByteCountN<32, uint32_t> ByteCount32;
585typedef ByteCountN<64, uint64_t> ByteCount64;
586typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount;
587
588typedef WordCountN<8, uint8_t> WordCount8;
589typedef WordCountN<16, uint16_t> WordCount16;
590typedef WordCountN<32, uint32_t> WordCount32;
591typedef WordCountN<64, uint64_t> WordCount64;
592typedef WordCountN<sizeof(uint) * 8, uint> WordCount;
593
594typedef ElementCountN<8, uint8_t> ElementCount8;
595typedef ElementCountN<16, uint16_t> ElementCount16;
596typedef ElementCountN<32, uint32_t> ElementCount32;
597typedef ElementCountN<64, uint64_t> ElementCount64;
598typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount;
599
600typedef WirePointerCountN<8, uint8_t> WirePointerCount8;
601typedef WirePointerCountN<16, uint16_t> WirePointerCount16;
602typedef WirePointerCountN<32, uint32_t> WirePointerCount32;
603typedef WirePointerCountN<64, uint64_t> WirePointerCount64;
604typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount;
605
606template <uint width>
607using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>());
608template <uint width>
609using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>());
610template <uint width>
611using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>());
612template <uint width>
613using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>());
614
615using kj::ThrowOverflow;
616// YYY
617
618template <uint i> inline constexpr uint bounded() { return i; }
619template <typename T> inline constexpr T bounded(T i) { return i; }
620template <typename T> inline constexpr T unbound(T i) { return i; }
621
622template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; }
623
624template <uint64_t requestedMax, typename T> inline constexpr uint unboundMax(T i) { return i; }
625template <uint bits, typename T> inline constexpr uint unboundMaxBits(T i) { return i; }
626
627template <uint newMax, typename T, typename ErrorFunc>
628inline T assertMax(T value, ErrorFunc&& func) {
629 if (KJ_UNLIKELY(value > newMax)) func();
630 return value;
631}
632
633template <typename T, typename ErrorFunc>
634inline T assertMax(uint newMax, T value, ErrorFunc&& func) {
635 if (KJ_UNLIKELY(value > newMax)) func();
636 return value;
637}
638
639template <uint bits, typename T, typename ErrorFunc = ThrowOverflow>
640inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) {
641 if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func();
642 return value;
643}
644
645template <typename T, typename ErrorFunc = ThrowOverflow>
646inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) {
647 if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func();
648 return value;
649}
650
651template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; }
652
653template <uint bits, typename T> inline constexpr T assumeBits(T i) { return i; }
654template <uint64_t max, typename T> inline constexpr T assumeMax(T i) { return i; }
655
656template <typename T, typename U, typename ErrorFunc = ThrowOverflow>
657inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc())
658 -> decltype(a - b) {
659 if (b > a) errorFunc();
660 return a - b;
661}
662
663template <typename T, typename U>
664inline auto trySubtract(T a, U b) -> kj::Maybe<decltype(a - b)> {
665 if (b > a) {
666 return nullptr;
667 } else {
668 return a - b;
669 }
670}
671
672constexpr uint BITS = 1;
673constexpr uint BYTES = 1;
674constexpr uint WORDS = 1;
675constexpr uint ELEMENTS = 1;
676constexpr uint POINTERS = 1;
677
678constexpr uint ZERO = 0;
679constexpr uint ONE = 1;
680
681// GCC 4.7 actually gives unused warnings on these constants in opt mode...
682constexpr uint BITS_PER_BYTE KJ_UNUSED = 8;
683constexpr uint BITS_PER_WORD KJ_UNUSED = 64;
684constexpr uint BYTES_PER_WORD KJ_UNUSED = 8;
685
686constexpr uint BITS_PER_POINTER KJ_UNUSED = 64;
687constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8;
688constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1;
689
690// XXX
691constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER;
692
693constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment.
694constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list.
695constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section.
696constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section.
697constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob.
698
699typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount;
700typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount;
701typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount;
702typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount;
703typedef ByteCountN<BLOB_SIZE_BITS> BlobSize;
704// YYY
705
706constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>();
707constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>();
708constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>();
709constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>();
710
711typedef uint StructDataBitCount;
712typedef uint StructDataOffset;
713typedef uint StructPointerOffset;
714
715inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; }
716inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; }
717
718constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
719typedef uint TextSize;
720
721template <typename T>
722inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); }
723
724template <typename T>
725inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; }
726
727template <typename T>
728inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) {
729 return b - a;
730}
731
732template <typename T, typename U>
733inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, T size) {
734 return kj::arrayPtr(ptr, size);
735}
736template <typename T, typename U>
737inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, T size) {
738 return kj::arrayPtr(ptr, size);
739}
740
741#endif
742
743} // namespace capnp
744