capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

common.h (27881B)


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