common.h 27 KB
Newer Older
Kenton Varda's avatar
Kenton Varda committed
1 2
// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
3
//
Kenton Varda's avatar
Kenton Varda committed
4 5 6 7 8 9
// 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:
10
//
Kenton Varda's avatar
Kenton Varda committed
11 12
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
13
//
Kenton Varda's avatar
Kenton Varda committed
14 15 16 17 18 19 20
// 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.
21 22 23 24 25

// 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.

26
#pragma once
27

28
#if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
29 30 31
#pragma GCC system_header
#endif

Kenton Varda's avatar
Kenton Varda committed
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 38 39 40
#if CAPNP_DEBUG_TYPES
#include <kj/units.h>
#endif

41
namespace capnp {
42

43
#define CAPNP_VERSION_MAJOR 0
44
#define CAPNP_VERSION_MINOR 7
45 46 47 48 49
#define CAPNP_VERSION_MICRO 0

#define CAPNP_VERSION \
  (CAPNP_VERSION_MAJOR * 1000000 + CAPNP_VERSION_MINOR * 1000 + CAPNP_VERSION_MICRO)

50 51 52 53
#ifndef CAPNP_LITE
#define CAPNP_LITE 0
#endif

54 55 56 57 58 59
#if CAPNP_TESTING_CAPNP  // defined in Cap'n Proto's own unit tests; others should not define this
#define CAPNP_DEPRECATED(reason)
#else
#define CAPNP_DEPRECATED KJ_DEPRECATED
#endif

60 61
typedef unsigned int uint;

62 63 64 65 66 67
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; }
68
};
69

70
static constexpr Void VOID = Void();
71 72
// Constant value for `Void`,  which is an empty struct.

73
inline kj::StringPtr KJ_STRINGIFY(Void) { return "void"; }
74

75 76 77 78 79 80 81 82 83 84 85
struct Text;
struct Data;

enum class Kind: uint8_t {
  PRIMITIVE,
  BLOB,
  ENUM,
  STRUCT,
  UNION,
  INTERFACE,
  LIST,
86 87 88 89

  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.
90 91
};

92 93 94 95 96 97 98
enum class Style: uint8_t {
  PRIMITIVE,
  POINTER,      // other than struct
  STRUCT,
  CAPABILITY
};

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
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
};

114 115 116 117 118 119 120 121
enum class PointerType {
  // Various wire types a pointer field can take

  NULL_,
  // Should be NULL, but that's #defined in stddef.h

  STRUCT,
  LIST,
122
  CAPABILITY
123 124
};

125 126 127 128 129 130 131
namespace schemas {

template <typename T>
struct EnumInfo;

}  // namespace schemas

132 133
namespace _ {  // private

134
template <typename T, typename = void> struct Kind_;
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150

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; };

151 152 153 154 155 156 157 158 159
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;
};
160

161 162
}  // namespace _ (private)

163 164 165 166 167 168 169
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;
}

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 179 180 181 182
// Use this macro rather than kind<T>() in any code which must work in MSVC.

#endif  // _MSC_VER, else

#if !CAPNP_LITE
183

184 185 186 187 188 189 190
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;
}

191
#endif  // !CAPNP_LITE
192

193
template <typename T, Kind k = CAPNP_KIND(T)>
194 195
struct List;

196 197 198 199 200 201 202 203 204 205 206
#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

207 208 209 210
template <typename T> struct ListElementType_;
template <typename T> struct ListElementType_<List<T>> { typedef T Type; };
template <typename T> using ListElementType = typename ListElementType_<T>::Type;

211
namespace _ {  // private
212
template <typename T, Kind k> struct Kind_<List<T, k>> {
213 214
  static constexpr Kind kind = Kind::LIST;
};
215 216
}  // namespace _ (private)

217
template <typename T, Kind k = CAPNP_KIND(T)> struct ReaderFor_ { typedef typename T::Reader Type; };
218 219
template <typename T> struct ReaderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
template <typename T> struct ReaderFor_<T, Kind::ENUM> { typedef T Type; };
220
template <typename T> struct ReaderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
221 222 223
template <typename T> using ReaderFor = typename ReaderFor_<T>::Type;
// The type returned by List<T>::Reader::operator[].

224
template <typename T, Kind k = CAPNP_KIND(T)> struct BuilderFor_ { typedef typename T::Builder Type; };
225 226
template <typename T> struct BuilderFor_<T, Kind::PRIMITIVE> { typedef T Type; };
template <typename T> struct BuilderFor_<T, Kind::ENUM> { typedef T Type; };
227
template <typename T> struct BuilderFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
228 229 230
template <typename T> using BuilderFor = typename BuilderFor_<T>::Type;
// The type returned by List<T>::Builder::operator[].

231
template <typename T, Kind k = CAPNP_KIND(T)> struct PipelineFor_ { typedef typename T::Pipeline Type;};
232 233 234
template <typename T> struct PipelineFor_<T, Kind::INTERFACE> { typedef typename T::Client Type; };
template <typename T> using PipelineFor = typename PipelineFor_<T>::Type;

235
template <typename T, Kind k = CAPNP_KIND(T)> struct TypeIfEnum_;
236 237 238 239 240 241 242 243 244 245 246 247 248
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).

249 250 251 252
template <typename T>
using FromPipeline = typename kj::Decay<T>::Pipelines;
// FromBuilder<MyType::Pipeline> = MyType (for any Cap'n Proto type).

253 254 255 256 257 258 259 260
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).

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
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>;
293 294 295
};

template <typename T>
296
using FromAny = typename FromAny_<T>::Type;
297 298 299 300 301 302 303 304 305
// 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

306
namespace _ {  // private
307

308
template <typename T, Kind k = CAPNP_KIND(T)>
309
struct PointerHelpers;
310 311 312 313 314 315 316 317 318 319 320 321

#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

322 323
}  // namespace _ (private)

324
struct MessageSize {
325
  // Size of a message. Every struct and list type has a method `.totalSize()` that returns this.
326 327
  uint64_t wordCount;
  uint capCount;
328 329 330 331

  inline constexpr MessageSize operator+(const MessageSize& other) const {
    return { wordCount + other.wordCount, capCount + other.capCount };
  }
332 333
};

334 335 336 337 338
// =======================================================================================
// Raw memory types and measures

using kj::byte;

339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
class word {
  // 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.
public:
  word() = default;
private:
  uint64_t content KJ_UNUSED_MEMBER;
#if __GNUC__ < 8 || __clang__
  // GCC 8's -Wclass-memaccess complains whenever we try to memcpy() a `word` if we've disallowed
  // the copy constructor. We don't want to disable the warning becaues it's a useful warning and
  // we'd have to disable it for all applications that include this header. Instead we allow `word`
  // to be copyable on GCC.
  KJ_DISALLOW_COPY(word);
#endif
};
361 362 363 364

static_assert(sizeof(byte) == 1, "uint8_t is not one byte?");
static_assert(sizeof(word) == 8, "uint64_t is not 8 bytes?");

365 366 367 368 369
#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.
370
//
371 372 373
// 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.
374

375
namespace _ { class BitLabel; class ElementLabel; struct WirePointer; }
376

377
template <uint width, typename T = uint>
378
using BitCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::BitLabel>;
379
template <uint width, typename T = uint>
380
using ByteCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, byte>;
381
template <uint width, typename T = uint>
382
using WordCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, word>;
383
template <uint width, typename T = uint>
384
using ElementCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::ElementLabel>;
385
template <uint width, typename T = uint>
386
using WirePointerCountN = kj::Quantity<kj::Bounded<kj::maxValueForBits<width>(), T>, _::WirePointer>;
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426

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>());

427 428 429 430 431
using kj::bounded;
using kj::unbound;
using kj::unboundAs;
using kj::unboundMax;
using kj::unboundMaxBits;
432 433
using kj::assertMax;
using kj::assertMaxBits;
434
using kj::upgradeBound;
435 436
using kj::ThrowOverflow;
using kj::assumeBits;
437
using kj::assumeMax;
438
using kj::subtractChecked;
439
using kj::trySubtract;
440

441 442
template <typename T, typename U>
inline constexpr U* operator+(U* ptr, kj::Quantity<T, U> offset) {
443
  return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
444 445 446
}
template <typename T, typename U>
inline constexpr const U* operator+(const U* ptr, kj::Quantity<T, U> offset) {
447
  return ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
448 449 450
}
template <typename T, typename U>
inline constexpr U* operator+=(U*& ptr, kj::Quantity<T, U> offset) {
451
  return ptr = ptr + unbound(offset / kj::unit<kj::Quantity<T, U>>());
452 453 454
}
template <typename T, typename U>
inline 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 458 459
}

template <typename T, typename U>
inline constexpr U* operator-(U* ptr, kj::Quantity<T, U> offset) {
460
  return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
461 462 463
}
template <typename T, typename U>
inline constexpr const U* operator-(const U* ptr, kj::Quantity<T, U> offset) {
464
  return ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
465 466 467
}
template <typename T, typename U>
inline constexpr U* operator-=(U*& ptr, kj::Quantity<T, U> offset) {
468
  return ptr = ptr - unbound(offset / kj::unit<kj::Quantity<T, U>>());
469 470 471
}
template <typename T, typename U>
inline 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
}

475 476 477 478 479
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>>();
480

481 482
constexpr auto ZERO = kj::bounded<0>();
constexpr auto ONE = kj::bounded<1>();
483

484
// GCC 4.7 actually gives unused warnings on these constants in opt mode...
485 486 487
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;
488

489 490
constexpr auto BITS_PER_POINTER KJ_UNUSED = bounded<64>() * BITS / POINTERS;
constexpr auto BYTES_PER_POINTER KJ_UNUSED = bounded<8>() * BYTES / POINTERS;
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
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 =
508
    bounded<kj::maxValueForBits<SEGMENT_WORD_COUNT_BITS>()>() * WORDS;
509
constexpr auto MAX_LIST_ELEMENTS =
510
    bounded<kj::maxValueForBits<LIST_ELEMENT_COUNT_BITS>()>() * ELEMENTS;
511
constexpr auto MAX_STUCT_DATA_WORDS =
512
    bounded<kj::maxValueForBits<STRUCT_DATA_WORD_COUNT_BITS>()>() * WORDS;
513
constexpr auto MAX_STRUCT_POINTER_COUNT =
514
    bounded<kj::maxValueForBits<STRUCT_POINTER_COUNT_BITS>()>() * POINTERS;
515 516 517 518

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>).

519 520 521 522 523 524
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),
525
                   bounded(offset) * ELEMENTS);
526 527 528
}

inline StructPointerOffset assumePointerOffset(uint32_t offset) {
529
  return assumeMax(MAX_STRUCT_POINTER_COUNT, bounded(offset) * POINTERS);
530 531
}

532
constexpr uint MAX_TEXT_SIZE = kj::maxValueForBits<BLOB_SIZE_BITS>() - 1;
533
typedef kj::Quantity<kj::Bounded<MAX_TEXT_SIZE, uint>, byte> TextSize;
534
// Not including NUL terminator.
535 536

template <typename T>
537 538
inline KJ_CONSTEXPR() decltype(bounded<sizeof(T)>() * BYTES / ELEMENTS) bytesPerElement() {
  return bounded<sizeof(T)>() * BYTES / ELEMENTS;
539 540 541
}

template <typename T>
542 543
inline KJ_CONSTEXPR() decltype(bounded<sizeof(T) * 8>() * BITS / ELEMENTS) bitsPerElement() {
  return bounded<sizeof(T) * 8>() * BITS / ELEMENTS;
544 545
}

546
template <typename T, uint maxN>
547 548 549
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>>();
550
}
551 552 553

template <typename T, typename U>
inline 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 556 557
}
template <typename T, typename U>
inline 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 562
#else

563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
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

618 619 620
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; }
621

622
template <typename T, typename U> inline constexpr T unboundAs(U i) { return i; }
623

624 625
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; }
626 627

template <uint newMax, typename T, typename ErrorFunc>
628
inline T assertMax(T value, ErrorFunc&& func) {
629 630 631 632 633
  if (KJ_UNLIKELY(value > newMax)) func();
  return value;
}

template <typename T, typename ErrorFunc>
634
inline T assertMax(uint newMax, T value, ErrorFunc&& func) {
635 636 637 638 639
  if (KJ_UNLIKELY(value > newMax)) func();
  return value;
}

template <uint bits, typename T, typename ErrorFunc = ThrowOverflow>
640
inline T assertMaxBits(T value, ErrorFunc&& func = ErrorFunc()) {
641 642 643 644 645
  if (KJ_UNLIKELY(value > kj::maxValueForBits<bits>())) func();
  return value;
}

template <typename T, typename ErrorFunc = ThrowOverflow>
646
inline T assertMaxBits(uint bits, T value, ErrorFunc&& func = ErrorFunc()) {
647 648 649 650
  if (KJ_UNLIKELY(value > (1ull << bits) - 1)) func();
  return value;
}

651
template <typename T, typename U> inline constexpr T upgradeBound(U i) { return i; }
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739

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);
}
740 741 742

#endif

743
}  // namespace capnp