Mercurial > hg > sv-dependency-builds
diff osx/include/capnp/common.h @ 62:0994c39f1e94
Cap'n Proto v0.6 + build for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Mon, 22 May 2017 10:01:37 +0100 |
parents | 3ab5a40c4e3b |
children |
line wrap: on
line diff
--- a/osx/include/capnp/common.h Mon Mar 06 13:29:58 2017 +0000 +++ b/osx/include/capnp/common.h Mon May 22 10:01:37 2017 +0100 @@ -1,487 +1,719 @@ -// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors -// Licensed under the MIT License: -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// This file contains types which are intended to help detect incorrect usage at compile -// time, but should then be optimized down to basic primitives (usually, integers) by the -// compiler. - -#ifndef CAPNP_COMMON_H_ -#define CAPNP_COMMON_H_ - -#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) -#pragma GCC system_header -#endif - -#include <kj/units.h> -#include <inttypes.h> -#include <kj/string.h> -#include <kj/memory.h> - -namespace capnp { - -#define CAPNP_VERSION_MAJOR 0 -#define CAPNP_VERSION_MINOR 6 -#define CAPNP_VERSION_MICRO 0 - -#define CAPNP_VERSION \ - (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO) - -#ifdef _MSC_VER -#define CAPNP_LITE 1 -// MSVC only supports "lite" mode for now, due to missing C++11 features. -#endif - -#ifndef CAPNP_LITE -#define CAPNP_LITE 0 -#endif - -typedef unsigned int uint; - -struct Void { - // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves - // differently from other types. - - inline constexpr bool operator==(Void other) const { return true; } - inline constexpr bool operator!=(Void other) const { return false; } -}; - -static constexpr Void VOID = Void(); -// Constant value for `Void`, which is an empty struct. - -inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; } - -struct Text; -struct Data; - -enum class Kind: uint8_t { - PRIMITIVE, - BLOB, - ENUM, - STRUCT, - UNION, - INTERFACE, - LIST, - - OTHER - // Some other type which is often a type parameter to Cap'n Proto templates, but which needs - // special handling. This includes types like AnyPointer, Dynamic*, etc. -}; - -enum class Style: uint8_t { - PRIMITIVE, - POINTER, // other than struct - STRUCT, - CAPABILITY -}; - -enum class ElementSize: uint8_t { - // Size of a list element. - - VOID = 0, - BIT = 1, - BYTE = 2, - TWO_BYTES = 3, - FOUR_BYTES = 4, - EIGHT_BYTES = 5, - - POINTER = 6, - - INLINE_COMPOSITE = 7 -}; - -enum class PointerType { - // Various wire types a pointer field can take - - NULL_, - // Should be NULL, but that's #defined in stddef.h - - STRUCT, - LIST, - CAPABILITY -}; - -namespace schemas { - -template <typename T> -struct EnumInfo; - -} // namespace schemas - -namespace _ { // private - -template <typename T, typename = void> struct Kind_; - -template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; }; -template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; }; -template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; }; - -template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> { - static constexpr Kind kind = Kind::STRUCT; -}; -template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> { - static constexpr Kind kind = Kind::INTERFACE; -}; -template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> { - static constexpr Kind kind = Kind::ENUM; -}; - -} // namespace _ (private) - -template <typename T, Kind k = _::Kind_<T>::kind> -inline constexpr Kind kind() { - // This overload of kind() matches types which have a Kind_ specialization. - - return k; -} - -#if CAPNP_LITE - -#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind -// Avoid constexpr methods in lite mode (MSVC is bad at constexpr). - -#else // CAPNP_LITE - -#define CAPNP_KIND(T) ::capnp::kind<T>() -// Use this macro rather than kind<T>() in any code which must work in lite mode. - -template <typename T, Kind k = kind<T>()> -inline constexpr Style style() { - return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE - : k == Kind::STRUCT ? Style::STRUCT - : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER; -} - -#endif // CAPNP_LITE, else - -template <typename T, Kind k = CAPNP_KIND(T)> -struct List; - -#if _MSC_VER - -template <typename T, Kind k> -struct List {}; -// For some reason, without this declaration, MSVC will error out on some uses of List -// claiming that "T" -- as used in the default initializer for the second template param, "k" -- -// is not defined. I do not understand this error, but adding this empty default declaration fixes -// it. - -#endif - -template <typename T> struct ListElementType_; -template <typename T> struct ListElementType_<List<T>> { typedef T Type; }; -template <typename T> using ListElementType = typename ListElementType_<T>::Type; - -namespace _ { // private -template <typename T, Kind k> struct Kind_<List<T, k>> { - static constexpr Kind kind = Kind::LIST; -}; -} // namespace _ (private) - -template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; }; -template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; -template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; }; -template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; -template <typename T> using ReaderFor = typename ReaderFor_<T>::Type; -// The type returned by List<T>::Reader::operator[]. - -template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; }; -template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; -template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; }; -template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; -template <typename T> using BuilderFor = typename BuilderFor_<T>::Type; -// The type returned by List<T>::Builder::operator[]. - -template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;}; -template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; -template <typename T> using PipelineFor = typename PipelineFor_<T>::Type; - -template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_; -template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; }; - -template <typename T> -using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type; - -template <typename T> -using FromReader = typename kj::Decay<T>::Reads; -// FromReader<MyType::Reader> = MyType (for any Cap'n Proto type). - -template <typename T> -using FromBuilder = typename kj::Decay<T>::Builds; -// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type). - -template <typename T> -using FromPipeline = typename kj::Decay<T>::Pipelines; -// FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type). - -template <typename T> -using FromClient = typename kj::Decay<T>::Calls; -// FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type). - -template <typename T> -using FromServer = typename kj::Decay<T>::Serves; -// FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type). - -template <typename T, typename = void> -struct FromAny_; - -template <typename T> -struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> { - using Type = FromReader<T>; -}; - -template <typename T> -struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> { - using Type = FromBuilder<T>; -}; - -template <typename T> -struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> { - using Type = FromPipeline<T>; -}; - -// Note that T::Client is covered by FromReader - -template <typename T> -struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> { - using Type = FromServer<T>; -}; - -template <typename T> -struct FromAny_<T, - kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> { - // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC - // cannot yet use style<T>() in this constexpr context. - - using Type = kj::Decay<T>; -}; - -template <typename T> -using FromAny = typename FromAny_<T>::Type; -// Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is: -// -// Foo::Reader -> Foo -// Foo::Builder -> Foo -// Foo::Pipeline -> Foo -// Foo::Client -> Foo -// Own<Foo::Server> -> Foo -// uint32_t -> uint32_t - -namespace _ { // private - -template <typename T, Kind k = CAPNP_KIND(T)> -struct PointerHelpers; - -#if _MSC_VER - -template <typename T, Kind k> -struct PointerHelpers {}; -// For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers -// claiming that "T" -- as used in the default initializer for the second template param, "k" -- -// is not defined. I do not understand this error, but adding this empty default declaration fixes -// it. - -#endif - -} // namespace _ (private) - -struct MessageSize { - // Size of a message. Every struct type has a method `.totalSize()` that returns this. - uint64_t wordCount; - uint capCount; -}; - -// ======================================================================================= -// Raw memory types and measures - -using kj::byte; - -class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; }; -// word is an opaque type with size of 64 bits. This type is useful only to make pointer -// arithmetic clearer. Since the contents are private, the only way to access them is to first -// reinterpret_cast to some other pointer type. -// -// Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of -// aliasing rules. -// -// A pointer of type word* should always be word-aligned even if won't actually be dereferenced as -// that type. - -static_assert(sizeof(byte) == 1, "uint8_t is not one byte?"); -static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?"); - -#if CAPNP_DEBUG_TYPES -// Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are -// used. All the code should still operate exactly the same, we just lose compile-time checking. -// Note that this will also change symbol names, so it's important that the library and any clients -// be compiled with the same setting here. -// -// We disable this by default to reduce symbol name size and avoid any possibility of the compiler -// failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this -// during development and testing. - -namespace _ { class BitLabel; class ElementLabel; struct WirePointer; } - -typedef kj::Quantity<uint, _::BitLabel> BitCount; -typedef kj::Quantity<uint8_t, _::BitLabel> BitCount8; -typedef kj::Quantity<uint16_t, _::BitLabel> BitCount16; -typedef kj::Quantity<uint32_t, _::BitLabel> BitCount32; -typedef kj::Quantity<uint64_t, _::BitLabel> BitCount64; - -typedef kj::Quantity<uint, byte> ByteCount; -typedef kj::Quantity<uint8_t, byte> ByteCount8; -typedef kj::Quantity<uint16_t, byte> ByteCount16; -typedef kj::Quantity<uint32_t, byte> ByteCount32; -typedef kj::Quantity<uint64_t, byte> ByteCount64; - -typedef kj::Quantity<uint, word> WordCount; -typedef kj::Quantity<uint8_t, word> WordCount8; -typedef kj::Quantity<uint16_t, word> WordCount16; -typedef kj::Quantity<uint32_t, word> WordCount32; -typedef kj::Quantity<uint64_t, word> WordCount64; - -typedef kj::Quantity<uint, _::ElementLabel> ElementCount; -typedef kj::Quantity<uint8_t, _::ElementLabel> ElementCount8; -typedef kj::Quantity<uint16_t, _::ElementLabel> ElementCount16; -typedef kj::Quantity<uint32_t, _::ElementLabel> ElementCount32; -typedef kj::Quantity<uint64_t, _::ElementLabel> ElementCount64; - -typedef kj::Quantity<uint, _::WirePointer> WirePointerCount; -typedef kj::Quantity<uint8_t, _::WirePointer> WirePointerCount8; -typedef kj::Quantity<uint16_t, _::WirePointer> WirePointerCount16; -typedef kj::Quantity<uint32_t, _::WirePointer> WirePointerCount32; -typedef kj::Quantity<uint64_t, _::WirePointer> WirePointerCount64; - -template <typename T, typename U> -inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) { - return ptr + offset / kj::unit<kj::Quantity<T, U>>(); -} -template <typename T, typename U> -inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) { - return ptr + offset / kj::unit<kj::Quantity<T, U>>(); -} -template <typename T, typename U> -inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) { - return ptr = ptr + offset / kj::unit<kj::Quantity<T, U>>(); -} -template <typename T, typename U> -inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) { - return ptr = ptr + offset / kj::unit<kj::Quantity<T, U>>(); -} - -template <typename T, typename U> -inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) { - return ptr - offset / kj::unit<kj::Quantity<T, U>>(); -} -template <typename T, typename U> -inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) { - return ptr - offset / kj::unit<kj::Quantity<T, U>>(); -} -template <typename T, typename U> -inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) { - return ptr = ptr - offset / kj::unit<kj::Quantity<T, U>>(); -} -template <typename T, typename U> -inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) { - return ptr = ptr - offset / kj::unit<kj::Quantity<T, U>>(); -} - -#else - -typedef uint BitCount; -typedef uint8_t BitCount8; -typedef uint16_t BitCount16; -typedef uint32_t BitCount32; -typedef uint64_t BitCount64; - -typedef uint ByteCount; -typedef uint8_t ByteCount8; -typedef uint16_t ByteCount16; -typedef uint32_t ByteCount32; -typedef uint64_t ByteCount64; - -typedef uint WordCount; -typedef uint8_t WordCount8; -typedef uint16_t WordCount16; -typedef uint32_t WordCount32; -typedef uint64_t WordCount64; - -typedef uint ElementCount; -typedef uint8_t ElementCount8; -typedef uint16_t ElementCount16; -typedef uint32_t ElementCount32; -typedef uint64_t ElementCount64; - -typedef uint WirePointerCount; -typedef uint8_t WirePointerCount8; -typedef uint16_t WirePointerCount16; -typedef uint32_t WirePointerCount32; -typedef uint64_t WirePointerCount64; - -#endif - -constexpr BitCount BITS = kj::unit<BitCount>(); -constexpr ByteCount BYTES = kj::unit<ByteCount>(); -constexpr WordCount WORDS = kj::unit<WordCount>(); -constexpr ElementCount ELEMENTS = kj::unit<ElementCount>(); -constexpr WirePointerCount POINTERS = kj::unit<WirePointerCount>(); - -// GCC 4.7 actually gives unused warnings on these constants in opt mode... -constexpr auto BITS_PER_BYTE KJ_UNUSED = 8 * BITS / BYTES; -constexpr auto BITS_PER_WORD KJ_UNUSED = 64 * BITS / WORDS; -constexpr auto BYTES_PER_WORD KJ_UNUSED = 8 * BYTES / WORDS; - -constexpr auto BITS_PER_POINTER KJ_UNUSED = 64 * BITS / POINTERS; -constexpr auto BYTES_PER_POINTER KJ_UNUSED = 8 * BYTES / POINTERS; -constexpr auto WORDS_PER_POINTER KJ_UNUSED = 1 * WORDS / POINTERS; - -constexpr WordCount POINTER_SIZE_IN_WORDS = 1 * POINTERS * WORDS_PER_POINTER; - -template <typename T> -inline KJ_CONSTEXPR() decltype(BYTES / ELEMENTS) bytesPerElement() { - return sizeof(T) * BYTES / ELEMENTS; -} - -template <typename T> -inline KJ_CONSTEXPR() decltype(BITS / ELEMENTS) bitsPerElement() { - return sizeof(T) * 8 * BITS / ELEMENTS; -} - -inline constexpr ByteCount intervalLength(const byte* a, const byte* b) { - return uint(b - a) * BYTES; -} -inline constexpr WordCount intervalLength(const word* a, const word* b) { - return uint(b - a) * WORDS; -} - -} // namespace capnp - -#endif // CAPNP_COMMON_H_ +// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors +// Licensed under the MIT License: +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// This file contains types which are intended to help detect incorrect usage at compile +// time, but should then be optimized down to basic primitives (usually, integers) by the +// compiler. + +#ifndef CAPNP_COMMON_H_ +#define CAPNP_COMMON_H_ + +#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS) +#pragma GCC system_header +#endif + +#include <inttypes.h> +#include <kj/string.h> +#include <kj/memory.h> + +#if CAPNP_DEBUG_TYPES +#include <kj/units.h> +#endif + +namespace capnp { + +#define CAPNP_VERSION_MAJOR 0 +#define CAPNP_VERSION_MINOR 6 +#define CAPNP_VERSION_MICRO 0 + +#define CAPNP_VERSION \ + (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO) + +#ifndef CAPNP_LITE +#define CAPNP_LITE 0 +#endif + +typedef unsigned int uint; + +struct Void { + // Type used for Void fields. Using C++'s "void" type creates a bunch of issues since it behaves + // differently from other types. + + inline constexpr bool operator==(Void other) const { return true; } + inline constexpr bool operator!=(Void other) const { return false; } +}; + +static constexpr Void VOID = Void(); +// Constant value for `Void`, which is an empty struct. + +inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; } + +struct Text; +struct Data; + +enum class Kind: uint8_t { + PRIMITIVE, + BLOB, + ENUM, + STRUCT, + UNION, + INTERFACE, + LIST, + + OTHER + // Some other type which is often a type parameter to Cap'n Proto templates, but which needs + // special handling. This includes types like AnyPointer, Dynamic*, etc. +}; + +enum class Style: uint8_t { + PRIMITIVE, + POINTER, // other than struct + STRUCT, + CAPABILITY +}; + +enum class ElementSize: uint8_t { + // Size of a list element. + + VOID = 0, + BIT = 1, + BYTE = 2, + TWO_BYTES = 3, + FOUR_BYTES = 4, + EIGHT_BYTES = 5, + + POINTER = 6, + + INLINE_COMPOSITE = 7 +}; + +enum class PointerType { + // Various wire types a pointer field can take + + NULL_, + // Should be NULL, but that's #defined in stddef.h + + STRUCT, + LIST, + CAPABILITY +}; + +namespace schemas { + +template <typename T> +struct EnumInfo; + +} // namespace schemas + +namespace _ { // private + +template <typename T, typename = void> struct Kind_; + +template <> struct Kind_<Void> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<bool> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<int8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<int16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<int32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<int64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<uint8_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<uint16_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<uint32_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<uint64_t> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<float> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<double> { static constexpr Kind kind = Kind::PRIMITIVE; }; +template <> struct Kind_<Text> { static constexpr Kind kind = Kind::BLOB; }; +template <> struct Kind_<Data> { static constexpr Kind kind = Kind::BLOB; }; + +template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsStruct>> { + static constexpr Kind kind = Kind::STRUCT; +}; +template <typename T> struct Kind_<T, kj::VoidSfinae<typename T::_capnpPrivate::IsInterface>> { + static constexpr Kind kind = Kind::INTERFACE; +}; +template <typename T> struct Kind_<T, kj::VoidSfinae<typename schemas::EnumInfo<T>::IsEnum>> { + static constexpr Kind kind = Kind::ENUM; +}; + +} // namespace _ (private) + +template <typename T, Kind k = _::Kind_<T>::kind> +inline constexpr Kind kind() { + // This overload of kind() matches types which have a Kind_ specialization. + + return k; +} + +#if CAPNP_LITE + +#define CAPNP_KIND(T) ::capnp::_::Kind_<T>::kind +// Avoid constexpr methods in lite mode (MSVC is bad at constexpr). + +#else // CAPNP_LITE + +#define CAPNP_KIND(T) ::capnp::kind<T>() +// Use this macro rather than kind<T>() in any code which must work in lite mode. + +template <typename T, Kind k = kind<T>()> +inline constexpr Style style() { + return k == Kind::PRIMITIVE || k == Kind::ENUM ? Style::PRIMITIVE + : k == Kind::STRUCT ? Style::STRUCT + : k == Kind::INTERFACE ? Style::CAPABILITY : Style::POINTER; +} + +#endif // CAPNP_LITE, else + +template <typename T, Kind k = CAPNP_KIND(T)> +struct List; + +#if _MSC_VER + +template <typename T, Kind k> +struct List {}; +// For some reason, without this declaration, MSVC will error out on some uses of List +// claiming that "T" -- as used in the default initializer for the second template param, "k" -- +// is not defined. I do not understand this error, but adding this empty default declaration fixes +// it. + +#endif + +template <typename T> struct ListElementType_; +template <typename T> struct ListElementType_<List<T>> { typedef T Type; }; +template <typename T> using ListElementType = typename ListElementType_<T>::Type; + +namespace _ { // private +template <typename T, Kind k> struct Kind_<List<T, k>> { + static constexpr Kind kind = Kind::LIST; +}; +} // namespace _ (private) + +template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; }; +template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; +template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; }; +template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; +template <typename T> using ReaderFor = typename ReaderFor_<T>::Type; +// The type returned by List<T>::Reader::operator[]. + +template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; }; +template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; }; +template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; }; +template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; +template <typename T> using BuilderFor = typename BuilderFor_<T>::Type; +// The type returned by List<T>::Builder::operator[]. + +template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;}; +template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; }; +template <typename T> using PipelineFor = typename PipelineFor_<T>::Type; + +template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_; +template <typename T> struct TypeIfEnum_<T, Kind::ENUM> { typedef T Type; }; + +template <typename T> +using TypeIfEnum = typename TypeIfEnum_<kj::Decay<T>>::Type; + +template <typename T> +using FromReader = typename kj::Decay<T>::Reads; +// FromReader<MyType::Reader> = MyType (for any Cap'n Proto type). + +template <typename T> +using FromBuilder = typename kj::Decay<T>::Builds; +// FromBuilder<MyType::Builder> = MyType (for any Cap'n Proto type). + +template <typename T> +using FromPipeline = typename kj::Decay<T>::Pipelines; +// FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type). + +template <typename T> +using FromClient = typename kj::Decay<T>::Calls; +// FromReader<MyType::Client> = MyType (for any Cap'n Proto interface type). + +template <typename T> +using FromServer = typename kj::Decay<T>::Serves; +// FromBuilder<MyType::Server> = MyType (for any Cap'n Proto interface type). + +template <typename T, typename = void> +struct FromAny_; + +template <typename T> +struct FromAny_<T, kj::VoidSfinae<FromReader<T>>> { + using Type = FromReader<T>; +}; + +template <typename T> +struct FromAny_<T, kj::VoidSfinae<FromBuilder<T>>> { + using Type = FromBuilder<T>; +}; + +template <typename T> +struct FromAny_<T, kj::VoidSfinae<FromPipeline<T>>> { + using Type = FromPipeline<T>; +}; + +// Note that T::Client is covered by FromReader + +template <typename T> +struct FromAny_<kj::Own<T>, kj::VoidSfinae<FromServer<T>>> { + using Type = FromServer<T>; +}; + +template <typename T> +struct FromAny_<T, + kj::EnableIf<_::Kind_<T>::kind == Kind::PRIMITIVE || _::Kind_<T>::kind == Kind::ENUM>> { + // TODO(msvc): Ideally the EnableIf condition would be `style<T>() == Style::PRIMITIVE`, but MSVC + // cannot yet use style<T>() in this constexpr context. + + using Type = kj::Decay<T>; +}; + +template <typename T> +using FromAny = typename FromAny_<T>::Type; +// Given any Cap'n Proto value type as an input, return the Cap'n Proto base type. That is: +// +// Foo::Reader -> Foo +// Foo::Builder -> Foo +// Foo::Pipeline -> Foo +// Foo::Client -> Foo +// Own<Foo::Server> -> Foo +// uint32_t -> uint32_t + +namespace _ { // private + +template <typename T, Kind k = CAPNP_KIND(T)> +struct PointerHelpers; + +#if _MSC_VER + +template <typename T, Kind k> +struct PointerHelpers {}; +// For some reason, without this declaration, MSVC will error out on some uses of PointerHelpers +// claiming that "T" -- as used in the default initializer for the second template param, "k" -- +// is not defined. I do not understand this error, but adding this empty default declaration fixes +// it. + +#endif + +} // namespace _ (private) + +struct MessageSize { + // Size of a message. Every struct type has a method `.totalSize()` that returns this. + uint64_t wordCount; + uint capCount; +}; + +// ======================================================================================= +// Raw memory types and measures + +using kj::byte; + +class word { uint64_t content KJ_UNUSED_MEMBER; KJ_DISALLOW_COPY(word); public: word() = default; }; +// word is an opaque type with size of 64 bits. This type is useful only to make pointer +// arithmetic clearer. Since the contents are private, the only way to access them is to first +// reinterpret_cast to some other pointer type. +// +// Copying is disallowed because you should always use memcpy(). Otherwise, you may run afoul of +// aliasing rules. +// +// A pointer of type word* should always be word-aligned even if won't actually be dereferenced as +// that type. + +static_assert(sizeof(byte) == 1, "uint8_t is not one byte?"); +static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?"); + +#if CAPNP_DEBUG_TYPES +// Set CAPNP_DEBUG_TYPES to 1 to use kj::Quantity for "count" types. Otherwise, plain integers are +// used. All the code should still operate exactly the same, we just lose compile-time checking. +// Note that this will also change symbol names, so it's important that the library and any clients +// be compiled with the same setting here. +// +// We disable this by default to reduce symbol name size and avoid any possibility of the compiler +// failing to fully-optimize the types, but anyone modifying Cap'n Proto itself should enable this +// during development and testing. + +namespace _ { class BitLabel; class ElementLabel; struct WirePointer; } + +template <uint width, typename T = uint> +using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>; +template <uint width, typename T = uint> +using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>; +template <uint width, typename T = uint> +using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>; +template <uint width, typename T = uint> +using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>; +template <uint width, typename T = uint> +using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>; + +typedef BitCountN<8, uint8_t> BitCount8; +typedef BitCountN<16, uint16_t> BitCount16; +typedef BitCountN<32, uint32_t> BitCount32; +typedef BitCountN<64, uint64_t> BitCount64; +typedef BitCountN<sizeof(uint) * 8, uint> BitCount; + +typedef ByteCountN<8, uint8_t> ByteCount8; +typedef ByteCountN<16, uint16_t> ByteCount16; +typedef ByteCountN<32, uint32_t> ByteCount32; +typedef ByteCountN<64, uint64_t> ByteCount64; +typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount; + +typedef WordCountN<8, uint8_t> WordCount8; +typedef WordCountN<16, uint16_t> WordCount16; +typedef WordCountN<32, uint32_t> WordCount32; +typedef WordCountN<64, uint64_t> WordCount64; +typedef WordCountN<sizeof(uint) * 8, uint> WordCount; + +typedef ElementCountN<8, uint8_t> ElementCount8; +typedef ElementCountN<16, uint16_t> ElementCount16; +typedef ElementCountN<32, uint32_t> ElementCount32; +typedef ElementCountN<64, uint64_t> ElementCount64; +typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount; + +typedef WirePointerCountN<8, uint8_t> WirePointerCount8; +typedef WirePointerCountN<16, uint16_t> WirePointerCount16; +typedef WirePointerCountN<32, uint32_t> WirePointerCount32; +typedef WirePointerCountN<64, uint64_t> WirePointerCount64; +typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount; + +template <uint width> +using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>()); +template <uint width> +using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>()); +template <uint width> +using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>()); +template <uint width> +using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>()); + +using kj::bounded; +using kj::unbound; +using kj::unboundAs; +using kj::unboundMax; +using kj::unboundMaxBits; +using kj::assertMax; +using kj::assertMaxBits; +using kj::upgradeBound; +using kj::ThrowOverflow; +using kj::assumeBits; +using kj::assumeMax; +using kj::subtractChecked; +using kj::trySubtract; + +template <typename T, typename U> +inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) { + return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} +template <typename T, typename U> +inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) { + return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} +template <typename T, typename U> +inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) { + return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} +template <typename T, typename U> +inline constexpr const U* operator+=(const U*& ptr, kj::Quantity<T, U> offset) { + return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} + +template <typename T, typename U> +inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) { + return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} +template <typename T, typename U> +inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) { + return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} +template <typename T, typename U> +inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) { + return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} +template <typename T, typename U> +inline constexpr const U* operator-=(const U*& ptr, kj::Quantity<T, U> offset) { + return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>()); +} + +constexpr auto BITS = kj::unit<BitCountN<1>>(); +constexpr auto BYTES = kj::unit<ByteCountN<1>>(); +constexpr auto WORDS = kj::unit<WordCountN<1>>(); +constexpr auto ELEMENTS = kj::unit<ElementCountN<1>>(); +constexpr auto POINTERS = kj::unit<WirePointerCountN<1>>(); + +constexpr auto ZERO = kj::bounded<0>(); +constexpr auto ONE = kj::bounded<1>(); + +// GCC 4.7 actually gives unused warnings on these constants in opt mode... +constexpr auto BITS_PER_BYTE KJ_UNUSED = bounded<8>() * BITS / BYTES; +constexpr auto BITS_PER_WORD KJ_UNUSED = bounded<64>() * BITS / WORDS; +constexpr auto BYTES_PER_WORD KJ_UNUSED = bounded<8>() * BYTES / WORDS; + +constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS; +constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS; +constexpr auto WORDS_PER_POINTER KJ_UNUSED = ONE * WORDS / POINTERS; + +constexpr auto POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; + +constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment. +constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list. +constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section. +constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section. +constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob. + +typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount; +typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount; +typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount; +typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount; +typedef ByteCountN<BLOB_SIZE_BITS> BlobSize; + +constexpr auto MAX_SEGMENT_WORDS = + bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS; +constexpr auto MAX_LIST_ELEMENTS = + bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS; +constexpr auto MAX_STUCT_DATA_WORDS = + bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS; +constexpr auto MAX_STRUCT_POINTER_COUNT = + bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS; + +using StructDataBitCount = decltype(WordCountN<STRUCT_POINTER_COUNT_BITS>() * BITS_PER_WORD); +// Number of bits in a Struct data segment (should come out to BitCountN<22>). + +using StructDataOffset = decltype(StructDataBitCount() * (ONE * ELEMENTS / BITS)); +using StructPointerOffset = StructPointerCount; +// Type of a field offset. + +inline StructDataOffset assumeDataOffset(uint32_t offset) { + return assumeMax(MAX_STUCT_DATA_WORDS * BITS_PER_WORD * (ONE * ELEMENTS / BITS), + bounded(offset) * ELEMENTS); +} + +inline StructPointerOffset assumePointerOffset(uint32_t offset) { + return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS); +} + +constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1; +typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize; +// Not including NUL terminator. + +template <typename T> +inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() { + return bounded<sizeof(T)>() * BYTES / ELEMENTS; +} + +template <typename T> +inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() { + return bounded<sizeof(T) * 8>() * BITS / ELEMENTS; +} + +template <typename T, uint maxN> +inline constexpr kj::Quantity<kj::Bounded<maxN, size_t>, T> +intervalLength(const T* a, const T* b, kj::Quantity<kj::BoundedConst<maxN>, T>) { + return kj::assumeMax<maxN>(b - a) * kj::unit<kj::Quantity<kj::BoundedConst<1u>, T>>(); +} + +template <typename T, typename U> +inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, kj::Quantity<T, U> size) { + return kj::ArrayPtr<const U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>())); +} +template <typename T, typename U> +inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, kj::Quantity<T, U> size) { + return kj::ArrayPtr<U>(ptr, unbound(size / kj::unit<kj::Quantity<T, U>>())); +} + +#else + +template <uint width, typename T = uint> +using BitCountN = T; +template <uint width, typename T = uint> +using ByteCountN = T; +template <uint width, typename T = uint> +using WordCountN = T; +template <uint width, typename T = uint> +using ElementCountN = T; +template <uint width, typename T = uint> +using WirePointerCountN = T; + + +// XXX +typedef BitCountN<8, uint8_t> BitCount8; +typedef BitCountN<16, uint16_t> BitCount16; +typedef BitCountN<32, uint32_t> BitCount32; +typedef BitCountN<64, uint64_t> BitCount64; +typedef BitCountN<sizeof(uint) * 8, uint> BitCount; + +typedef ByteCountN<8, uint8_t> ByteCount8; +typedef ByteCountN<16, uint16_t> ByteCount16; +typedef ByteCountN<32, uint32_t> ByteCount32; +typedef ByteCountN<64, uint64_t> ByteCount64; +typedef ByteCountN<sizeof(uint) * 8, uint> ByteCount; + +typedef WordCountN<8, uint8_t> WordCount8; +typedef WordCountN<16, uint16_t> WordCount16; +typedef WordCountN<32, uint32_t> WordCount32; +typedef WordCountN<64, uint64_t> WordCount64; +typedef WordCountN<sizeof(uint) * 8, uint> WordCount; + +typedef ElementCountN<8, uint8_t> ElementCount8; +typedef ElementCountN<16, uint16_t> ElementCount16; +typedef ElementCountN<32, uint32_t> ElementCount32; +typedef ElementCountN<64, uint64_t> ElementCount64; +typedef ElementCountN<sizeof(uint) * 8, uint> ElementCount; + +typedef WirePointerCountN<8, uint8_t> WirePointerCount8; +typedef WirePointerCountN<16, uint16_t> WirePointerCount16; +typedef WirePointerCountN<32, uint32_t> WirePointerCount32; +typedef WirePointerCountN<64, uint64_t> WirePointerCount64; +typedef WirePointerCountN<sizeof(uint) * 8, uint> WirePointerCount; + +template <uint width> +using BitsPerElementN = decltype(BitCountN<width>() / ElementCountN<width>()); +template <uint width> +using BytesPerElementN = decltype(ByteCountN<width>() / ElementCountN<width>()); +template <uint width> +using WordsPerElementN = decltype(WordCountN<width>() / ElementCountN<width>()); +template <uint width> +using PointersPerElementN = decltype(WirePointerCountN<width>() / ElementCountN<width>()); + +using kj::ThrowOverflow; +// YYY + +template <uint i> inline constexpr uint bounded() { return i; } +template <typename T> inline constexpr T bounded(T i) { return i; } +template <typename T> inline constexpr T unbound(T i) { return i; } + +template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; } + +template <uint64_t requestedMax, typename T> inline constexpr uint unboundMax(T i) { return i; } +template <uint bits, typename T> inline constexpr uint unboundMaxBits(T i) { return i; } + +template <uint newMax, typename T, typename ErrorFunc> +inline T assertMax(T value, ErrorFunc&& func) { + if (KJ_UNLIKELY(value > newMax)) func(); + return value; +} + +template <typename T, typename ErrorFunc> +inline T assertMax(uint newMax, T value, ErrorFunc&& func) { + if (KJ_UNLIKELY(value > newMax)) func(); + return value; +} + +template <uint bits, typename T, typename ErrorFunc = ThrowOverflow> +inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) { + if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func(); + return value; +} + +template <typename T, typename ErrorFunc = ThrowOverflow> +inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) { + if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func(); + return value; +} + +template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; } + +template <uint bits, typename T> inline constexpr T assumeBits(T i) { return i; } +template <uint64_t max, typename T> inline constexpr T assumeMax(T i) { return i; } + +template <typename T, typename U, typename ErrorFunc = ThrowOverflow> +inline auto subtractChecked(T a, U b, ErrorFunc&& errorFunc = ErrorFunc()) + -> decltype(a - b) { + if (b > a) errorFunc(); + return a - b; +} + +template <typename T, typename U> +inline auto trySubtract(T a, U b) -> kj::Maybe<decltype(a - b)> { + if (b > a) { + return nullptr; + } else { + return a - b; + } +} + +constexpr uint BITS = 1; +constexpr uint BYTES = 1; +constexpr uint WORDS = 1; +constexpr uint ELEMENTS = 1; +constexpr uint POINTERS = 1; + +constexpr uint ZERO = 0; +constexpr uint ONE = 1; + +// GCC 4.7 actually gives unused warnings on these constants in opt mode... +constexpr uint BITS_PER_BYTE KJ_UNUSED = 8; +constexpr uint BITS_PER_WORD KJ_UNUSED = 64; +constexpr uint BYTES_PER_WORD KJ_UNUSED = 8; + +constexpr uint BITS_PER_POINTER KJ_UNUSED = 64; +constexpr uint BYTES_PER_POINTER KJ_UNUSED = 8; +constexpr uint WORDS_PER_POINTER KJ_UNUSED = 1; + +// XXX +constexpr uint POINTER_SIZE_IN_WORDS = ONE * POINTERS * WORDS_PER_POINTER; + +constexpr uint SEGMENT_WORD_COUNT_BITS = 29; // Number of words in a segment. +constexpr uint LIST_ELEMENT_COUNT_BITS = 29; // Number of elements in a list. +constexpr uint STRUCT_DATA_WORD_COUNT_BITS = 16; // Number of words in a Struct data section. +constexpr uint STRUCT_POINTER_COUNT_BITS = 16; // Number of pointers in a Struct pointer section. +constexpr uint BLOB_SIZE_BITS = 29; // Number of bytes in a blob. + +typedef WordCountN<SEGMENT_WORD_COUNT_BITS> SegmentWordCount; +typedef ElementCountN<LIST_ELEMENT_COUNT_BITS> ListElementCount; +typedef WordCountN<STRUCT_DATA_WORD_COUNT_BITS, uint16_t> StructDataWordCount; +typedef WirePointerCountN<STRUCT_POINTER_COUNT_BITS, uint16_t> StructPointerCount; +typedef ByteCountN<BLOB_SIZE_BITS> BlobSize; +// YYY + +constexpr auto MAX_SEGMENT_WORDS = kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>(); +constexpr auto MAX_LIST_ELEMENTS = kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>(); +constexpr auto MAX_STUCT_DATA_WORDS = kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>(); +constexpr auto MAX_STRUCT_POINTER_COUNT = kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>(); + +typedef uint StructDataBitCount; +typedef uint StructDataOffset; +typedef uint StructPointerOffset; + +inline StructDataOffset assumeDataOffset(uint32_t offset) { return offset; } +inline StructPointerOffset assumePointerOffset(uint32_t offset) { return offset; } + +constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1; +typedef uint TextSize; + +template <typename T> +inline KJ_CONSTEXPR() size_t bytesPerElement() { return sizeof(T); } + +template <typename T> +inline KJ_CONSTEXPR() size_t bitsPerElement() { return sizeof(T) * 8; } + +template <typename T> +inline constexpr ptrdiff_t intervalLength(const T* a, const T* b, uint) { + return b - a; +} + +template <typename T, typename U> +inline constexpr kj::ArrayPtr<const U> arrayPtr(const U* ptr, T size) { + return kj::arrayPtr(ptr, size); +} +template <typename T, typename U> +inline constexpr kj::ArrayPtr<U> arrayPtr(U* ptr, T size) { + return kj::arrayPtr(ptr, size); +} + +#endif + +} // namespace capnp + +#endif // CAPNP_COMMON_H_