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

units.h (46198B)


      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 "common.h"
     29 #include <inttypes.h>
     30 
     31 KJ_BEGIN_HEADER
     32 
     33 namespace kj {
     34 
     35 // =======================================================================================
     36 // IDs
     37 
     38 template <typename UnderlyingType, typename Label>
     39 struct Id {
     40   // A type-safe numeric ID.  `UnderlyingType` is the underlying integer representation.  `Label`
     41   // distinguishes this Id from other Id types.  Sample usage:
     42   //
     43   //   class Foo;
     44   //   typedef Id<uint, Foo> FooId;
     45   //
     46   //   class Bar;
     47   //   typedef Id<uint, Bar> BarId;
     48   //
     49   // You can now use the FooId and BarId types without any possibility of accidentally using a
     50   // FooId when you really wanted a BarId or vice-versa.
     51 
     52   UnderlyingType value;
     53 
     54   inline constexpr Id(): value(0) {}
     55   inline constexpr explicit Id(int value): value(value) {}
     56 
     57   inline constexpr bool operator==(const Id& other) const { return value == other.value; }
     58   inline constexpr bool operator!=(const Id& other) const { return value != other.value; }
     59   inline constexpr bool operator<=(const Id& other) const { return value <= other.value; }
     60   inline constexpr bool operator>=(const Id& other) const { return value >= other.value; }
     61   inline constexpr bool operator< (const Id& other) const { return value <  other.value; }
     62   inline constexpr bool operator> (const Id& other) const { return value >  other.value; }
     63 };
     64 
     65 // =======================================================================================
     66 // Quantity and UnitRatio -- implement unit analysis via the type system
     67 
     68 struct Unsafe_ {};
     69 constexpr Unsafe_ unsafe = Unsafe_();
     70 // Use as a parameter to constructors that are unsafe to indicate that you really do mean it.
     71 
     72 template <uint64_t maxN, typename T>
     73 class Bounded;
     74 template <uint value>
     75 class BoundedConst;
     76 
     77 template <typename T> constexpr bool isIntegral() { return false; }
     78 template <> constexpr bool isIntegral<char>() { return true; }
     79 template <> constexpr bool isIntegral<signed char>() { return true; }
     80 template <> constexpr bool isIntegral<short>() { return true; }
     81 template <> constexpr bool isIntegral<int>() { return true; }
     82 template <> constexpr bool isIntegral<long>() { return true; }
     83 template <> constexpr bool isIntegral<long long>() { return true; }
     84 template <> constexpr bool isIntegral<unsigned char>() { return true; }
     85 template <> constexpr bool isIntegral<unsigned short>() { return true; }
     86 template <> constexpr bool isIntegral<unsigned int>() { return true; }
     87 template <> constexpr bool isIntegral<unsigned long>() { return true; }
     88 template <> constexpr bool isIntegral<unsigned long long>() { return true; }
     89 
     90 template <typename T>
     91 struct IsIntegralOrBounded_ { static constexpr bool value = isIntegral<T>(); };
     92 template <uint64_t m, typename T>
     93 struct IsIntegralOrBounded_<Bounded<m, T>> { static constexpr bool value = true; };
     94 template <uint v>
     95 struct IsIntegralOrBounded_<BoundedConst<v>> { static constexpr bool value = true; };
     96 
     97 template <typename T>
     98 inline constexpr bool isIntegralOrBounded() { return IsIntegralOrBounded_<T>::value; }
     99 
    100 template <typename Number, typename Unit1, typename Unit2>
    101 class UnitRatio {
    102   // A multiplier used to convert Quantities of one unit to Quantities of another unit.  See
    103   // Quantity, below.
    104   //
    105   // Construct this type by dividing one Quantity by another of a different unit.  Use this type
    106   // by multiplying it by a Quantity, or dividing a Quantity by it.
    107 
    108   static_assert(isIntegralOrBounded<Number>(),
    109       "Underlying type for UnitRatio must be integer.");
    110 
    111 public:
    112   inline UnitRatio() {}
    113 
    114   constexpr UnitRatio(Number unit1PerUnit2, decltype(unsafe)): unit1PerUnit2(unit1PerUnit2) {}
    115   // This constructor was intended to be private, but GCC complains about it being private in a
    116   // bunch of places that don't appear to even call it, so I made it public.  Oh well.
    117 
    118   template <typename OtherNumber>
    119   inline constexpr UnitRatio(const UnitRatio<OtherNumber, Unit1, Unit2>& other)
    120       : unit1PerUnit2(other.unit1PerUnit2) {}
    121 
    122   template <typename OtherNumber>
    123   inline constexpr UnitRatio<decltype(Number()+OtherNumber()), Unit1, Unit2>
    124       operator+(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
    125     return UnitRatio<decltype(Number()+OtherNumber()), Unit1, Unit2>(
    126         unit1PerUnit2 + other.unit1PerUnit2, unsafe);
    127   }
    128   template <typename OtherNumber>
    129   inline constexpr UnitRatio<decltype(Number()-OtherNumber()), Unit1, Unit2>
    130       operator-(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
    131     return UnitRatio<decltype(Number()-OtherNumber()), Unit1, Unit2>(
    132         unit1PerUnit2 - other.unit1PerUnit2, unsafe);
    133   }
    134 
    135   template <typename OtherNumber, typename Unit3>
    136   inline constexpr UnitRatio<decltype(Number()*OtherNumber()), Unit3, Unit2>
    137       operator*(UnitRatio<OtherNumber, Unit3, Unit1> other) const {
    138     // U1 / U2 * U3 / U1 = U3 / U2
    139     return UnitRatio<decltype(Number()*OtherNumber()), Unit3, Unit2>(
    140         unit1PerUnit2 * other.unit1PerUnit2, unsafe);
    141   }
    142   template <typename OtherNumber, typename Unit3>
    143   inline constexpr UnitRatio<decltype(Number()*OtherNumber()), Unit1, Unit3>
    144       operator*(UnitRatio<OtherNumber, Unit2, Unit3> other) const {
    145     // U1 / U2 * U2 / U3 = U1 / U3
    146     return UnitRatio<decltype(Number()*OtherNumber()), Unit1, Unit3>(
    147         unit1PerUnit2 * other.unit1PerUnit2, unsafe);
    148   }
    149 
    150   template <typename OtherNumber, typename Unit3>
    151   inline constexpr UnitRatio<decltype(Number()*OtherNumber()), Unit3, Unit2>
    152       operator/(UnitRatio<OtherNumber, Unit1, Unit3> other) const {
    153     // (U1 / U2) / (U1 / U3) = U3 / U2
    154     return UnitRatio<decltype(Number()*OtherNumber()), Unit3, Unit2>(
    155         unit1PerUnit2 / other.unit1PerUnit2, unsafe);
    156   }
    157   template <typename OtherNumber, typename Unit3>
    158   inline constexpr UnitRatio<decltype(Number()*OtherNumber()), Unit1, Unit3>
    159       operator/(UnitRatio<OtherNumber, Unit3, Unit2> other) const {
    160     // (U1 / U2) / (U3 / U2) = U1 / U3
    161     return UnitRatio<decltype(Number()*OtherNumber()), Unit1, Unit3>(
    162         unit1PerUnit2 / other.unit1PerUnit2, unsafe);
    163   }
    164 
    165   template <typename OtherNumber>
    166   inline decltype(Number() / OtherNumber())
    167       operator/(UnitRatio<OtherNumber, Unit1, Unit2> other) const {
    168     return unit1PerUnit2 / other.unit1PerUnit2;
    169   }
    170 
    171   template <typename OtherNumber>
    172   inline constexpr bool operator==(const UnitRatio<OtherNumber, Unit1, Unit2>& other) const {
    173     return unit1PerUnit2 == other.unit1PerUnit2;
    174   }
    175   template <typename OtherNumber>
    176   inline constexpr bool operator!=(const UnitRatio<OtherNumber, Unit1, Unit2>& other) const {
    177     return unit1PerUnit2 != other.unit1PerUnit2;
    178   }
    179 
    180 private:
    181   Number unit1PerUnit2;
    182 
    183   template <typename OtherNumber, typename OtherUnit>
    184   friend class Quantity;
    185   template <typename OtherNumber, typename OtherUnit1, typename OtherUnit2>
    186   friend class UnitRatio;
    187 
    188   template <typename N1, typename N2, typename U1, typename U2, typename>
    189   friend inline constexpr UnitRatio<decltype(N1() * N2()), U1, U2>
    190       operator*(N1, UnitRatio<N2, U1, U2>);
    191 };
    192 
    193 template <typename N1, typename N2, typename U1, typename U2,
    194           typename = EnableIf<isIntegralOrBounded<N1>() && isIntegralOrBounded<N2>()>>
    195 inline constexpr UnitRatio<decltype(N1() * N2()), U1, U2>
    196     operator*(N1 n, UnitRatio<N2, U1, U2> r) {
    197   return UnitRatio<decltype(N1() * N2()), U1, U2>(n * r.unit1PerUnit2, unsafe);
    198 }
    199 
    200 template <typename Number, typename Unit>
    201 class Quantity {
    202   // A type-safe numeric quantity, specified in terms of some unit.  Two Quantities cannot be used
    203   // in arithmetic unless they use the same unit.  The `Unit` type parameter is only used to prevent
    204   // accidental mixing of units; this type is never instantiated and can very well be incomplete.
    205   // `Number` is the underlying primitive numeric type.
    206   //
    207   // Quantities support most basic arithmetic operators, intelligently handling units, and
    208   // automatically casting the underlying type in the same way that the compiler would.
    209   //
    210   // To convert a primitive number to a Quantity, multiply it by unit<Quantity<N, U>>().
    211   // To convert a Quantity to a primitive number, divide it by unit<Quantity<N, U>>().
    212   // To convert a Quantity of one unit to another unit, multiply or divide by a UnitRatio.
    213   //
    214   // The Quantity class is not well-suited to hardcore physics as it does not allow multiplying
    215   // one quantity by another.  For example, multiplying meters by meters won't get you square
    216   // meters; it will get you a compiler error.  It would be interesting to see if template
    217   // metaprogramming could properly deal with such things but this isn't needed for the present
    218   // use case.
    219   //
    220   // Sample usage:
    221   //
    222   //   class SecondsLabel;
    223   //   typedef Quantity<double, SecondsLabel> Seconds;
    224   //   constexpr Seconds SECONDS = unit<Seconds>();
    225   //
    226   //   class MinutesLabel;
    227   //   typedef Quantity<double, MinutesLabel> Minutes;
    228   //   constexpr Minutes MINUTES = unit<Minutes>();
    229   //
    230   //   constexpr UnitRatio<double, SecondsLabel, MinutesLabel> SECONDS_PER_MINUTE =
    231   //       60 * SECONDS / MINUTES;
    232   //
    233   //   void waitFor(Seconds seconds) {
    234   //     sleep(seconds / SECONDS);
    235   //   }
    236   //   void waitFor(Minutes minutes) {
    237   //     waitFor(minutes * SECONDS_PER_MINUTE);
    238   //   }
    239   //
    240   //   void waitThreeMinutes() {
    241   //     waitFor(3 * MINUTES);
    242   //   }
    243 
    244   static_assert(isIntegralOrBounded<Number>(),
    245       "Underlying type for Quantity must be integer.");
    246 
    247 public:
    248   inline constexpr Quantity() = default;
    249 
    250   inline constexpr Quantity(MaxValue_): value(maxValue) {}
    251   inline constexpr Quantity(MinValue_): value(minValue) {}
    252   // Allow initialization from maxValue and minValue.
    253   // TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function
    254   // parameters, causing the compiler to complain of a duplicate constructor definition, so we
    255   // specify MaxValue_ and MinValue_ types explicitly.
    256 
    257   inline constexpr Quantity(Number value, decltype(unsafe)): value(value) {}
    258   // This constructor was intended to be private, but GCC complains about it being private in a
    259   // bunch of places that don't appear to even call it, so I made it public.  Oh well.
    260 
    261   template <typename OtherNumber>
    262   inline constexpr Quantity(const Quantity<OtherNumber, Unit>& other)
    263       : value(other.value) {}
    264 
    265   template <typename OtherNumber>
    266   inline Quantity& operator=(const Quantity<OtherNumber, Unit>& other) {
    267     value = other.value;
    268     return *this;
    269   }
    270 
    271   template <typename OtherNumber>
    272   inline constexpr Quantity<decltype(Number() + OtherNumber()), Unit>
    273       operator+(const Quantity<OtherNumber, Unit>& other) const {
    274     return Quantity<decltype(Number() + OtherNumber()), Unit>(value + other.value, unsafe);
    275   }
    276   template <typename OtherNumber>
    277   inline constexpr Quantity<decltype(Number() - OtherNumber()), Unit>
    278       operator-(const Quantity<OtherNumber, Unit>& other) const {
    279     return Quantity<decltype(Number() - OtherNumber()), Unit>(value - other.value, unsafe);
    280   }
    281   template <typename OtherNumber, typename = EnableIf<isIntegralOrBounded<OtherNumber>()>>
    282   inline constexpr Quantity<decltype(Number() * OtherNumber()), Unit>
    283       operator*(OtherNumber other) const {
    284     return Quantity<decltype(Number() * other), Unit>(value * other, unsafe);
    285   }
    286   template <typename OtherNumber, typename = EnableIf<isIntegralOrBounded<OtherNumber>()>>
    287   inline constexpr Quantity<decltype(Number() / OtherNumber()), Unit>
    288       operator/(OtherNumber other) const {
    289     return Quantity<decltype(Number() / other), Unit>(value / other, unsafe);
    290   }
    291   template <typename OtherNumber>
    292   inline constexpr decltype(Number() / OtherNumber())
    293       operator/(const Quantity<OtherNumber, Unit>& other) const {
    294     return value / other.value;
    295   }
    296   template <typename OtherNumber>
    297   inline constexpr Quantity<decltype(Number() % OtherNumber()), Unit>
    298       operator%(const Quantity<OtherNumber, Unit>& other) const {
    299     return Quantity<decltype(Number() % OtherNumber()), Unit>(value % other.value, unsafe);
    300   }
    301 
    302   template <typename OtherNumber, typename OtherUnit>
    303   inline constexpr Quantity<decltype(Number() * OtherNumber()), OtherUnit>
    304       operator*(UnitRatio<OtherNumber, OtherUnit, Unit> ratio) const {
    305     return Quantity<decltype(Number() * OtherNumber()), OtherUnit>(
    306         value * ratio.unit1PerUnit2, unsafe);
    307   }
    308   template <typename OtherNumber, typename OtherUnit>
    309   inline constexpr Quantity<decltype(Number() / OtherNumber()), OtherUnit>
    310       operator/(UnitRatio<OtherNumber, Unit, OtherUnit> ratio) const {
    311     return Quantity<decltype(Number() / OtherNumber()), OtherUnit>(
    312         value / ratio.unit1PerUnit2, unsafe);
    313   }
    314   template <typename OtherNumber, typename OtherUnit>
    315   inline constexpr Quantity<decltype(Number() % OtherNumber()), Unit>
    316       operator%(UnitRatio<OtherNumber, Unit, OtherUnit> ratio) const {
    317     return Quantity<decltype(Number() % OtherNumber()), Unit>(
    318         value % ratio.unit1PerUnit2, unsafe);
    319   }
    320   template <typename OtherNumber, typename OtherUnit>
    321   inline constexpr UnitRatio<decltype(Number() / OtherNumber()), Unit, OtherUnit>
    322       operator/(Quantity<OtherNumber, OtherUnit> other) const {
    323     return UnitRatio<decltype(Number() / OtherNumber()), Unit, OtherUnit>(
    324         value / other.value, unsafe);
    325   }
    326 
    327   template <typename OtherNumber>
    328   inline constexpr bool operator==(const Quantity<OtherNumber, Unit>& other) const {
    329     return value == other.value;
    330   }
    331   template <typename OtherNumber>
    332   inline constexpr bool operator!=(const Quantity<OtherNumber, Unit>& other) const {
    333     return value != other.value;
    334   }
    335   template <typename OtherNumber>
    336   inline constexpr bool operator<=(const Quantity<OtherNumber, Unit>& other) const {
    337     return value <= other.value;
    338   }
    339   template <typename OtherNumber>
    340   inline constexpr bool operator>=(const Quantity<OtherNumber, Unit>& other) const {
    341     return value >= other.value;
    342   }
    343   template <typename OtherNumber>
    344   inline constexpr bool operator<(const Quantity<OtherNumber, Unit>& other) const {
    345     return value < other.value;
    346   }
    347   template <typename OtherNumber>
    348   inline constexpr bool operator>(const Quantity<OtherNumber, Unit>& other) const {
    349     return value > other.value;
    350   }
    351 
    352   template <typename OtherNumber>
    353   inline Quantity& operator+=(const Quantity<OtherNumber, Unit>& other) {
    354     value += other.value;
    355     return *this;
    356   }
    357   template <typename OtherNumber>
    358   inline Quantity& operator-=(const Quantity<OtherNumber, Unit>& other) {
    359     value -= other.value;
    360     return *this;
    361   }
    362   template <typename OtherNumber>
    363   inline Quantity& operator*=(OtherNumber other) {
    364     value *= other;
    365     return *this;
    366   }
    367   template <typename OtherNumber>
    368   inline Quantity& operator/=(OtherNumber other) {
    369     value /= other.value;
    370     return *this;
    371   }
    372 
    373 private:
    374   Number value;
    375 
    376   template <typename OtherNumber, typename OtherUnit>
    377   friend class Quantity;
    378 
    379   template <typename Number1, typename Number2, typename Unit2, typename>
    380   friend inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit2> b)
    381       -> Quantity<decltype(Number1() * Number2()), Unit2>;
    382 };
    383 
    384 template <typename T> struct Unit_ {
    385   static inline constexpr T get() { return T(1); }
    386 };
    387 template <typename T, typename U>
    388 struct Unit_<Quantity<T, U>> {
    389   static inline constexpr Quantity<decltype(Unit_<T>::get()), U> get() {
    390     return Quantity<decltype(Unit_<T>::get()), U>(Unit_<T>::get(), unsafe);
    391   }
    392 };
    393 
    394 template <typename T>
    395 inline constexpr auto unit() -> decltype(Unit_<T>::get()) { return Unit_<T>::get(); }
    396 // unit<Quantity<T, U>>() returns a Quantity of value 1.  It also, intentionally, works on basic
    397 // numeric types.
    398 
    399 template <typename Number1, typename Number2, typename Unit,
    400           typename = EnableIf<isIntegralOrBounded<Number1>()>>
    401 inline constexpr auto operator*(Number1 a, Quantity<Number2, Unit> b)
    402     -> Quantity<decltype(Number1() * Number2()), Unit> {
    403   return Quantity<decltype(Number1() * Number2()), Unit>(a * b.value, unsafe);
    404 }
    405 
    406 template <typename Number1, typename Number2, typename Unit, typename Unit2>
    407 inline constexpr auto operator*(UnitRatio<Number1, Unit2, Unit> ratio,
    408     Quantity<Number2, Unit> measure)
    409     -> decltype(measure * ratio) {
    410   return measure * ratio;
    411 }
    412 
    413 // =======================================================================================
    414 // Absolute measures
    415 
    416 template <typename T, typename Label>
    417 class Absolute {
    418   // Wraps some other value -- typically a Quantity -- but represents a value measured based on
    419   // some absolute origin.  For example, if `Duration` is a type representing a time duration,
    420   // Absolute<Duration, UnixEpoch> might be a calendar date.
    421   //
    422   // Since Absolute represents measurements relative to some arbitrary origin, the only sensible
    423   // arithmetic to perform on them is addition and subtraction.
    424 
    425   // TODO(someday):  Do the same automatic expansion of integer width that Quantity does?  Doesn't
    426   //   matter for our time use case, where we always use 64-bit anyway.  Note that fixing this
    427   //   would implicitly allow things like multiplying an Absolute by a UnitRatio to change its
    428   //   units, which is actually totally logical and kind of neat.
    429 
    430 public:
    431   inline constexpr Absolute(MaxValue_): value(maxValue) {}
    432   inline constexpr Absolute(MinValue_): value(minValue) {}
    433   // Allow initialization from maxValue and minValue.
    434   // TODO(msvc): decltype(maxValue) and decltype(minValue) deduce unknown-type for these function
    435   // parameters, causing the compiler to complain of a duplicate constructor definition, so we
    436   // specify MaxValue_ and MinValue_ types explicitly.
    437 
    438   inline constexpr Absolute operator+(const T& other) const { return Absolute(value + other); }
    439   inline constexpr Absolute operator-(const T& other) const { return Absolute(value - other); }
    440   inline constexpr T operator-(const Absolute& other) const { return value - other.value; }
    441 
    442   inline Absolute& operator+=(const T& other) { value += other; return *this; }
    443   inline Absolute& operator-=(const T& other) { value -= other; return *this; }
    444 
    445   inline constexpr bool operator==(const Absolute& other) const { return value == other.value; }
    446   inline constexpr bool operator!=(const Absolute& other) const { return value != other.value; }
    447   inline constexpr bool operator<=(const Absolute& other) const { return value <= other.value; }
    448   inline constexpr bool operator>=(const Absolute& other) const { return value >= other.value; }
    449   inline constexpr bool operator< (const Absolute& other) const { return value <  other.value; }
    450   inline constexpr bool operator> (const Absolute& other) const { return value >  other.value; }
    451 
    452 private:
    453   T value;
    454 
    455   explicit constexpr Absolute(T value): value(value) {}
    456 
    457   template <typename U>
    458   friend inline constexpr U origin();
    459 };
    460 
    461 template <typename T, typename Label>
    462 inline constexpr Absolute<T, Label> operator+(const T& a, const Absolute<T, Label>& b) {
    463   return b + a;
    464 }
    465 
    466 template <typename T> struct UnitOf_ { typedef T Type; };
    467 template <typename T, typename Label> struct UnitOf_<Absolute<T, Label>> { typedef T Type; };
    468 template <typename T>
    469 using UnitOf = typename UnitOf_<T>::Type;
    470 // UnitOf<Absolute<T, U>> is T.  UnitOf<AnythingElse> is AnythingElse.
    471 
    472 template <typename T>
    473 inline constexpr T origin() { return T(0 * unit<UnitOf<T>>()); }
    474 // origin<Absolute<T, U>>() returns an Absolute of value 0.  It also, intentionally, works on basic
    475 // numeric types.
    476 
    477 // =======================================================================================
    478 // Overflow avoidance
    479 
    480 template <uint64_t n, uint accum = 0>
    481 struct BitCount_ {
    482   static constexpr uint value = BitCount_<(n >> 1), accum + 1>::value;
    483 };
    484 template <uint accum>
    485 struct BitCount_<0, accum> {
    486   static constexpr uint value = accum;
    487 };
    488 
    489 template <uint64_t n>
    490 inline constexpr uint bitCount() { return BitCount_<n>::value; }
    491 // Number of bits required to represent the number `n`.
    492 
    493 template <uint bitCountBitCount> struct AtLeastUInt_ {
    494   static_assert(bitCountBitCount < 7, "don't know how to represent integers over 64 bits");
    495 };
    496 template <> struct AtLeastUInt_<0> { typedef uint8_t Type; };
    497 template <> struct AtLeastUInt_<1> { typedef uint8_t Type; };
    498 template <> struct AtLeastUInt_<2> { typedef uint8_t Type; };
    499 template <> struct AtLeastUInt_<3> { typedef uint8_t Type; };
    500 template <> struct AtLeastUInt_<4> { typedef uint16_t Type; };
    501 template <> struct AtLeastUInt_<5> { typedef uint32_t Type; };
    502 template <> struct AtLeastUInt_<6> { typedef uint64_t Type; };
    503 
    504 template <uint bits>
    505 using AtLeastUInt = typename AtLeastUInt_<bitCount<max(bits, 1) - 1>()>::Type;
    506 // AtLeastUInt<n> is an unsigned integer of at least n bits. E.g. AtLeastUInt<12> is uint16_t.
    507 
    508 // -------------------------------------------------------------------
    509 
    510 template <uint value>
    511 class BoundedConst {
    512   // A constant integer value on which we can do bit size analysis.
    513 
    514 public:
    515   BoundedConst() = default;
    516 
    517   inline constexpr uint unwrap() const { return value; }
    518 
    519 #define OP(op, check) \
    520   template <uint other> \
    521   inline constexpr BoundedConst<(value op other)> \
    522       operator op(BoundedConst<other>) const { \
    523     static_assert(check, "overflow in BoundedConst arithmetic"); \
    524     return BoundedConst<(value op other)>(); \
    525   }
    526 #define COMPARE_OP(op) \
    527   template <uint other> \
    528   inline constexpr bool operator op(BoundedConst<other>) const { \
    529     return value op other; \
    530   }
    531 
    532   OP(+, value + other >= value)
    533   OP(-, value - other <= value)
    534   OP(*, value * other / other == value)
    535   OP(/, true)   // div by zero already errors out; no other division ever overflows
    536   OP(%, true)   // mod by zero already errors out; no other modulus ever overflows
    537   OP(<<, value << other >= value)
    538   OP(>>, true)  // right shift can't overflow
    539   OP(&, true)   // bitwise ops can't overflow
    540   OP(|, true)   // bitwise ops can't overflow
    541 
    542   COMPARE_OP(==)
    543   COMPARE_OP(!=)
    544   COMPARE_OP(< )
    545   COMPARE_OP(> )
    546   COMPARE_OP(<=)
    547   COMPARE_OP(>=)
    548 #undef OP
    549 #undef COMPARE_OP
    550 };
    551 
    552 template <uint64_t m, typename T>
    553 struct Unit_<Bounded<m, T>> {
    554   static inline constexpr BoundedConst<1> get() { return BoundedConst<1>(); }
    555 };
    556 
    557 template <uint value>
    558 struct Unit_<BoundedConst<value>> {
    559   static inline constexpr BoundedConst<1> get() { return BoundedConst<1>(); }
    560 };
    561 
    562 template <uint value>
    563 inline constexpr BoundedConst<value> bounded() {
    564   return BoundedConst<value>();
    565 }
    566 
    567 template <uint64_t a, uint64_t b>
    568 static constexpr uint64_t boundedAdd() {
    569   static_assert(a + b >= a, "possible overflow detected");
    570   return a + b;
    571 }
    572 template <uint64_t a, uint64_t b>
    573 static constexpr uint64_t boundedSub() {
    574   static_assert(a - b <= a, "possible underflow detected");
    575   return a - b;
    576 }
    577 template <uint64_t a, uint64_t b>
    578 static constexpr uint64_t boundedMul() {
    579   static_assert(a * b / b == a, "possible overflow detected");
    580   return a * b;
    581 }
    582 template <uint64_t a, uint64_t b>
    583 static constexpr uint64_t boundedLShift() {
    584   static_assert(a << b >= a, "possible overflow detected");
    585   return a << b;
    586 }
    587 
    588 template <uint a, uint b>
    589 inline constexpr BoundedConst<kj::min(a, b)> min(BoundedConst<a>, BoundedConst<b>) {
    590   return bounded<kj::min(a, b)>();
    591 }
    592 template <uint a, uint b>
    593 inline constexpr BoundedConst<kj::max(a, b)> max(BoundedConst<a>, BoundedConst<b>) {
    594   return bounded<kj::max(a, b)>();
    595 }
    596 // We need to override min() and max() between constants because the ternary operator in the
    597 // default implementation would complain.
    598 
    599 // -------------------------------------------------------------------
    600 
    601 template <uint64_t maxN, typename T>
    602 class Bounded {
    603 public:
    604   static_assert(maxN <= T(kj::maxValue), "possible overflow detected");
    605 
    606   Bounded() = default;
    607 
    608   Bounded(const Bounded& other) = default;
    609   template <typename OtherInt, typename = EnableIf<isIntegral<OtherInt>()>>
    610   inline constexpr Bounded(OtherInt value): value(value) {
    611     static_assert(OtherInt(maxValue) <= maxN, "possible overflow detected");
    612   }
    613   template <uint64_t otherMax, typename OtherT>
    614   inline constexpr Bounded(const Bounded<otherMax, OtherT>& other)
    615       : value(other.value) {
    616     static_assert(otherMax <= maxN, "possible overflow detected");
    617   }
    618   template <uint otherValue>
    619   inline constexpr Bounded(BoundedConst<otherValue>)
    620       : value(otherValue) {
    621     static_assert(otherValue <= maxN, "overflow detected");
    622   }
    623 
    624   Bounded& operator=(const Bounded& other) = default;
    625   template <typename OtherInt, typename = EnableIf<isIntegral<OtherInt>()>>
    626   Bounded& operator=(OtherInt other) {
    627     static_assert(OtherInt(maxValue) <= maxN, "possible overflow detected");
    628     value = other;
    629     return *this;
    630   }
    631   template <uint64_t otherMax, typename OtherT>
    632   inline Bounded& operator=(const Bounded<otherMax, OtherT>& other) {
    633     static_assert(otherMax <= maxN, "possible overflow detected");
    634     value = other.value;
    635     return *this;
    636   }
    637   template <uint otherValue>
    638   inline Bounded& operator=(BoundedConst<otherValue>) {
    639     static_assert(otherValue <= maxN, "overflow detected");
    640     value = otherValue;
    641     return *this;
    642   }
    643 
    644   inline constexpr T unwrap() const { return value; }
    645 
    646 #define OP(op, newMax) \
    647   template <uint64_t otherMax, typename otherT> \
    648   inline constexpr Bounded<newMax, decltype(T() op otherT())> \
    649       operator op(const Bounded<otherMax, otherT>& other) const { \
    650     return Bounded<newMax, decltype(T() op otherT())>(value op other.value, unsafe); \
    651   }
    652 #define COMPARE_OP(op) \
    653   template <uint64_t otherMax, typename OtherT> \
    654   inline constexpr bool operator op(const Bounded<otherMax, OtherT>& other) const { \
    655     return value op other.value; \
    656   }
    657 
    658   OP(+, (boundedAdd<maxN, otherMax>()))
    659   OP(*, (boundedMul<maxN, otherMax>()))
    660   OP(/, maxN)
    661   OP(%, otherMax - 1)
    662 
    663   // operator- is intentionally omitted because we mostly use this with unsigned types, and
    664   // subtraction requires proof that subtrahend is not greater than the minuend.
    665 
    666   COMPARE_OP(==)
    667   COMPARE_OP(!=)
    668   COMPARE_OP(< )
    669   COMPARE_OP(> )
    670   COMPARE_OP(<=)
    671   COMPARE_OP(>=)
    672 
    673 #undef OP
    674 #undef COMPARE_OP
    675 
    676   template <uint64_t newMax, typename ErrorFunc>
    677   inline Bounded<newMax, T> assertMax(ErrorFunc&& func) const {
    678     // Assert that the number is no more than `newMax`. Otherwise, call `func`.
    679     static_assert(newMax < maxN, "this bounded size assertion is redundant");
    680     if (KJ_UNLIKELY(value > newMax)) func();
    681     return Bounded<newMax, T>(value, unsafe);
    682   }
    683 
    684   template <uint64_t otherMax, typename OtherT, typename ErrorFunc>
    685   inline Bounded<maxN, decltype(T() - OtherT())> subtractChecked(
    686       const Bounded<otherMax, OtherT>& other, ErrorFunc&& func) const {
    687     // Subtract a number, calling func() if the result would underflow.
    688     if (KJ_UNLIKELY(value < other.value)) func();
    689     return Bounded<maxN, decltype(T() - OtherT())>(value - other.value, unsafe);
    690   }
    691 
    692   template <uint otherValue, typename ErrorFunc>
    693   inline Bounded<maxN - otherValue, T> subtractChecked(
    694       BoundedConst<otherValue>, ErrorFunc&& func) const {
    695     // Subtract a number, calling func() if the result would underflow.
    696     static_assert(otherValue <= maxN, "underflow detected");
    697     if (KJ_UNLIKELY(value < otherValue)) func();
    698     return Bounded<maxN - otherValue, T>(value - otherValue, unsafe);
    699   }
    700 
    701   template <uint64_t otherMax, typename OtherT>
    702   inline Maybe<Bounded<maxN, decltype(T() - OtherT())>> trySubtract(
    703       const Bounded<otherMax, OtherT>& other) const {
    704     // Subtract a number, calling func() if the result would underflow.
    705     if (value < other.value) {
    706       return nullptr;
    707     } else {
    708       return Bounded<maxN, decltype(T() - OtherT())>(value - other.value, unsafe);
    709     }
    710   }
    711 
    712   template <uint otherValue>
    713   inline Maybe<Bounded<maxN - otherValue, T>> trySubtract(BoundedConst<otherValue>) const {
    714     // Subtract a number, calling func() if the result would underflow.
    715     if (value < otherValue) {
    716       return nullptr;
    717     } else {
    718       return Bounded<maxN - otherValue, T>(value - otherValue, unsafe);
    719     }
    720   }
    721 
    722   inline constexpr Bounded(T value, decltype(unsafe)): value(value) {}
    723   template <uint64_t otherMax, typename OtherT>
    724   inline constexpr Bounded(Bounded<otherMax, OtherT> value, decltype(unsafe))
    725       : value(value.value) {}
    726   // Mainly for internal use.
    727   //
    728   // Only use these as a last resort, with ample commentary on why you think it's safe.
    729 
    730 private:
    731   T value;
    732 
    733   template <uint64_t, typename>
    734   friend class Bounded;
    735 };
    736 
    737 template <typename Number>
    738 inline constexpr Bounded<Number(kj::maxValue), Number> bounded(Number value) {
    739   return Bounded<Number(kj::maxValue), Number>(value, unsafe);
    740 }
    741 
    742 inline constexpr Bounded<1, uint8_t> bounded(bool value) {
    743   return Bounded<1, uint8_t>(value, unsafe);
    744 }
    745 
    746 template <uint bits, typename Number>
    747 inline constexpr Bounded<maxValueForBits<bits>(), Number> assumeBits(Number value) {
    748   return Bounded<maxValueForBits<bits>(), Number>(value, unsafe);
    749 }
    750 
    751 template <uint bits, uint64_t maxN, typename T>
    752 inline constexpr Bounded<maxValueForBits<bits>(), T> assumeBits(Bounded<maxN, T> value) {
    753   return Bounded<maxValueForBits<bits>(), T>(value, unsafe);
    754 }
    755 
    756 template <uint bits, typename Number, typename Unit>
    757 inline constexpr auto assumeBits(Quantity<Number, Unit> value)
    758     -> Quantity<decltype(assumeBits<bits>(value / unit<Quantity<Number, Unit>>())), Unit> {
    759   return Quantity<decltype(assumeBits<bits>(value / unit<Quantity<Number, Unit>>())), Unit>(
    760       assumeBits<bits>(value / unit<Quantity<Number, Unit>>()), unsafe);
    761 }
    762 
    763 template <uint64_t maxN, typename Number>
    764 inline constexpr Bounded<maxN, Number> assumeMax(Number value) {
    765   return Bounded<maxN, Number>(value, unsafe);
    766 }
    767 
    768 template <uint64_t newMaxN, uint64_t maxN, typename T>
    769 inline constexpr Bounded<newMaxN, T> assumeMax(Bounded<maxN, T> value) {
    770   return Bounded<newMaxN, T>(value, unsafe);
    771 }
    772 
    773 template <uint64_t maxN, typename Number, typename Unit>
    774 inline constexpr auto assumeMax(Quantity<Number, Unit> value)
    775     -> Quantity<decltype(assumeMax<maxN>(value / unit<Quantity<Number, Unit>>())), Unit> {
    776   return Quantity<decltype(assumeMax<maxN>(value / unit<Quantity<Number, Unit>>())), Unit>(
    777       assumeMax<maxN>(value / unit<Quantity<Number, Unit>>()), unsafe);
    778 }
    779 
    780 template <uint maxN, typename Number>
    781 inline constexpr Bounded<maxN, Number> assumeMax(BoundedConst<maxN>, Number value) {
    782   return assumeMax<maxN>(value);
    783 }
    784 
    785 template <uint newMaxN, uint64_t maxN, typename T>
    786 inline constexpr Bounded<newMaxN, T> assumeMax(BoundedConst<maxN>, Bounded<maxN, T> value) {
    787   return assumeMax<maxN>(value);
    788 }
    789 
    790 template <uint maxN, typename Number, typename Unit>
    791 inline constexpr auto assumeMax(Quantity<BoundedConst<maxN>, Unit>, Quantity<Number, Unit> value)
    792     -> decltype(assumeMax<maxN>(value)) {
    793   return assumeMax<maxN>(value);
    794 }
    795 
    796 template <uint64_t newMax, uint64_t maxN, typename T, typename ErrorFunc>
    797 inline Bounded<newMax, T> assertMax(Bounded<maxN, T> value, ErrorFunc&& errorFunc) {
    798   // Assert that the bounded value is less than or equal to the given maximum, calling errorFunc()
    799   // if not.
    800   static_assert(newMax < maxN, "this bounded size assertion is redundant");
    801   return value.template assertMax<newMax>(kj::fwd<ErrorFunc>(errorFunc));
    802 }
    803 
    804 template <uint64_t newMax, uint64_t maxN, typename T, typename Unit, typename ErrorFunc>
    805 inline Quantity<Bounded<newMax, T>, Unit> assertMax(
    806     Quantity<Bounded<maxN, T>, Unit> value, ErrorFunc&& errorFunc) {
    807   // Assert that the bounded value is less than or equal to the given maximum, calling errorFunc()
    808   // if not.
    809   static_assert(newMax < maxN, "this bounded size assertion is redundant");
    810   return (value / unit<decltype(value)>()).template assertMax<newMax>(
    811       kj::fwd<ErrorFunc>(errorFunc)) * unit<decltype(value)>();
    812 }
    813 
    814 template <uint newMax, uint64_t maxN, typename T, typename ErrorFunc>
    815 inline Bounded<newMax, T> assertMax(
    816     BoundedConst<newMax>, Bounded<maxN, T> value, ErrorFunc&& errorFunc) {
    817   return assertMax<newMax>(value, kj::mv(errorFunc));
    818 }
    819 
    820 template <uint newMax, uint64_t maxN, typename T, typename Unit, typename ErrorFunc>
    821 inline Quantity<Bounded<newMax, T>, Unit> assertMax(
    822     Quantity<BoundedConst<newMax>, Unit>,
    823     Quantity<Bounded<maxN, T>, Unit> value, ErrorFunc&& errorFunc) {
    824   return assertMax<newMax>(value, kj::mv(errorFunc));
    825 }
    826 
    827 template <uint64_t newBits, uint64_t maxN, typename T, typename ErrorFunc = ThrowOverflow>
    828 inline Bounded<maxValueForBits<newBits>(), T> assertMaxBits(
    829     Bounded<maxN, T> value, ErrorFunc&& errorFunc = ErrorFunc()) {
    830   // Assert that the bounded value requires no more than the given number of bits, calling
    831   // errorFunc() if not.
    832   return assertMax<maxValueForBits<newBits>()>(value, kj::fwd<ErrorFunc>(errorFunc));
    833 }
    834 
    835 template <uint64_t newBits, uint64_t maxN, typename T, typename Unit,
    836           typename ErrorFunc = ThrowOverflow>
    837 inline Quantity<Bounded<maxValueForBits<newBits>(), T>, Unit> assertMaxBits(
    838     Quantity<Bounded<maxN, T>, Unit> value, ErrorFunc&& errorFunc = ErrorFunc()) {
    839   // Assert that the bounded value requires no more than the given number of bits, calling
    840   // errorFunc() if not.
    841   return assertMax<maxValueForBits<newBits>()>(value, kj::fwd<ErrorFunc>(errorFunc));
    842 }
    843 
    844 template <typename newT, uint64_t maxN, typename T>
    845 inline constexpr Bounded<maxN, newT> upgradeBound(Bounded<maxN, T> value) {
    846   return value;
    847 }
    848 
    849 template <typename newT, uint64_t maxN, typename T, typename Unit>
    850 inline constexpr Quantity<Bounded<maxN, newT>, Unit> upgradeBound(
    851     Quantity<Bounded<maxN, T>, Unit> value) {
    852   return value;
    853 }
    854 
    855 template <uint64_t maxN, typename T, typename Other, typename ErrorFunc>
    856 inline auto subtractChecked(Bounded<maxN, T> value, Other other, ErrorFunc&& errorFunc)
    857     -> decltype(value.subtractChecked(other, kj::fwd<ErrorFunc>(errorFunc))) {
    858   return value.subtractChecked(other, kj::fwd<ErrorFunc>(errorFunc));
    859 }
    860 
    861 template <typename T, typename U, typename Unit, typename ErrorFunc>
    862 inline auto subtractChecked(Quantity<T, Unit> value, Quantity<U, Unit> other, ErrorFunc&& errorFunc)
    863     -> Quantity<decltype(subtractChecked(T(), U(), kj::fwd<ErrorFunc>(errorFunc))), Unit> {
    864   return subtractChecked(value / unit<Quantity<T, Unit>>(),
    865                          other / unit<Quantity<U, Unit>>(),
    866                          kj::fwd<ErrorFunc>(errorFunc))
    867       * unit<Quantity<T, Unit>>();
    868 }
    869 
    870 template <uint64_t maxN, typename T, typename Other>
    871 inline auto trySubtract(Bounded<maxN, T> value, Other other)
    872     -> decltype(value.trySubtract(other)) {
    873   return value.trySubtract(other);
    874 }
    875 
    876 template <typename T, typename U, typename Unit>
    877 inline auto trySubtract(Quantity<T, Unit> value, Quantity<U, Unit> other)
    878     -> Maybe<Quantity<decltype(subtractChecked(T(), U(), int())), Unit>> {
    879   return trySubtract(value / unit<Quantity<T, Unit>>(),
    880                      other / unit<Quantity<U, Unit>>())
    881       .map([](decltype(subtractChecked(T(), U(), int())) x) {
    882     return x * unit<Quantity<T, Unit>>();
    883   });
    884 }
    885 
    886 template <uint64_t aN, uint64_t bN, typename A, typename B>
    887 inline constexpr Bounded<kj::min(aN, bN), WiderType<A, B>>
    888 min(Bounded<aN, A> a, Bounded<bN, B> b) {
    889   return Bounded<kj::min(aN, bN), WiderType<A, B>>(kj::min(a.unwrap(), b.unwrap()), unsafe);
    890 }
    891 template <uint64_t aN, uint64_t bN, typename A, typename B>
    892 inline constexpr Bounded<kj::max(aN, bN), WiderType<A, B>>
    893 max(Bounded<aN, A> a, Bounded<bN, B> b) {
    894   return Bounded<kj::max(aN, bN), WiderType<A, B>>(kj::max(a.unwrap(), b.unwrap()), unsafe);
    895 }
    896 // We need to override min() and max() because:
    897 // 1) WiderType<> might not choose the correct bounds.
    898 // 2) One of the two sides of the ternary operator in the default implementation would fail to
    899 //    typecheck even though it is OK in practice.
    900 
    901 // -------------------------------------------------------------------
    902 // Operators between Bounded and BoundedConst
    903 
    904 #define OP(op, newMax) \
    905 template <uint64_t maxN, uint cvalue, typename T> \
    906 inline constexpr Bounded<(newMax), decltype(T() op uint())> operator op( \
    907     Bounded<maxN, T> value, BoundedConst<cvalue>) { \
    908   return Bounded<(newMax), decltype(T() op uint())>(value.unwrap() op cvalue, unsafe); \
    909 }
    910 
    911 #define REVERSE_OP(op, newMax) \
    912 template <uint64_t maxN, uint cvalue, typename T> \
    913 inline constexpr Bounded<(newMax), decltype(uint() op T())> operator op( \
    914     BoundedConst<cvalue>, Bounded<maxN, T> value) { \
    915   return Bounded<(newMax), decltype(uint() op T())>(cvalue op value.unwrap(), unsafe); \
    916 }
    917 
    918 #define COMPARE_OP(op) \
    919 template <uint64_t maxN, uint cvalue, typename T> \
    920 inline constexpr bool operator op(Bounded<maxN, T> value, BoundedConst<cvalue>) { \
    921   return value.unwrap() op cvalue; \
    922 } \
    923 template <uint64_t maxN, uint cvalue, typename T> \
    924 inline constexpr bool operator op(BoundedConst<cvalue>, Bounded<maxN, T> value) { \
    925   return cvalue op value.unwrap(); \
    926 }
    927 
    928 OP(+, (boundedAdd<maxN, cvalue>()))
    929 REVERSE_OP(+, (boundedAdd<maxN, cvalue>()))
    930 
    931 OP(*, (boundedMul<maxN, cvalue>()))
    932 REVERSE_OP(*, (boundedAdd<maxN, cvalue>()))
    933 
    934 OP(/, maxN / cvalue)
    935 REVERSE_OP(/, cvalue)  // denominator could be 1
    936 
    937 OP(%, cvalue - 1)
    938 REVERSE_OP(%, maxN - 1)
    939 
    940 OP(<<, (boundedLShift<maxN, cvalue>()))
    941 REVERSE_OP(<<, (boundedLShift<cvalue, maxN>()))
    942 
    943 OP(>>, maxN >> cvalue)
    944 REVERSE_OP(>>, cvalue >> maxN)
    945 
    946 OP(&, maxValueForBits<bitCount<maxN>()>() & cvalue)
    947 REVERSE_OP(&, maxValueForBits<bitCount<maxN>()>() & cvalue)
    948 
    949 OP(|, maxN | cvalue)
    950 REVERSE_OP(|, maxN | cvalue)
    951 
    952 COMPARE_OP(==)
    953 COMPARE_OP(!=)
    954 COMPARE_OP(< )
    955 COMPARE_OP(> )
    956 COMPARE_OP(<=)
    957 COMPARE_OP(>=)
    958 
    959 #undef OP
    960 #undef REVERSE_OP
    961 #undef COMPARE_OP
    962 
    963 template <uint64_t maxN, uint cvalue, typename T>
    964 inline constexpr Bounded<cvalue, decltype(uint() - T())>
    965     operator-(BoundedConst<cvalue>, Bounded<maxN, T> value) {
    966   // We allow subtraction of a variable from a constant only if the constant is greater than or
    967   // equal to the maximum possible value of the variable. Since the variable could be zero, the
    968   // result can be as large as the constant.
    969   //
    970   // We do not allow subtraction of a constant from a variable because there's never a guarantee it
    971   // won't underflow (unless the constant is zero, which is silly).
    972   static_assert(cvalue >= maxN, "possible underflow detected");
    973   return Bounded<cvalue, decltype(uint() - T())>(cvalue - value.unwrap(), unsafe);
    974 }
    975 
    976 template <uint64_t aN, uint b, typename A>
    977 inline constexpr Bounded<kj::min(aN, b), A> min(Bounded<aN, A> a, BoundedConst<b>) {
    978   return Bounded<kj::min(aN, b), A>(kj::min(b, a.unwrap()), unsafe);
    979 }
    980 template <uint64_t aN, uint b, typename A>
    981 inline constexpr Bounded<kj::min(aN, b), A> min(BoundedConst<b>, Bounded<aN, A> a) {
    982   return Bounded<kj::min(aN, b), A>(kj::min(a.unwrap(), b), unsafe);
    983 }
    984 template <uint64_t aN, uint b, typename A>
    985 inline constexpr Bounded<kj::max(aN, b), A> max(Bounded<aN, A> a, BoundedConst<b>) {
    986   return Bounded<kj::max(aN, b), A>(kj::max(b, a.unwrap()), unsafe);
    987 }
    988 template <uint64_t aN, uint b, typename A>
    989 inline constexpr Bounded<kj::max(aN, b), A> max(BoundedConst<b>, Bounded<aN, A> a) {
    990   return Bounded<kj::max(aN, b), A>(kj::max(a.unwrap(), b), unsafe);
    991 }
    992 // We need to override min() between a Bounded and a constant since:
    993 // 1) WiderType<> might choose BoundedConst over a 1-byte Bounded, which is wrong.
    994 // 2) To clamp the bounds of the output type.
    995 // 3) Same ternary operator typechecking issues.
    996 
    997 // -------------------------------------------------------------------
    998 
    999 template <uint64_t maxN, typename T>
   1000 class SafeUnwrapper {
   1001 public:
   1002   inline explicit constexpr SafeUnwrapper(Bounded<maxN, T> value): value(value.unwrap()) {}
   1003 
   1004   template <typename U, typename = EnableIf<isIntegral<U>()>>
   1005   inline constexpr operator U() const {
   1006     static_assert(maxN <= U(maxValue), "possible truncation detected");
   1007     return value;
   1008   }
   1009 
   1010   inline constexpr operator bool() const {
   1011     static_assert(maxN <= 1, "possible truncation detected");
   1012     return value;
   1013   }
   1014 
   1015 private:
   1016   T value;
   1017 };
   1018 
   1019 template <uint64_t maxN, typename T>
   1020 inline constexpr SafeUnwrapper<maxN, T> unbound(Bounded<maxN, T> bounded) {
   1021   // Unwraps the bounded value, returning a value that can be implicitly cast to any integer type.
   1022   // If this implicit cast could truncate, a compile-time error will be raised.
   1023   return SafeUnwrapper<maxN, T>(bounded);
   1024 }
   1025 
   1026 template <uint64_t value>
   1027 class SafeConstUnwrapper {
   1028 public:
   1029   template <typename T, typename = EnableIf<isIntegral<T>()>>
   1030   inline constexpr operator T() const {
   1031     static_assert(value <= T(maxValue), "this operation will truncate");
   1032     return value;
   1033   }
   1034 
   1035   inline constexpr operator bool() const {
   1036     static_assert(value <= 1, "this operation will truncate");
   1037     return value;
   1038   }
   1039 };
   1040 
   1041 template <uint value>
   1042 inline constexpr SafeConstUnwrapper<value> unbound(BoundedConst<value>) {
   1043   return SafeConstUnwrapper<value>();
   1044 }
   1045 
   1046 template <typename T, typename U>
   1047 inline constexpr T unboundAs(U value) {
   1048   return unbound(value);
   1049 }
   1050 
   1051 template <uint64_t requestedMax, uint64_t maxN, typename T>
   1052 inline constexpr T unboundMax(Bounded<maxN, T> value) {
   1053   // Explicitly unguard expecting a value that is at most `maxN`.
   1054   static_assert(maxN <= requestedMax, "possible overflow detected");
   1055   return value.unwrap();
   1056 }
   1057 
   1058 template <uint64_t requestedMax, uint value>
   1059 inline constexpr uint unboundMax(BoundedConst<value>) {
   1060   // Explicitly unguard expecting a value that is at most `maxN`.
   1061   static_assert(value <= requestedMax, "overflow detected");
   1062   return value;
   1063 }
   1064 
   1065 template <uint bits, typename T>
   1066 inline constexpr auto unboundMaxBits(T value) ->
   1067     decltype(unboundMax<maxValueForBits<bits>()>(value)) {
   1068   // Explicitly unguard expecting a value that fits into `bits` bits.
   1069   return unboundMax<maxValueForBits<bits>()>(value);
   1070 }
   1071 
   1072 #define OP(op) \
   1073 template <uint64_t maxN, typename T, typename U> \
   1074 inline constexpr auto operator op(T a, SafeUnwrapper<maxN, U> b) -> decltype(a op (T)b) { \
   1075   return a op (AtLeastUInt<sizeof(T)*8>)b; \
   1076 } \
   1077 template <uint64_t maxN, typename T, typename U> \
   1078 inline constexpr auto operator op(SafeUnwrapper<maxN, U> b, T a) -> decltype((T)b op a) { \
   1079   return (AtLeastUInt<sizeof(T)*8>)b op a; \
   1080 } \
   1081 template <uint64_t value, typename T> \
   1082 inline constexpr auto operator op(T a, SafeConstUnwrapper<value> b) -> decltype(a op (T)b) { \
   1083   return a op (AtLeastUInt<sizeof(T)*8>)b; \
   1084 } \
   1085 template <uint64_t value, typename T> \
   1086 inline constexpr auto operator op(SafeConstUnwrapper<value> b, T a) -> decltype((T)b op a) { \
   1087   return (AtLeastUInt<sizeof(T)*8>)b op a; \
   1088 }
   1089 
   1090 OP(+)
   1091 OP(-)
   1092 OP(*)
   1093 OP(/)
   1094 OP(%)
   1095 OP(<<)
   1096 OP(>>)
   1097 OP(&)
   1098 OP(|)
   1099 OP(==)
   1100 OP(!=)
   1101 OP(<=)
   1102 OP(>=)
   1103 OP(<)
   1104 OP(>)
   1105 
   1106 #undef OP
   1107 
   1108 // -------------------------------------------------------------------
   1109 
   1110 template <uint64_t maxN, typename T>
   1111 class Range<Bounded<maxN, T>> {
   1112 public:
   1113   inline constexpr Range(Bounded<maxN, T> begin, Bounded<maxN, T> end)
   1114       : inner(unbound(begin), unbound(end)) {}
   1115   inline explicit constexpr Range(Bounded<maxN, T> end)
   1116       : inner(unbound(end)) {}
   1117 
   1118   class Iterator {
   1119   public:
   1120     Iterator() = default;
   1121     inline explicit Iterator(typename Range<T>::Iterator inner): inner(inner) {}
   1122 
   1123     inline Bounded<maxN, T> operator* () const { return Bounded<maxN, T>(*inner, unsafe); }
   1124     inline Iterator& operator++() { ++inner; return *this; }
   1125 
   1126     inline bool operator==(const Iterator& other) const { return inner == other.inner; }
   1127     inline bool operator!=(const Iterator& other) const { return inner != other.inner; }
   1128 
   1129   private:
   1130     typename Range<T>::Iterator inner;
   1131   };
   1132 
   1133   inline Iterator begin() const { return Iterator(inner.begin()); }
   1134   inline Iterator end() const { return Iterator(inner.end()); }
   1135 
   1136 private:
   1137   Range<T> inner;
   1138 };
   1139 
   1140 template <typename T, typename U>
   1141 class Range<Quantity<T, U>> {
   1142 public:
   1143   inline constexpr Range(Quantity<T, U> begin, Quantity<T, U> end)
   1144       : inner(begin / unit<Quantity<T, U>>(), end / unit<Quantity<T, U>>()) {}
   1145   inline explicit constexpr Range(Quantity<T, U> end)
   1146       : inner(end / unit<Quantity<T, U>>()) {}
   1147 
   1148   class Iterator {
   1149   public:
   1150     Iterator() = default;
   1151     inline explicit Iterator(typename Range<T>::Iterator inner): inner(inner) {}
   1152 
   1153     inline Quantity<T, U> operator* () const { return *inner * unit<Quantity<T, U>>(); }
   1154     inline Iterator& operator++() { ++inner; return *this; }
   1155 
   1156     inline bool operator==(const Iterator& other) const { return inner == other.inner; }
   1157     inline bool operator!=(const Iterator& other) const { return inner != other.inner; }
   1158 
   1159   private:
   1160     typename Range<T>::Iterator inner;
   1161   };
   1162 
   1163   inline Iterator begin() const { return Iterator(inner.begin()); }
   1164   inline Iterator end() const { return Iterator(inner.end()); }
   1165 
   1166 private:
   1167   Range<T> inner;
   1168 };
   1169 
   1170 template <uint value>
   1171 inline constexpr Range<Bounded<value, uint>> zeroTo(BoundedConst<value> end) {
   1172   return Range<Bounded<value, uint>>(end);
   1173 }
   1174 
   1175 template <uint value, typename Unit>
   1176 inline constexpr Range<Quantity<Bounded<value, uint>, Unit>>
   1177     zeroTo(Quantity<BoundedConst<value>, Unit> end) {
   1178   return Range<Quantity<Bounded<value, uint>, Unit>>(end);
   1179 }
   1180 
   1181 }  // namespace kj
   1182 
   1183 KJ_END_HEADER