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

// Header that should be #included by everyone.
//
// This defines very simple utilities that are widely applicable.

#pragma once

#if defined(__GNUC__) || defined(__clang__)
#define KJ_BEGIN_SYSTEM_HEADER _Pragma("GCC system_header")
#elif defined(_MSC_VER)
#define KJ_BEGIN_SYSTEM_HEADER __pragma(warning(push, 0))
#define KJ_END_SYSTEM_HEADER __pragma(warning(pop))
#endif

#ifndef KJ_BEGIN_SYSTEM_HEADER
#define KJ_BEGIN_SYSTEM_HEADER
#endif

#ifndef KJ_END_SYSTEM_HEADER
#define KJ_END_SYSTEM_HEADER
#endif

#if !defined(KJ_HEADER_WARNINGS) || !KJ_HEADER_WARNINGS
#define KJ_BEGIN_HEADER KJ_BEGIN_SYSTEM_HEADER
#define KJ_END_HEADER KJ_END_SYSTEM_HEADER
#else
#define KJ_BEGIN_HEADER
#define KJ_END_HEADER
#endif

#ifdef __has_cpp_attribute
#define KJ_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define KJ_HAS_CPP_ATTRIBUTE(x) 0
#endif

#ifdef __has_feature
#define KJ_HAS_COMPILER_FEATURE(x) __has_feature(x)
#else
#define KJ_HAS_COMPILER_FEATURE(x) 0
#endif

KJ_BEGIN_HEADER

#ifndef KJ_NO_COMPILER_CHECK
// Technically, __cplusplus should be 201402L for C++14, but GCC 4.9 -- which is supported -- still
// had it defined to 201300L even with -std=c++14.
#if __cplusplus < 201300L && !__CDT_PARSER__ && !_MSC_VER
  #error "This code requires C++14. Either your compiler does not support it or it is not enabled."
  #ifdef __GNUC__
    // Compiler claims compatibility with GCC, so presumably supports -std.
    #error "Pass -std=c++14 on the compiler command line to enable C++14."
  #endif
#endif

#ifdef __GNUC__
  #if __clang__
    #if __clang_major__ < 5
      #warning "This library requires at least Clang 5.0."
    #elif __cplusplus >= 201402L && !__has_include(<initializer_list>)
      #warning "Your compiler supports C++14 but your C++ standard library does not.  If your "\
               "system has libc++ installed (as should be the case on e.g. Mac OSX), try adding "\
               "-stdlib=libc++ to your CXXFLAGS."
    #endif
  #else
    #if __GNUC__ < 5
      #warning "This library requires at least GCC 5.0."
    #endif
  #endif
#elif defined(_MSC_VER)
  #if _MSC_VER < 1910 && !defined(__clang__)
    #error "You need Visual Studio 2017 or better to compile this code."
  #endif
#else
  #warning "I don't recognize your compiler. As of this writing, Clang, GCC, and Visual Studio "\
           "are the only known compilers with enough C++14 support for this library. "\
           "#define KJ_NO_COMPILER_CHECK to make this warning go away."
#endif
#endif

#include <stddef.h>
#include <initializer_list>

#if __linux__ && __cplusplus > 201200L
// Hack around stdlib bug with C++14 that exists on some Linux systems.
// Apparently in this mode the C library decides not to define gets() but the C++ library still
// tries to import it into the std namespace. This bug has been fixed at the source but is still
// widely present in the wild e.g. on Ubuntu 14.04.
#undef _GLIBCXX_HAVE_GETS
#endif

#if _WIN32
// Windows likes to define macros for min() and max(). We just can't deal with this.
// If windows.h was included already, undef these.
#undef min
#undef max
// If windows.h was not included yet, define the macro that prevents min() and max() from being
// defined.
#ifndef NOMINMAX
#define NOMINMAX 1
#endif
#endif

#if defined(_MSC_VER)
#include <intrin.h>  // __popcnt
#endif

// =======================================================================================

namespace kj {

typedef unsigned int uint;
typedef unsigned char byte;

// =======================================================================================
// Common macros, especially for common yet compiler-specific features.

// Detect whether RTTI and exceptions are enabled, assuming they are unless we have specific
// evidence to the contrary.  Clients can always define KJ_NO_RTTI or KJ_NO_EXCEPTIONS explicitly
// to override these checks.

// TODO: Ideally we'd use __cpp_exceptions/__cpp_rtti not being defined as the first pass since
//   that is the standard compliant way. However, it's unclear how to use those macros (or any
//   others) to distinguish between the compiler supporting feature detection and the feature being
//   disabled vs the compiler not supporting feature detection at all.
#if defined(__has_feature)
  #if !defined(KJ_NO_RTTI) && !__has_feature(cxx_rtti)
    #define KJ_NO_RTTI 1
  #endif
  #if !defined(KJ_NO_EXCEPTIONS) && !__has_feature(cxx_exceptions)
    #define KJ_NO_EXCEPTIONS 1
  #endif
#elif defined(__GNUC__)
  #if !defined(KJ_NO_RTTI) && !__GXX_RTTI
    #define KJ_NO_RTTI 1
  #endif
  #if !defined(KJ_NO_EXCEPTIONS) && !__EXCEPTIONS
    #define KJ_NO_EXCEPTIONS 1
  #endif
#elif defined(_MSC_VER)
  #if !defined(KJ_NO_RTTI) && !defined(_CPPRTTI)
    #define KJ_NO_RTTI 1
  #endif
  #if !defined(KJ_NO_EXCEPTIONS) && !defined(_CPPUNWIND)
    #define KJ_NO_EXCEPTIONS 1
  #endif
#endif

#if !defined(KJ_DEBUG) && !defined(KJ_NDEBUG)
// Heuristically decide whether to enable debug mode.  If DEBUG or NDEBUG is defined, use that.
// Otherwise, fall back to checking whether optimization is enabled.
#if defined(DEBUG) || defined(_DEBUG)
#define KJ_DEBUG
#elif defined(NDEBUG)
#define KJ_NDEBUG
#elif __OPTIMIZE__
#define KJ_NDEBUG
#else
#define KJ_DEBUG
#endif
#endif

#define KJ_DISALLOW_COPY(classname) \
  classname(const classname&) = delete; \
  classname& operator=(const classname&) = delete
// Deletes the implicit copy constructor and assignment operator.

#ifdef __GNUC__
#define KJ_LIKELY(condition) __builtin_expect(condition, true)
#define KJ_UNLIKELY(condition) __builtin_expect(condition, false)
// Branch prediction macros.  Evaluates to the condition given, but also tells the compiler that we
// expect the condition to be true/false enough of the time that it's worth hard-coding branch
// prediction.
#else
#define KJ_LIKELY(condition) (condition)
#define KJ_UNLIKELY(condition) (condition)
#endif

#if defined(KJ_DEBUG) || __NO_INLINE__
#define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__
// Don't force inline in debug mode.
#else
#if defined(_MSC_VER) && !defined(__clang__)
#define KJ_ALWAYS_INLINE(...) __forceinline __VA_ARGS__
#else
#define KJ_ALWAYS_INLINE(...) inline __VA_ARGS__ __attribute__((always_inline))
#endif
// Force a function to always be inlined.  Apply only to the prototype, not to the definition.
#endif

#if defined(_MSC_VER) && !defined(__clang__)
#define KJ_NOINLINE __declspec(noinline)
#else
#define KJ_NOINLINE __attribute__((noinline))
#endif

#if defined(_MSC_VER) && !__clang__
#define KJ_NORETURN(prototype) __declspec(noreturn) prototype
#define KJ_UNUSED
#define KJ_WARN_UNUSED_RESULT
// TODO(msvc): KJ_WARN_UNUSED_RESULT can use _Check_return_ on MSVC, but it's a prefix, so
//   wrapping the whole prototype is needed. http://msdn.microsoft.com/en-us/library/jj159529.aspx
//   Similarly, KJ_UNUSED could use __pragma(warning(suppress:...)), but again that's a prefix.
#else
#define KJ_NORETURN(prototype) prototype __attribute__((noreturn))
#define KJ_UNUSED __attribute__((unused))
#define KJ_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#endif

#if KJ_HAS_CPP_ATTRIBUTE(clang::lifetimebound)
// If this is generating too many false-positives, the user is responsible for disabling the
// problematic warning at the compiler switch level or by suppressing the place where the
// false-positive is reported through compiler-specific pragmas if available.
#define KJ_LIFETIMEBOUND [[clang::lifetimebound]]
#else
#define KJ_LIFETIMEBOUND
#endif
// Annotation that indicates the returned value is referencing a resource owned by this type (e.g.
// cStr() on a std::string). Unfortunately this lifetime can only be superficial currently & cannot
// track further. For example, there's no way to get `array.asPtr().slice(5, 6))` to warn if the
// last slice exceeds the lifetime of `array`. That's because in the general case `ArrayPtr::slice`
// can't have the lifetime bound annotation since it's not wrong to do something like:
//     ArrayPtr<char> doSomething(ArrayPtr<char> foo) {
//        ...
//        return foo.slice(5, 6);
//     }
// If `ArrayPtr::slice` had a lifetime bound then the compiler would warn about this perfectly
// legitimate method. Really there needs to be 2 more annotations. One to inherit the lifetime bound
// and another to inherit the lifetime bound from a parameter (which really could be the same thing
// by allowing a syntax like `[[clang::lifetimebound(*this)]]`.
// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound

#if __clang__
#define KJ_UNUSED_MEMBER __attribute__((unused))
// Inhibits "unused" warning for member variables.  Only Clang produces such a warning, while GCC
// complains if the attribute is set on members.
#else
#define KJ_UNUSED_MEMBER
#endif

#if __cplusplus > 201703L || (__clang__  && __clang_major__ >= 9 && __cplusplus >= 201103L)
// Technically this was only added to C++20 but Clang allows it for >= C++11 and spelunking the
// attributes manual indicates it first came in with Clang 9.
#define KJ_NO_UNIQUE_ADDRESS [[no_unique_address]]
#else
#define KJ_NO_UNIQUE_ADDRESS
#endif

#if KJ_HAS_COMPILER_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
#define KJ_DISABLE_TSAN __attribute__((no_sanitize("thread"), noinline))
#else
#define KJ_DISABLE_TSAN
#endif

#if __clang__
#define KJ_DEPRECATED(reason) \
    __attribute__((deprecated(reason)))
#define KJ_UNAVAILABLE(reason) \
    __attribute__((unavailable(reason)))
#elif __GNUC__
#define KJ_DEPRECATED(reason) \
    __attribute__((deprecated))
#define KJ_UNAVAILABLE(reason)
#else
#define KJ_DEPRECATED(reason)
#define KJ_UNAVAILABLE(reason)
// TODO(msvc): Again, here, MSVC prefers a prefix, __declspec(deprecated).
#endif

#if KJ_TESTING_KJ  // defined in KJ's own unit tests; others should not define this
#undef KJ_DEPRECATED
#define KJ_DEPRECATED(reason)
#endif

namespace _ {  // private

KJ_NORETURN(void inlineRequireFailure(
    const char* file, int line, const char* expectation, const char* macroArgs,
    const char* message = nullptr));

KJ_NORETURN(void unreachable());

}  // namespace _ (private)

#ifdef KJ_DEBUG
#if _MSC_VER && !defined(__clang__) && (!defined(_MSVC_TRADITIONAL) || _MSVC_TRADITIONAL)
#define KJ_MSVC_TRADITIONAL_CPP 1
#endif
#if KJ_MSVC_TRADITIONAL_CPP
#define KJ_IREQUIRE(condition, ...) \
    if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
        __FILE__, __LINE__, #condition, "" #__VA_ARGS__, __VA_ARGS__)
// Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users.  Used to
// check preconditions inside inline methods.  KJ_IREQUIRE is particularly useful in that
// it will be enabled depending on whether the application is compiled in debug mode rather than
// whether libkj is.
#else
#define KJ_IREQUIRE(condition, ...) \
    if (KJ_LIKELY(condition)); else ::kj::_::inlineRequireFailure( \
        __FILE__, __LINE__, #condition, #__VA_ARGS__, ##__VA_ARGS__)
// Version of KJ_DREQUIRE() which is safe to use in headers that are #included by users.  Used to
// check preconditions inside inline methods.  KJ_IREQUIRE is particularly useful in that
// it will be enabled depending on whether the application is compiled in debug mode rather than
// whether libkj is.
#endif
#else
#define KJ_IREQUIRE(condition, ...)
#endif

#define KJ_IASSERT KJ_IREQUIRE

#define KJ_UNREACHABLE ::kj::_::unreachable();
// Put this on code paths that cannot be reached to suppress compiler warnings about missing
// returns.

#if __clang__
#define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT
#else
#define KJ_CLANG_KNOWS_THIS_IS_UNREACHABLE_BUT_GCC_DOESNT KJ_UNREACHABLE
#endif

#if __clang__
#define KJ_KNOWN_UNREACHABLE(code) \
    do { \
      _Pragma("clang diagnostic push") \
      _Pragma("clang diagnostic ignored \"-Wunreachable-code\"") \
      code; \
      _Pragma("clang diagnostic pop") \
    } while (false)
// Suppress "unreachable code" warnings on intentionally unreachable code.
#else
// TODO(someday): Add support for non-clang compilers.
#define KJ_KNOWN_UNREACHABLE(code) do {code;} while(false)
#endif

#if KJ_HAS_CPP_ATTRIBUTE(fallthrough)
#define KJ_FALLTHROUGH [[fallthrough]]
#else
#define KJ_FALLTHROUGH
#endif

// #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack)
//
// Allocate an array, preferably on the stack, unless it is too big.  On GCC this will use
// variable-sized arrays.  For other compilers we could just use a fixed-size array.  `minStack`
// is the stack array size to use if variable-width arrays are not supported.  `maxStack` is the
// maximum stack array size if variable-width arrays *are* supported.
#if __GNUC__ && !__clang__
#define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
  size_t name##_size = (size); \
  bool name##_isOnStack = name##_size <= (maxStack); \
  type name##_stack[kj::max(1, name##_isOnStack ? name##_size : 0)]; \
  ::kj::Array<type> name##_heap = name##_isOnStack ? \
      nullptr : kj::heapArray<type>(name##_size); \
  ::kj::ArrayPtr<type> name = name##_isOnStack ? \
      kj::arrayPtr(name##_stack, name##_size) : name##_heap
#else
#define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
  size_t name##_size = (size); \
  bool name##_isOnStack = name##_size <= (minStack); \
  type name##_stack[minStack]; \
  ::kj::Array<type> name##_heap = name##_isOnStack ? \
      nullptr : kj::heapArray<type>(name##_size); \
  ::kj::ArrayPtr<type> name = name##_isOnStack ? \
      kj::arrayPtr(name##_stack, name##_size) : name##_heap
#endif

#define KJ_CONCAT_(x, y) x##y
#define KJ_CONCAT(x, y) KJ_CONCAT_(x, y)
#define KJ_UNIQUE_NAME(prefix) KJ_CONCAT(prefix, __LINE__)
// Create a unique identifier name.  We use concatenate __LINE__ rather than __COUNTER__ so that
// the name can be used multiple times in the same macro.

#if _MSC_VER && !defined(__clang__)

#define KJ_CONSTEXPR(...) __VA_ARGS__
// Use in cases where MSVC barfs on constexpr. A replacement keyword (e.g. "const") can be
// provided, or just leave blank to remove the keyword entirely.
//
// TODO(msvc): Remove this hack once MSVC fully supports constexpr.

#ifndef __restrict__
#define __restrict__ __restrict
// TODO(msvc): Would it be better to define a KJ_RESTRICT macro?
#endif

#pragma warning(disable: 4521 4522)
// This warning complains when there are two copy constructors, one for a const reference and
// one for a non-const reference. It is often quite necessary to do this in wrapper templates,
// therefore this warning is dumb and we disable it.

#pragma warning(disable: 4458)
// Warns when a parameter name shadows a class member. Unfortunately my code does this a lot,
// since I don't use a special name format for members.

#else  // _MSC_VER
#define KJ_CONSTEXPR(...) constexpr
#endif

// =======================================================================================
// Template metaprogramming helpers.

template <typename T> struct NoInfer_ { typedef T Type; };
template <typename T> using NoInfer = typename NoInfer_<T>::Type;
// Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
// the type based on the parameter value.

template <typename T> struct RemoveConst_ { typedef T Type; };
template <typename T> struct RemoveConst_<const T> { typedef T Type; };
template <typename T> using RemoveConst = typename RemoveConst_<T>::Type;

template <typename> struct IsLvalueReference_ { static constexpr bool value = false; };
template <typename T> struct IsLvalueReference_<T&> { static constexpr bool value = true; };
template <typename T>
inline constexpr bool isLvalueReference() { return IsLvalueReference_<T>::value; }

template <typename T> struct Decay_ { typedef T Type; };
template <typename T> struct Decay_<T&> { typedef typename Decay_<T>::Type Type; };
template <typename T> struct Decay_<T&&> { typedef typename Decay_<T>::Type Type; };
template <typename T> struct Decay_<T[]> { typedef typename Decay_<T*>::Type Type; };
template <typename T> struct Decay_<const T[]> { typedef typename Decay_<const T*>::Type Type; };
template <typename T, size_t s> struct Decay_<T[s]> { typedef typename Decay_<T*>::Type Type; };
template <typename T, size_t s> struct Decay_<const T[s]> { typedef typename Decay_<const T*>::Type Type; };
template <typename T> struct Decay_<const T> { typedef typename Decay_<T>::Type Type; };
template <typename T> struct Decay_<volatile T> { typedef typename Decay_<T>::Type Type; };
template <typename T> using Decay = typename Decay_<T>::Type;

template <bool b> struct EnableIf_;
template <> struct EnableIf_<true> { typedef void Type; };
template <bool b> using EnableIf = typename EnableIf_<b>::Type;
// Use like:
//
//     template <typename T, typename = EnableIf<isValid<T>()>>
//     void func(T&& t);

template <typename...> struct VoidSfinae_ { using Type = void; };
template <typename... Ts> using VoidSfinae = typename VoidSfinae_<Ts...>::Type;
// Note: VoidSfinae is std::void_t from C++17.

template <typename T>
T instance() noexcept;
// Like std::declval, but doesn't transform T into an rvalue reference.  If you want that, specify
// instance<T&&>().

struct DisallowConstCopy {
  // Inherit from this, or declare a member variable of this type, to prevent the class from being
  // copyable from a const reference -- instead, it will only be copyable from non-const references.
  // This is useful for enforcing transitive constness of contained pointers.
  //
  // For example, say you have a type T which contains a pointer.  T has non-const methods which
  // modify the value at that pointer, but T's const methods are designed to allow reading only.
  // Unfortunately, if T has a regular copy constructor, someone can simply make a copy of T and
  // then use it to modify the pointed-to value.  However, if T inherits DisallowConstCopy, then
  // callers will only be able to copy non-const instances of T.  Ideally, there is some
  // parallel type ImmutableT which is like a version of T that only has const methods, and can
  // be copied from a const T.
  //
  // Note that due to C++ rules about implicit copy constructors and assignment operators, any
  // type that contains or inherits from a type that disallows const copies will also automatically
  // disallow const copies.  Hey, cool, that's exactly what we want.

#if CAPNP_DEBUG_TYPES
  // Alas! Declaring a defaulted non-const copy constructor tickles a bug which causes GCC and
  // Clang to disagree on ABI, using different calling conventions to pass this type, leading to
  // immediate segfaults. See:
  //     https://bugs.llvm.org/show_bug.cgi?id=23764
  //     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58074
  //
  // Because of this, we can't use this technique. We guard it by CAPNP_DEBUG_TYPES so that it
  // still applies to the Cap'n Proto developers during internal testing.

  DisallowConstCopy() = default;
  DisallowConstCopy(DisallowConstCopy&) = default;
  DisallowConstCopy(DisallowConstCopy&&) = default;
  DisallowConstCopy& operator=(DisallowConstCopy&) = default;
  DisallowConstCopy& operator=(DisallowConstCopy&&) = default;
#endif
};

#if _MSC_VER && !defined(__clang__)

#define KJ_CPCAP(obj) obj=::kj::cp(obj)
// TODO(msvc): MSVC refuses to invoke non-const versions of copy constructors in by-value lambda
// captures. Wrap your captured object in this macro to force the compiler to perform a copy.
// Example:
//
//   struct Foo: DisallowConstCopy {};
//   Foo foo;
//   auto lambda = [KJ_CPCAP(foo)] {};

#else

#define KJ_CPCAP(obj) obj
// Clang and gcc both already perform copy capturing correctly with non-const copy constructors.

#endif

template <typename T>
struct DisallowConstCopyIfNotConst: public DisallowConstCopy {
  // Inherit from this when implementing a template that contains a pointer to T and which should
  // enforce transitive constness.  If T is a const type, this has no effect.  Otherwise, it is
  // an alias for DisallowConstCopy.
};

template <typename T>
struct DisallowConstCopyIfNotConst<const T> {};

template <typename T> struct IsConst_ { static constexpr bool value = false; };
template <typename T> struct IsConst_<const T> { static constexpr bool value = true; };
template <typename T> constexpr bool isConst() { return IsConst_<T>::value; }

template <typename T> struct EnableIfNotConst_ { typedef T Type; };
template <typename T> struct EnableIfNotConst_<const T>;
template <typename T> using EnableIfNotConst = typename EnableIfNotConst_<T>::Type;

template <typename T> struct EnableIfConst_;
template <typename T> struct EnableIfConst_<const T> { typedef T Type; };
template <typename T> using EnableIfConst = typename EnableIfConst_<T>::Type;

template <typename T> struct RemoveConstOrDisable_ { struct Type; };
template <typename T> struct RemoveConstOrDisable_<const T> { typedef T Type; };
template <typename T> using RemoveConstOrDisable = typename RemoveConstOrDisable_<T>::Type;

template <typename T> struct IsReference_ { static constexpr bool value = false; };
template <typename T> struct IsReference_<T&> { static constexpr bool value = true; };
template <typename T> constexpr bool isReference() { return IsReference_<T>::value; }

template <typename From, typename To>
struct PropagateConst_ { typedef To Type; };
template <typename From, typename To>
struct PropagateConst_<const From, To> { typedef const To Type; };
template <typename From, typename To>
using PropagateConst = typename PropagateConst_<From, To>::Type;

namespace _ {  // private

template <typename T>
T refIfLvalue(T&&);

}  // namespace _ (private)

#define KJ_DECLTYPE_REF(exp) decltype(::kj::_::refIfLvalue(exp))
// Like decltype(exp), but if exp is an lvalue, produces a reference type.
//
//     int i;
//     decltype(i) i1(i);                         // i1 has type int.
//     KJ_DECLTYPE_REF(i + 1) i2(i + 1);          // i2 has type int.
//     KJ_DECLTYPE_REF(i) i3(i);                  // i3 has type int&.
//     KJ_DECLTYPE_REF(kj::mv(i)) i4(kj::mv(i));  // i4 has type int.

template <typename T, typename U> struct IsSameType_ { static constexpr bool value = false; };
template <typename T> struct IsSameType_<T, T> { static constexpr bool value = true; };
template <typename T, typename U> constexpr bool isSameType() { return IsSameType_<T, U>::value; }

template <typename T>
struct CanConvert_ {
  static int sfinae(T);
  static bool sfinae(...);
};

template <typename T, typename U>
constexpr bool canConvert() {
  return sizeof(CanConvert_<U>::sfinae(instance<T>())) == sizeof(int);
}

#if __GNUC__ && !__clang__ && __GNUC__ < 5
template <typename T>
constexpr bool canMemcpy() {
  // Returns true if T can be copied using memcpy instead of using the copy constructor or
  // assignment operator.

  // GCC 4 does not have __is_trivially_constructible and friends, and there doesn't seem to be
  // any reliable alternative. __has_trivial_copy() and __has_trivial_assign() return the right
  // thing at one point but later on they changed such that a deleted copy constructor was
  // considered "trivial" (apparently technically correct, though useless). So, on GCC 4 we give up
  // and assume we can't memcpy() at all, and must explicitly copy-construct everything.
  return false;
}
#define KJ_ASSERT_CAN_MEMCPY(T)
#else
template <typename T>
constexpr bool canMemcpy() {
  // Returns true if T can be copied using memcpy instead of using the copy constructor or
  // assignment operator.

  return __is_trivially_constructible(T, const T&) && __is_trivially_assignable(T, const T&);
}
#define KJ_ASSERT_CAN_MEMCPY(T) \
  static_assert(kj::canMemcpy<T>(), "this code expects this type to be memcpy()-able");
#endif

template <typename T>
class Badge {
  // A pattern for marking individual methods such that they can only be called from a specific
  // caller class: Make the method public but give it a parameter of type `Badge<Caller>`. Only
  // `Caller` can construct one, so only `Caller` can call the method.
  //
  //     // We only allow calls from the class `Bar`.
  //     void foo(Badge<Bar>)
  //
  // The call site looks like:
  //
  //     foo({});
  //
  // This pattern also works well for declaring private constructors, but still being able to use
  // them with `kj::heap()`, etc.
  //
  // Idea from: https://awesomekling.github.io/Serenity-C++-patterns-The-Badge/
  //
  // Note that some forms of this idea make the copy constructor private as well, in order to
  // prohibit `Badge<NotMe>(*(Badge<NotMe>*)nullptr)`. However, that would prevent badges from
  // being passed through forwarding functions like `kj::heap()`, which would ruin one of the main
  // use cases for this pattern in KJ. In any case, dereferencing a null pointer is UB; there are
  // plenty of other ways to get access to private members if you're willing to go UB. For one-off
  // debugging purposes, you might as well use `#define private public` at the top of the file.
private:
  Badge() {}
  friend T;
};

// =======================================================================================
// Equivalents to std::move() and std::forward(), since these are very commonly needed and the
// std header <utility> pulls in lots of other stuff.
//
// We use abbreviated names mv and fwd because these helpers (especially mv) are so commonly used
// that the cost of typing more letters outweighs the cost of being slightly harder to understand
// when first encountered.

template<typename T> constexpr T&& mv(T& t) noexcept { return static_cast<T&&>(t); }
template<typename T> constexpr T&& fwd(NoInfer<T>& t) noexcept { return static_cast<T&&>(t); }

template<typename T> constexpr T cp(T& t) noexcept { return t; }
template<typename T> constexpr T cp(const T& t) noexcept { return t; }
// Useful to force a copy, particularly to pass into a function that expects T&&.

template <typename T, typename U, bool takeT, bool uOK = true> struct ChooseType_;
template <typename T, typename U> struct ChooseType_<T, U, true, true> { typedef T Type; };
template <typename T, typename U> struct ChooseType_<T, U, true, false> { typedef T Type; };
template <typename T, typename U> struct ChooseType_<T, U, false, true> { typedef U Type; };

template <typename T, typename U>
using WiderType = typename ChooseType_<T, U, sizeof(T) >= sizeof(U)>::Type;

template <typename T, typename U>
inline constexpr auto min(T&& a, U&& b) -> WiderType<Decay<T>, Decay<U>> {
  return a < b ? WiderType<Decay<T>, Decay<U>>(a) : WiderType<Decay<T>, Decay<U>>(b);
}

template <typename T, typename U>
inline constexpr auto max(T&& a, U&& b) -> WiderType<Decay<T>, Decay<U>> {
  return a > b ? WiderType<Decay<T>, Decay<U>>(a) : WiderType<Decay<T>, Decay<U>>(b);
}

template <typename T, size_t s>
inline constexpr size_t size(T (&arr)[s]) { return s; }
template <typename T>
inline constexpr size_t size(T&& arr) { return arr.size(); }
// Returns the size of the parameter, whether the parameter is a regular C array or a container
// with a `.size()` method.

class MaxValue_ {
private:
  template <typename T>
  inline constexpr T maxSigned() const {
    return (1ull << (sizeof(T) * 8 - 1)) - 1;
  }
  template <typename T>
  inline constexpr T maxUnsigned() const {
    return ~static_cast<T>(0u);
  }

public:
#define _kJ_HANDLE_TYPE(T) \
  inline constexpr operator   signed T() const { return MaxValue_::maxSigned  <  signed T>(); } \
  inline constexpr operator unsigned T() const { return MaxValue_::maxUnsigned<unsigned T>(); }
  _kJ_HANDLE_TYPE(char)
  _kJ_HANDLE_TYPE(short)
  _kJ_HANDLE_TYPE(int)
  _kJ_HANDLE_TYPE(long)
  _kJ_HANDLE_TYPE(long long)
#undef _kJ_HANDLE_TYPE

  inline constexpr operator char() const {
    // `char` is different from both `signed char` and `unsigned char`, and may be signed or
    // unsigned on different platforms.  Ugh.
    return char(-1) < 0 ? MaxValue_::maxSigned<char>()
                        : MaxValue_::maxUnsigned<char>();
  }
};

class MinValue_ {
private:
  template <typename T>
  inline constexpr T minSigned() const {
    return 1ull << (sizeof(T) * 8 - 1);
  }
  template <typename T>
  inline constexpr T minUnsigned() const {
    return 0u;
  }

public:
#define _kJ_HANDLE_TYPE(T) \
  inline constexpr operator   signed T() const { return MinValue_::minSigned  <  signed T>(); } \
  inline constexpr operator unsigned T() const { return MinValue_::minUnsigned<unsigned T>(); }
  _kJ_HANDLE_TYPE(char)
  _kJ_HANDLE_TYPE(short)
  _kJ_HANDLE_TYPE(int)
  _kJ_HANDLE_TYPE(long)
  _kJ_HANDLE_TYPE(long long)
#undef _kJ_HANDLE_TYPE

  inline constexpr operator char() const {
    // `char` is different from both `signed char` and `unsigned char`, and may be signed or
    // unsigned on different platforms.  Ugh.
    return char(-1) < 0 ? MinValue_::minSigned<char>()
                        : MinValue_::minUnsigned<char>();
  }
};

static KJ_CONSTEXPR(const) MaxValue_ maxValue = MaxValue_();
// A special constant which, when cast to an integer type, takes on the maximum possible value of
// that type.  This is useful to use as e.g. a parameter to a function because it will be robust
// in the face of changes to the parameter's type.
//
// `char` is not supported, but `signed char` and `unsigned char` are.

static KJ_CONSTEXPR(const) MinValue_ minValue = MinValue_();
// A special constant which, when cast to an integer type, takes on the minimum possible value
// of that type.  This is useful to use as e.g. a parameter to a function because it will be robust
// in the face of changes to the parameter's type.
//
// `char` is not supported, but `signed char` and `unsigned char` are.

template <typename T>
inline bool operator==(T t, MaxValue_) { return t == Decay<T>(maxValue); }
template <typename T>
inline bool operator==(T t, MinValue_) { return t == Decay<T>(minValue); }

template <uint bits>
inline constexpr unsigned long long maxValueForBits() {
  // Get the maximum integer representable in the given number of bits.

  // 1ull << 64 is unfortunately undefined.
  return (bits == 64 ? 0 : (1ull << bits)) - 1;
}

struct ThrowOverflow {
  // Functor which throws an exception complaining about integer overflow. Usually this is used
  // with the interfaces in units.h, but is defined here because Cap'n Proto wants to avoid
  // including units.h when not using CAPNP_DEBUG_TYPES.
  [[noreturn]] void operator()() const;
};

#if __GNUC__ || __clang__ || _MSC_VER
inline constexpr float inf() { return __builtin_huge_valf(); }
inline constexpr float nan() { return __builtin_nanf(""); }

#else
#error "Not sure how to support your compiler."
#endif

inline constexpr bool isNaN(float f) { return f != f; }
inline constexpr bool isNaN(double f) { return f != f; }

inline int popCount(unsigned int x) {
#if defined(_MSC_VER) && !defined(__clang__)
  return __popcnt(x);
  // Note: __popcnt returns unsigned int, but the value is clearly guaranteed to fit into an int
#else
  return __builtin_popcount(x);
#endif
}

// =======================================================================================
// Useful fake containers

template <typename T>
class Range {
public:
  inline constexpr Range(const T& begin, const T& end): begin_(begin), end_(end) {}
  inline explicit constexpr Range(const T& end): begin_(0), end_(end) {}

  class Iterator {
  public:
    Iterator() = default;
    inline Iterator(const T& value): value(value) {}

    inline const T&  operator* () const { return value; }
    inline const T&  operator[](size_t index) const { return value + index; }
    inline Iterator& operator++() { ++value; return *this; }
    inline Iterator  operator++(int) { return Iterator(value++); }
    inline Iterator& operator--() { --value; return *this; }
    inline Iterator  operator--(int) { return Iterator(value--); }
    inline Iterator& operator+=(ptrdiff_t amount) { value += amount; return *this; }
    inline Iterator& operator-=(ptrdiff_t amount) { value -= amount; return *this; }
    inline Iterator  operator+ (ptrdiff_t amount) const { return Iterator(value + amount); }
    inline Iterator  operator- (ptrdiff_t amount) const { return Iterator(value - amount); }
    inline ptrdiff_t operator- (const Iterator& other) const { return value - other.value; }

    inline bool operator==(const Iterator& other) const { return value == other.value; }
    inline bool operator!=(const Iterator& other) const { return value != other.value; }
    inline bool operator<=(const Iterator& other) const { return value <= other.value; }
    inline bool operator>=(const Iterator& other) const { return value >= other.value; }
    inline bool operator< (const Iterator& other) const { return value <  other.value; }
    inline bool operator> (const Iterator& other) const { return value >  other.value; }

  private:
    T value;
  };

  inline Iterator begin() const { return Iterator(begin_); }
  inline Iterator end() const { return Iterator(end_); }

  inline auto size() const -> decltype(instance<T>() - instance<T>()) { return end_ - begin_; }

private:
  T begin_;
  T end_;
};

template <typename T, typename U>
inline constexpr Range<WiderType<Decay<T>, Decay<U>>> range(T begin, U end) {
  return Range<WiderType<Decay<T>, Decay<U>>>(begin, end);
}

template <typename T>
inline constexpr Range<Decay<T>> range(T begin, T end) { return Range<Decay<T>>(begin, end); }
// Returns a fake iterable container containing all values of T from `begin` (inclusive) to `end`
// (exclusive).  Example:
//
//     // Prints 1, 2, 3, 4, 5, 6, 7, 8, 9.
//     for (int i: kj::range(1, 10)) { print(i); }

template <typename T>
inline constexpr Range<Decay<T>> zeroTo(T end) { return Range<Decay<T>>(end); }
// Returns a fake iterable container containing all values of T from zero (inclusive) to `end`
// (exclusive).  Example:
//
//     // Prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
//     for (int i: kj::zeroTo(10)) { print(i); }

template <typename T>
inline constexpr Range<size_t> indices(T&& container) {
  // Shortcut for iterating over the indices of a container:
  //
  //     for (size_t i: kj::indices(myArray)) { handle(myArray[i]); }

  return range<size_t>(0, kj::size(container));
}

template <typename T>
class Repeat {
public:
  inline constexpr Repeat(const T& value, size_t count): value(value), count(count) {}

  class Iterator {
  public:
    Iterator() = default;
    inline Iterator(const T& value, size_t index): value(value), index(index) {}

    inline const T&  operator* () const { return value; }
    inline const T&  operator[](ptrdiff_t index) const { return value; }
    inline Iterator& operator++() { ++index; return *this; }
    inline Iterator  operator++(int) { return Iterator(value, index++); }
    inline Iterator& operator--() { --index; return *this; }
    inline Iterator  operator--(int) { return Iterator(value, index--); }
    inline Iterator& operator+=(ptrdiff_t amount) { index += amount; return *this; }
    inline Iterator& operator-=(ptrdiff_t amount) { index -= amount; return *this; }
    inline Iterator  operator+ (ptrdiff_t amount) const { return Iterator(value, index + amount); }
    inline Iterator  operator- (ptrdiff_t amount) const { return Iterator(value, index - amount); }
    inline ptrdiff_t operator- (const Iterator& other) const { return index - other.index; }

    inline bool operator==(const Iterator& other) const { return index == other.index; }
    inline bool operator!=(const Iterator& other) const { return index != other.index; }
    inline bool operator<=(const Iterator& other) const { return index <= other.index; }
    inline bool operator>=(const Iterator& other) const { return index >= other.index; }
    inline bool operator< (const Iterator& other) const { return index <  other.index; }
    inline bool operator> (const Iterator& other) const { return index >  other.index; }

  private:
    T value;
    size_t index;
  };

  inline Iterator begin() const { return Iterator(value, 0); }
  inline Iterator end() const { return Iterator(value, count); }

  inline size_t size() const { return count; }
  inline const T& operator[](ptrdiff_t) const { return value; }

private:
  T value;
  size_t count;
};

template <typename T>
inline constexpr Repeat<Decay<T>> repeat(T&& value, size_t count) {
  // Returns a fake iterable which contains `count` repeats of `value`.  Useful for e.g. creating
  // a bunch of spaces:  `kj::repeat(' ', indent * 2)`

  return Repeat<Decay<T>>(value, count);
}

template <typename Inner, class Mapping>
class MappedIterator: private Mapping {
  // An iterator that wraps some other iterator and maps the values through a mapping function.
  // The type `Mapping` must define a method `map()` which performs this mapping.

public:
  template <typename... Params>
  MappedIterator(Inner inner, Params&&... params)
      : Mapping(kj::fwd<Params>(params)...), inner(inner) {}

  inline auto operator->() const { return &Mapping::map(*inner); }
  inline decltype(auto) operator* () const { return Mapping::map(*inner); }
  inline decltype(auto) operator[](size_t index) const { return Mapping::map(inner[index]); }
  inline MappedIterator& operator++() { ++inner; return *this; }
  inline MappedIterator  operator++(int) { return MappedIterator(inner++, *this); }
  inline MappedIterator& operator--() { --inner; return *this; }
  inline MappedIterator  operator--(int) { return MappedIterator(inner--, *this); }
  inline MappedIterator& operator+=(ptrdiff_t amount) { inner += amount; return *this; }
  inline MappedIterator& operator-=(ptrdiff_t amount) { inner -= amount; return *this; }
  inline MappedIterator  operator+ (ptrdiff_t amount) const {
    return MappedIterator(inner + amount, *this);
  }
  inline MappedIterator  operator- (ptrdiff_t amount) const {
    return MappedIterator(inner - amount, *this);
  }
  inline ptrdiff_t operator- (const MappedIterator& other) const { return inner - other.inner; }

  inline bool operator==(const MappedIterator& other) const { return inner == other.inner; }
  inline bool operator!=(const MappedIterator& other) const { return inner != other.inner; }
  inline bool operator<=(const MappedIterator& other) const { return inner <= other.inner; }
  inline bool operator>=(const MappedIterator& other) const { return inner >= other.inner; }
  inline bool operator< (const MappedIterator& other) const { return inner <  other.inner; }
  inline bool operator> (const MappedIterator& other) const { return inner >  other.inner; }

private:
  Inner inner;
};

template <typename Inner, typename Mapping>
class MappedIterable: private Mapping {
  // An iterable that wraps some other iterable and maps the values through a mapping function.
  // The type `Mapping` must define a method `map()` which performs this mapping.

public:
  template <typename... Params>
  MappedIterable(Inner inner, Params&&... params)
      : Mapping(kj::fwd<Params>(params)...), inner(inner) {}

  typedef Decay<decltype(instance<Inner>().begin())> InnerIterator;
  typedef MappedIterator<InnerIterator, Mapping> Iterator;
  typedef Decay<decltype(instance<const Inner>().begin())> InnerConstIterator;
  typedef MappedIterator<InnerConstIterator, Mapping> ConstIterator;

  inline Iterator begin() { return { inner.begin(), (Mapping&)*this }; }
  inline Iterator end() { return { inner.end(), (Mapping&)*this }; }
  inline ConstIterator begin() const { return { inner.begin(), (const Mapping&)*this }; }
  inline ConstIterator end() const { return { inner.end(), (const Mapping&)*this }; }

private:
  Inner inner;
};

// =======================================================================================
// Manually invoking constructors and destructors
//
// ctor(x, ...) and dtor(x) invoke x's constructor or destructor, respectively.

// We want placement new, but we don't want to #include <new>.  operator new cannot be defined in
// a namespace, and defining it globally conflicts with the definition in <new>.  So we have to
// define a dummy type and an operator new that uses it.

namespace _ {  // private
struct PlacementNew {};
}  // namespace _ (private)
} // namespace kj

inline void* operator new(size_t, kj::_::PlacementNew, void* __p) noexcept {
  return __p;
}

inline void operator delete(void*, kj::_::PlacementNew, void* __p) noexcept {}

namespace kj {

template <typename T, typename... Params>
inline void ctor(T& location, Params&&... params) {
  new (_::PlacementNew(), &location) T(kj::fwd<Params>(params)...);
}

template <typename T>
inline void dtor(T& location) {
  location.~T();
}

// =======================================================================================
// Maybe
//
// Use in cases where you want to indicate that a value may be null.  Using Maybe<T&> instead of T*
// forces the caller to handle the null case in order to satisfy the compiler, thus reliably
// preventing null pointer dereferences at runtime.
//
// Maybe<T> can be implicitly constructed from T and from nullptr.
// To read the value of a Maybe<T>, do:
//
//    KJ_IF_MAYBE(value, someFuncReturningMaybe()) {
//      doSomething(*value);
//    } else {
//      maybeWasNull();
//    }
//
// KJ_IF_MAYBE's first parameter is a variable name which will be defined within the following
// block.  The variable will behave like a (guaranteed non-null) pointer to the Maybe's value,
// though it may or may not actually be a pointer.
//
// Note that Maybe<T&> actually just wraps a pointer, whereas Maybe<T> wraps a T and a boolean
// indicating nullness.

template <typename T>
class Maybe;

namespace _ {  // private

template <typename T>
class NullableValue {
  // Class whose interface behaves much like T*, but actually contains an instance of T and a
  // boolean flag indicating nullness.

public:
  inline NullableValue(NullableValue&& other)
      : isSet(other.isSet) {
    if (isSet) {
      ctor(value, kj::mv(other.value));
    }
  }
  inline NullableValue(const NullableValue& other)
      : isSet(other.isSet) {
    if (isSet) {
      ctor(value, other.value);
    }
  }
  inline NullableValue(NullableValue& other)
      : isSet(other.isSet) {
    if (isSet) {
      ctor(value, other.value);
    }
  }
  inline ~NullableValue()
#if _MSC_VER && !defined(__clang__)
      // TODO(msvc): MSVC has a hard time with noexcept specifier expressions that are more complex
      //   than `true` or `false`. We had a workaround for VS2015, but VS2017 regressed.
      noexcept(false)
#else
      noexcept(noexcept(instance<T&>().~T()))
#endif
  {
    if (isSet) {
      dtor(value);
    }
  }

  inline T& operator*() & { return value; }
  inline const T& operator*() const & { return value; }
  inline T&& operator*() && { return kj::mv(value); }
  inline const T&& operator*() const && { return kj::mv(value); }
  inline T* operator->() { return &value; }
  inline const T* operator->() const { return &value; }
  inline operator T*() { return isSet ? &value : nullptr; }
  inline operator const T*() const { return isSet ? &value : nullptr; }

  template <typename... Params>
  inline T& emplace(Params&&... params) {
    if (isSet) {
      isSet = false;
      dtor(value);
    }
    ctor(value, kj::fwd<Params>(params)...);
    isSet = true;
    return value;
  }

  inline NullableValue(): isSet(false) {}
  inline NullableValue(T&& t)
      : isSet(true) {
    ctor(value, kj::mv(t));
  }
  inline NullableValue(T& t)
      : isSet(true) {
    ctor(value, t);
  }
  inline NullableValue(const T& t)
      : isSet(true) {
    ctor(value, t);
  }
  template <typename U>
  inline NullableValue(NullableValue<U>&& other)
      : isSet(other.isSet) {
    if (isSet) {
      ctor(value, kj::mv(other.value));
    }
  }
  template <typename U>
  inline NullableValue(const NullableValue<U>& other)
      : isSet(other.isSet) {
    if (isSet) {
      ctor(value, other.value);
    }
  }
  template <typename U>
  inline NullableValue(const NullableValue<U&>& other)
      : isSet(other.isSet) {
    if (isSet) {
      ctor(value, *other.ptr);
    }
  }
  inline NullableValue(decltype(nullptr)): isSet(false) {}

  inline NullableValue& operator=(NullableValue&& other) {
    if (&other != this) {
      // Careful about throwing destructors/constructors here.
      if (isSet) {
        isSet = false;
        dtor(value);
      }
      if (other.isSet) {
        ctor(value, kj::mv(other.value));
        isSet = true;
      }
    }
    return *this;
  }

  inline NullableValue& operator=(NullableValue& other) {
    if (&other != this) {
      // Careful about throwing destructors/constructors here.
      if (isSet) {
        isSet = false;
        dtor(value);
      }
      if (other.isSet) {
        ctor(value, other.value);
        isSet = true;
      }
    }
    return *this;
  }

  inline NullableValue& operator=(const NullableValue& other) {
    if (&other != this) {
      // Careful about throwing destructors/constructors here.
      if (isSet) {
        isSet = false;
        dtor(value);
      }
      if (other.isSet) {
        ctor(value, other.value);
        isSet = true;
      }
    }
    return *this;
  }

  inline NullableValue& operator=(T&& other) { emplace(kj::mv(other)); return *this; }
  inline NullableValue& operator=(T& other) { emplace(other); return *this; }
  inline NullableValue& operator=(const T& other) { emplace(other); return *this; }
  template <typename U>
  inline NullableValue& operator=(NullableValue<U>&& other) {
    if (other.isSet) {
      emplace(kj::mv(other.value));
    } else {
      *this = nullptr;
    }
    return *this;
  }
  template <typename U>
  inline NullableValue& operator=(const NullableValue<U>& other) {
    if (other.isSet) {
      emplace(other.value);
    } else {
      *this = nullptr;
    }
    return *this;
  }
  template <typename U>
  inline NullableValue& operator=(const NullableValue<U&>& other) {
    if (other.isSet) {
      emplace(other.value);
    } else {
      *this = nullptr;
    }
    return *this;
  }
  inline NullableValue& operator=(decltype(nullptr)) {
    if (isSet) {
      isSet = false;
      dtor(value);
    }
    return *this;
  }

  inline bool operator==(decltype(nullptr)) const { return !isSet; }
  inline bool operator!=(decltype(nullptr)) const { return isSet; }

  NullableValue(const T* t) = delete;
  NullableValue& operator=(const T* other) = delete;
  // We used to permit assigning a Maybe<T> directly from a T*, and the assignment would check for
  // nullness. This turned out never to be useful, and sometimes to be dangerous.

private:
  bool isSet;

#if _MSC_VER && !defined(__clang__)
#pragma warning(push)
#pragma warning(disable: 4624)
// Warns that the anonymous union has a deleted destructor when T is non-trivial. This warning
// seems broken.
#endif

  union {
    T value;
  };

#if _MSC_VER && !defined(__clang__)
#pragma warning(pop)
#endif

  friend class kj::Maybe<T>;
  template <typename U>
  friend NullableValue<U>&& readMaybe(Maybe<U>&& maybe);
};

template <typename T>
inline NullableValue<T>&& readMaybe(Maybe<T>&& maybe) { return kj::mv(maybe.ptr); }
template <typename T>
inline T* readMaybe(Maybe<T>& maybe) { return maybe.ptr; }
template <typename T>
inline const T* readMaybe(const Maybe<T>& maybe) { return maybe.ptr; }
template <typename T>
inline T* readMaybe(Maybe<T&>&& maybe) { return maybe.ptr; }
template <typename T>
inline T* readMaybe(const Maybe<T&>& maybe) { return maybe.ptr; }

template <typename T>
inline T* readMaybe(T* ptr) { return ptr; }
// Allow KJ_IF_MAYBE to work on regular pointers.

}  // namespace _ (private)

#define KJ_IF_MAYBE(name, exp) if (auto name = ::kj::_::readMaybe(exp))

#if __GNUC__
// These two macros provide a friendly syntax to extract the value of a Maybe or return early.
//
// Use KJ_UNWRAP_OR_RETURN if you just want to return a simple value when the Maybe is null:
//
//     int foo(Maybe<int> maybe) {
//       int value = KJ_UNWRAP_OR_RETURN(maybe, -1);
//       // ... use value ...
//     }
//
// For functions returning void, omit the second parameter to KJ_UNWRAP_OR_RETURN:
//
//     void foo(Maybe<int> maybe) {
//       int value = KJ_UNWRAP_OR_RETURN(maybe);
//       // ... use value ...
//     }
//
// Use KJ_UNWRAP_OR if you want to execute a block with multiple statements.
//
//     int foo(Maybe<int> maybe) {
//       int value = KJ_UNWRAP_OR(maybe, {
//         KJ_LOG(ERROR, "problem!!!");
//         return -1;
//       });
//       // ... use value ...
//     }
//
// The block MUST return at the end or you will get a compiler error
//
// Unfortunately, these macros seem impossible to express without using GCC's non-standard
// "statement expressions" extension. IIFEs don't do the trick here because a lambda cannot
// return out of the parent scope. These macros should therefore only be used in projects that
// target GCC or GCC-compatible compilers.

#define KJ_UNWRAP_OR_RETURN(value, ...) \
  (*({ \
    auto _kj_result = ::kj::_::readMaybe(value); \
    if (!_kj_result) { \
      return __VA_ARGS__; \
    } \
    kj::mv(_kj_result); \
  }))

#define KJ_UNWRAP_OR(value, block) \
  (*({ \
    auto _kj_result = ::kj::_::readMaybe(value); \
    if (!_kj_result) { \
      block; \
      asm("KJ_UNWRAP_OR_block_is_missing_return_statement\n"); \
    } \
    kj::mv(_kj_result); \
  }))
#endif

template <typename T>
class Maybe {
  // A T, or nullptr.

  // IF YOU CHANGE THIS CLASS:  Note that there is a specialization of it in memory.h.

public:
  Maybe(): ptr(nullptr) {}
  Maybe(T&& t): ptr(kj::mv(t)) {}
  Maybe(T& t): ptr(t) {}
  Maybe(const T& t): ptr(t) {}
  Maybe(Maybe&& other): ptr(kj::mv(other.ptr)) { other = nullptr; }
  Maybe(const Maybe& other): ptr(other.ptr) {}
  Maybe(Maybe& other): ptr(other.ptr) {}

  template <typename U>
  Maybe(Maybe<U>&& other) {
    KJ_IF_MAYBE(val, kj::mv(other)) {
      ptr.emplace(kj::mv(*val));
      other = nullptr;
    }
  }
  template <typename U>
  Maybe(Maybe<U&>&& other) {
    KJ_IF_MAYBE(val, other) {
      ptr.emplace(*val);
      other = nullptr;
    }
  }
  template <typename U>
  Maybe(const Maybe<U>& other) {
    KJ_IF_MAYBE(val, other) {
      ptr.emplace(*val);
    }
  }

  Maybe(decltype(nullptr)): ptr(nullptr) {}

  template <typename... Params>
  inline T& emplace(Params&&... params) {
    // Replace this Maybe's content with a new value constructed by passing the given parameters to
    // T's constructor. This can be used to initialize a Maybe without copying or even moving a T.
    // Returns a reference to the newly-constructed value.

    return ptr.emplace(kj::fwd<Params>(params)...);
  }

  inline Maybe& operator=(T&& other) { ptr = kj::mv(other); return *this; }
  inline Maybe& operator=(T& other) { ptr = other; return *this; }
  inline Maybe& operator=(const T& other) { ptr = other; return *this; }

  inline Maybe& operator=(Maybe&& other) { ptr = kj::mv(other.ptr); other = nullptr; return *this; }
  inline Maybe& operator=(Maybe& other) { ptr = other.ptr; return *this; }
  inline Maybe& operator=(const Maybe& other) { ptr = other.ptr; return *this; }

  template <typename U>
  Maybe& operator=(Maybe<U>&& other) {
    KJ_IF_MAYBE(val, kj::mv(other)) {
      ptr.emplace(kj::mv(*val));
      other = nullptr;
    } else {
      ptr = nullptr;
    }
    return *this;
  }
  template <typename U>
  Maybe& operator=(const Maybe<U>& other) {
    KJ_IF_MAYBE(val, other) {
      ptr.emplace(*val);
    } else {
      ptr = nullptr;
    }
    return *this;
  }

  inline Maybe& operator=(decltype(nullptr)) { ptr = nullptr; return *this; }

  inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
  inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }

  inline bool operator==(const Maybe<T>& other) const {
    if (ptr == nullptr) {
      return other == nullptr;
    } else {
      return other.ptr != nullptr && *ptr == *other.ptr;
    }
  }
  inline bool operator!=(const Maybe<T>& other) const { return !(*this == other); }

  Maybe(const T* t) = delete;
  Maybe& operator=(const T* other) = delete;
  // We used to permit assigning a Maybe<T> directly from a T*, and the assignment would check for
  // nullness. This turned out never to be useful, and sometimes to be dangerous.

  T& orDefault(T& defaultValue) & {
    if (ptr == nullptr) {
      return defaultValue;
    } else {
      return *ptr;
    }
  }
  const T& orDefault(const T& defaultValue) const & {
    if (ptr == nullptr) {
      return defaultValue;
    } else {
      return *ptr;
    }
  }
  T&& orDefault(T&& defaultValue) && {
    if (ptr == nullptr) {
      return kj::mv(defaultValue);
    } else {
      return kj::mv(*ptr);
    }
  }
  const T&& orDefault(const T&& defaultValue) const && {
    if (ptr == nullptr) {
      return kj::mv(defaultValue);
    } else {
      return kj::mv(*ptr);
    }
  }

  template <typename F,
      typename Result = decltype(instance<bool>() ? instance<T&>() : instance<F>()())>
  Result orDefault(F&& lazyDefaultValue) & {
    if (ptr == nullptr) {
      return lazyDefaultValue();
    } else {
      return *ptr;
    }
  }

  template <typename F,
      typename Result = decltype(instance<bool>() ? instance<const T&>() : instance<F>()())>
  Result orDefault(F&& lazyDefaultValue) const & {
    if (ptr == nullptr) {
      return lazyDefaultValue();
    } else {
      return *ptr;
    }
  }

  template <typename F,
      typename Result = decltype(instance<bool>() ? instance<T&&>() : instance<F>()())>
  Result orDefault(F&& lazyDefaultValue) && {
    if (ptr == nullptr) {
      return lazyDefaultValue();
    } else {
      return kj::mv(*ptr);
    }
  }

  template <typename F,
      typename Result = decltype(instance<bool>() ? instance<const T&&>() : instance<F>()())>
  Result orDefault(F&& lazyDefaultValue) const && {
    if (ptr == nullptr) {
      return lazyDefaultValue();
    } else {
      return kj::mv(*ptr);
    }
  }

  template <typename Func>
  auto map(Func&& f) & -> Maybe<decltype(f(instance<T&>()))> {
    if (ptr == nullptr) {
      return nullptr;
    } else {
      return f(*ptr);
    }
  }

  template <typename Func>
  auto map(Func&& f) const & -> Maybe<decltype(f(instance<const T&>()))> {
    if (ptr == nullptr) {
      return nullptr;
    } else {
      return f(*ptr);
    }
  }

  template <typename Func>
  auto map(Func&& f) && -> Maybe<decltype(f(instance<T&&>()))> {
    if (ptr == nullptr) {
      return nullptr;
    } else {
      return f(kj::mv(*ptr));
    }
  }

  template <typename Func>
  auto map(Func&& f) const && -> Maybe<decltype(f(instance<const T&&>()))> {
    if (ptr == nullptr) {
      return nullptr;
    } else {
      return f(kj::mv(*ptr));
    }
  }

private:
  _::NullableValue<T> ptr;

  template <typename U>
  friend class Maybe;
  template <typename U>
  friend _::NullableValue<U>&& _::readMaybe(Maybe<U>&& maybe);
  template <typename U>
  friend U* _::readMaybe(Maybe<U>& maybe);
  template <typename U>
  friend const U* _::readMaybe(const Maybe<U>& maybe);
};

template <typename T>
class Maybe<T&> {
public:
  constexpr Maybe(): ptr(nullptr) {}
  constexpr Maybe(T& t): ptr(&t) {}
  constexpr Maybe(T* t): ptr(t) {}

  inline constexpr Maybe(PropagateConst<T, Maybe>& other): ptr(other.ptr) {}
  // Allow const copy only if `T` itself is const. Otherwise allow only non-const copy, to
  // protect transitive constness. Clang is happy for this constructor to be declared `= default`
  // since, after evaluation of `PropagateConst`, it does end up being a default-able constructor.
  // But, GCC and MSVC both complain about that, claiming this constructor cannot be declared
  // default. I don't know who is correct, but whatever, we'll write out an implementation, fine.
  //
  // Note that we can't solve this by inheriting DisallowConstCopyIfNotConst<T> because we want
  // to override the move constructor, and if we override the move constructor then we must define
  // the copy constructor here.

  inline constexpr Maybe(Maybe&& other): ptr(other.ptr) { other.ptr = nullptr; }

  template <typename U>
  inline constexpr Maybe(Maybe<U&>& other): ptr(other.ptr) {}
  template <typename U>
  inline constexpr Maybe(const Maybe<U&>& other): ptr(const_cast<const U*>(other.ptr)) {}
  template <typename U>
  inline constexpr Maybe(Maybe<U&>&& other): ptr(other.ptr) { other.ptr = nullptr; }
  template <typename U>
  inline constexpr Maybe(const Maybe<U&>&& other) = delete;
  template <typename U, typename = EnableIf<canConvert<U*, T*>()>>
  constexpr Maybe(Maybe<U>& other): ptr(other.ptr.operator U*()) {}
  template <typename U, typename = EnableIf<canConvert<const U*, T*>()>>
  constexpr Maybe(const Maybe<U>& other): ptr(other.ptr.operator const U*()) {}
  inline constexpr Maybe(decltype(nullptr)): ptr(nullptr) {}

  inline Maybe& operator=(T& other) { ptr = &other; return *this; }
  inline Maybe& operator=(T* other) { ptr = other; return *this; }
  inline Maybe& operator=(PropagateConst<T, Maybe>& other) { ptr = other.ptr; return *this; }
  inline Maybe& operator=(Maybe&& other) { ptr = other.ptr; other.ptr = nullptr; return *this; }
  template <typename U>
  inline Maybe& operator=(Maybe<U&>& other) { ptr = other.ptr; return *this; }
  template <typename U>
  inline Maybe& operator=(const Maybe<const U&>& other) { ptr = other.ptr; return *this; }
  template <typename U>
  inline Maybe& operator=(Maybe<U&>&& other) { ptr = other.ptr; other.ptr = nullptr; return *this; }
  template <typename U>
  inline Maybe& operator=(const Maybe<U&>&& other) = delete;

  inline bool operator==(decltype(nullptr)) const { return ptr == nullptr; }
  inline bool operator!=(decltype(nullptr)) const { return ptr != nullptr; }

  T& orDefault(T& defaultValue) {
    if (ptr == nullptr) {
      return defaultValue;
    } else {
      return *ptr;
    }
  }
  const T& orDefault(const T& defaultValue) const {
    if (ptr == nullptr) {
      return defaultValue;
    } else {
      return *ptr;
    }
  }

  template <typename Func>
  auto map(Func&& f) -> Maybe<decltype(f(instance<T&>()))> {
    if (ptr == nullptr) {
      return nullptr;
    } else {
      return f(*ptr);
    }
  }

  template <typename Func>
  auto map(Func&& f) const -> Maybe<decltype(f(instance<const T&>()))> {
    if (ptr == nullptr) {
      return nullptr;
    } else {
      const T& ref = *ptr;
      return f(ref);
    }
  }

private:
  T* ptr;

  template <typename U>
  friend class Maybe;
  template <typename U>
  friend U* _::readMaybe(Maybe<U&>&& maybe);
  template <typename U>
  friend U* _::readMaybe(const Maybe<U&>& maybe);
};

// =======================================================================================
// ArrayPtr
//
// So common that we put it in common.h rather than array.h.

template <typename T>
class Array;

template <typename T>
class ArrayPtr: public DisallowConstCopyIfNotConst<T> {
  // A pointer to an array.  Includes a size.  Like any pointer, it doesn't own the target data,
  // and passing by value only copies the pointer, not the target.

public:
  inline constexpr ArrayPtr(): ptr(nullptr), size_(0) {}
  inline constexpr ArrayPtr(decltype(nullptr)): ptr(nullptr), size_(0) {}
  inline constexpr ArrayPtr(T* ptr KJ_LIFETIMEBOUND, size_t size): ptr(ptr), size_(size) {}
  inline constexpr ArrayPtr(T* begin KJ_LIFETIMEBOUND, T* end KJ_LIFETIMEBOUND)
      : ptr(begin), size_(end - begin) {}
  ArrayPtr<T>& operator=(Array<T>&&) = delete;
  ArrayPtr<T>& operator=(decltype(nullptr)) {
    ptr = nullptr;
    size_ = 0;
    return *this;
  }

#if __GNUC__ && !__clang__ && __GNUC__ >= 9
// GCC 9 added a warning when we take an initializer_list as a constructor parameter and save a
// pointer to its content in a class member. GCC apparently imagines we're going to do something
// dumb like this:
//     ArrayPtr<const int> ptr = { 1, 2, 3 };
//     foo(ptr[1]); // undefined behavior!
// Any KJ programmer should be able to recognize that this is UB, because an ArrayPtr does not own
// its content. That's not what this constructor is for, tohugh. This constructor is meant to allow
// code like this:
//     int foo(ArrayPtr<const int> p);
//     // ... later ...
//     foo({1, 2, 3});
// In this case, the initializer_list's backing array, like any temporary, lives until the end of
// the statement `foo({1, 2, 3});`. Therefore, it lives at least until the call to foo() has
// returned, which is exactly what we care about. This usage is fine! GCC is wrong to warn.
//
// Amusingly, Clang's implementation has a similar type that they call ArrayRef which apparently
// triggers this same GCC warning. My guess is that Clang will not introduce a similar warning
// given that it triggers on their own, legitimate code.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Winit-list-lifetime"
#endif
  inline KJ_CONSTEXPR() ArrayPtr(
      ::std::initializer_list<RemoveConstOrDisable<T>> init KJ_LIFETIMEBOUND)
      : ptr(init.begin()), size_(init.size()) {}
#if __GNUC__ && !__clang__ && __GNUC__ >= 9
#pragma GCC diagnostic pop
#endif

  template <size_t size>
  inline constexpr ArrayPtr(KJ_LIFETIMEBOUND T (&native)[size]): ptr(native), size_(size) {
    // Construct an ArrayPtr from a native C-style array.
    //
    // We disable this constructor for const char arrays because otherwise you would be able to
    // implicitly convert a character literal to ArrayPtr<const char>, which sounds really great,
    // except that the NUL terminator would be included, which probably isn't what you intended.
    //
    // TODO(someday): Maybe we should support character literals but explicitly chop off the NUL
    //   terminator. This could do the wrong thing if someone tries to construct an
    //   ArrayPtr<const char> from a non-NUL-terminated char array, but evidence suggests that all
    //   real use cases are in fact intending to remove the NUL terminator. It's convenient to be
    //   able to specify ArrayPtr<const char> as a parameter type and be able to accept strings
    //   as input in addition to arrays. Currently, you'll need overloading to support string
    //   literals in this case, but if you overload StringPtr, then you'll find that several
    //   conversions (e.g. from String and from a literal char array) become ambiguous! You end up
    //   having to overload for literal char arrays specifically which is cumbersome.

    static_assert(!isSameType<T, const char>(),
        "Can't implicitly convert literal char array to ArrayPtr because we don't know if "
        "you meant to include the NUL terminator. We may change this in the future to "
        "automatically drop the NUL terminator. For now, try explicitly converting to StringPtr, "
        "which can in turn implicitly convert to ArrayPtr<const char>.");
    static_assert(!isSameType<T, const char16_t>(), "see above");
    static_assert(!isSameType<T, const char32_t>(), "see above");
  }

  inline operator ArrayPtr<const T>() const {
    return ArrayPtr<const T>(ptr, size_);
  }
  inline ArrayPtr<const T> asConst() const {
    return ArrayPtr<const T>(ptr, size_);
  }

  inline constexpr size_t size() const { return size_; }
  inline const T& operator[](size_t index) const {
    KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
    return ptr[index];
  }
  inline T& operator[](size_t index) {
    KJ_IREQUIRE(index < size_, "Out-of-bounds ArrayPtr access.");
    return ptr[index];
  }

  inline T* begin() { return ptr; }
  inline T* end() { return ptr + size_; }
  inline T& front() { return *ptr; }
  inline T& back() { return *(ptr + size_ - 1); }
  inline constexpr const T* begin() const { return ptr; }
  inline constexpr const T* end() const { return ptr + size_; }
  inline const T& front() const { return *ptr; }
  inline const T& back() const { return *(ptr + size_ - 1); }

  inline ArrayPtr<const T> slice(size_t start, size_t end) const {
    KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
    return ArrayPtr<const T>(ptr + start, end - start);
  }
  inline ArrayPtr slice(size_t start, size_t end) {
    KJ_IREQUIRE(start <= end && end <= size_, "Out-of-bounds ArrayPtr::slice().");
    return ArrayPtr(ptr + start, end - start);
  }

  inline ArrayPtr<PropagateConst<T, byte>> asBytes() const {
    // Reinterpret the array as a byte array. This is explicitly legal under C++ aliasing
    // rules.
    return { reinterpret_cast<PropagateConst<T, byte>*>(ptr), size_ * sizeof(T) };
  }
  inline ArrayPtr<PropagateConst<T, char>> asChars() const {
    // Reinterpret the array as a char array. This is explicitly legal under C++ aliasing
    // rules.
    return { reinterpret_cast<PropagateConst<T, char>*>(ptr), size_ * sizeof(T) };
  }

  inline bool operator==(decltype(nullptr)) const { return size_ == 0; }
  inline bool operator!=(decltype(nullptr)) const { return size_ != 0; }

  inline bool operator==(const ArrayPtr& other) const {
    if (size_ != other.size_) return false;
    for (size_t i = 0; i < size_; i++) {
      if (ptr[i] != other[i]) return false;
    }
    return true;
  }
  inline bool operator!=(const ArrayPtr& other) const { return !(*this == other); }

  template <typename U>
  inline bool operator==(const ArrayPtr<U>& other) const {
    if (size_ != other.size()) return false;
    for (size_t i = 0; i < size_; i++) {
      if (ptr[i] != other[i]) return false;
    }
    return true;
  }
  template <typename U>
  inline bool operator!=(const ArrayPtr<U>& other) const { return !(*this == other); }

  template <typename... Attachments>
  Array<T> attach(Attachments&&... attachments) const KJ_WARN_UNUSED_RESULT;
  // Like Array<T>::attach(), but also promotes an ArrayPtr to an Array. Generally the attachment
  // should be an object that actually owns the array that the ArrayPtr is pointing at.
  //
  // You must include kj/array.h to call this.

private:
  T* ptr;
  size_t size_;
};

template <typename T>
inline constexpr ArrayPtr<T> arrayPtr(T* ptr KJ_LIFETIMEBOUND, size_t size) {
  // Use this function to construct ArrayPtrs without writing out the type name.
  return ArrayPtr<T>(ptr, size);
}

template <typename T>
inline constexpr ArrayPtr<T> arrayPtr(T* begin KJ_LIFETIMEBOUND, T* end KJ_LIFETIMEBOUND) {
  // Use this function to construct ArrayPtrs without writing out the type name.
  return ArrayPtr<T>(begin, end);
}

// =======================================================================================
// Casts

template <typename To, typename From>
To implicitCast(From&& from) {
  // `implicitCast<T>(value)` casts `value` to type `T` only if the conversion is implicit.  Useful
  // for e.g. resolving ambiguous overloads without sacrificing type-safety.
  return kj::fwd<From>(from);
}

template <typename To, typename From>
Maybe<To&> dynamicDowncastIfAvailable(From& from) {
  // If RTTI is disabled, always returns nullptr.  Otherwise, works like dynamic_cast.  Useful
  // in situations where dynamic_cast could allow an optimization, but isn't strictly necessary
  // for correctness.  It is highly recommended that you try to arrange all your dynamic_casts
  // this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface
  // design.

  // Force a compile error if To is not a subtype of From.  Cross-casting is rare; if it is needed
  // we should have a separate cast function like dynamicCrosscastIfAvailable().
  if (false) {
    kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
  }

#if KJ_NO_RTTI
  return nullptr;
#else
  return dynamic_cast<To*>(&from);
#endif
}

template <typename To, typename From>
To& downcast(From& from) {
  // Down-cast a value to a sub-type, asserting that the cast is valid.  In opt mode this is a
  // static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify
  // that the value really has the requested type.

  // Force a compile error if To is not a subtype of From.
  if (false) {
    kj::implicitCast<From*>(kj::implicitCast<To*>(nullptr));
  }

#if !KJ_NO_RTTI
  KJ_IREQUIRE(dynamic_cast<To*>(&from) != nullptr, "Value cannot be downcast() to requested type.");
#endif

  return static_cast<To&>(from);
}

// =======================================================================================
// Defer

namespace _ {  // private

template <typename Func>
class Deferred {
public:
  inline Deferred(Func&& func): func(kj::fwd<Func>(func)), canceled(false) {}
  inline ~Deferred() noexcept(false) { if (!canceled) func(); }
  KJ_DISALLOW_COPY(Deferred);

  // This move constructor is usually optimized away by the compiler.
  inline Deferred(Deferred&& other): func(kj::fwd<Func>(other.func)), canceled(other.canceled) {
    other.canceled = true;
  }

  void cancel() {
    canceled = true;
  }

private:
  Func func;
  bool canceled;
};

}  // namespace _ (private)

template <typename Func>
_::Deferred<Func> defer(Func&& func) {
  // Returns an object which will invoke the given functor in its destructor.  The object is not
  // copyable but is movable with the semantics you'd expect.  Since the return type is private,
  // you need to assign to an `auto` variable.
  //
  // The KJ_DEFER macro provides slightly more convenient syntax for the common case where you
  // want some code to run at current scope exit.

  return _::Deferred<Func>(kj::fwd<Func>(func));
}

#define KJ_DEFER(code) auto KJ_UNIQUE_NAME(_kjDefer) = ::kj::defer([&](){code;})
// Run the given code when the function exits, whether by return or exception.

}  // namespace kj

KJ_END_HEADER
