// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Utilities for efficiently reading and writing to/from memory.
#ifndef EMBOSS_RUNTIME_CPP_EMBOSS_MEMORY_UTIL_H_
#define EMBOSS_RUNTIME_CPP_EMBOSS_MEMORY_UTIL_H_

#include <algorithm>
#include <cstddef>
#include <cstring>

#include "runtime/cpp/emboss_bit_util.h"
#include "runtime/cpp/emboss_cpp_types.h"
#include "runtime/cpp/emboss_defines.h"

namespace emboss {
namespace support {

// MemoryAccessor reads and writes big- and little-endian unsigned integers in
// and out of memory, using optimized routines where possible.
//
// The default MemoryAccessor just proxies to the MemoryAccessor with the
// next-smallest alignment and equivalent offset: MemoryAccessor<C, 8, 0, 32>
// and MemoryAccessor<C, 8, 4, 32> will proxy to MemoryAccessor<C, 4, 0, 32>,
// since an 8-byte-aligned pointer is also 4-byte-aligned, as is a pointer that
// is 4 bytes away from 8-byte alignment.
template <typename CharT, ::std::size_t kAlignment, ::std::size_t kOffset,
          ::std::size_t kBits>
struct MemoryAccessor {
  static_assert(IsPowerOfTwo(kAlignment),
                "MemoryAccessor requires power-of-two alignment.");
  static_assert(
      kOffset < kAlignment,
      "MemoryAccessor requires offset to be strictly less than alignment.");

  using ChainedAccessor =
      MemoryAccessor<CharT, kAlignment / 2, kOffset % (kAlignment / 2), kBits>;
  using Unsigned = typename LeastWidthInteger<kBits>::Unsigned;
  static inline Unsigned ReadLittleEndianUInt(const CharT *bytes) {
    return ChainedAccessor::ReadLittleEndianUInt(bytes);
  }
  static inline void WriteLittleEndianUInt(CharT *bytes, Unsigned value) {
    ChainedAccessor::WriteLittleEndianUInt(bytes, value);
  }
  static inline Unsigned ReadBigEndianUInt(const CharT *bytes) {
    return ChainedAccessor::ReadBigEndianUInt(bytes);
  }
  static inline void WriteBigEndianUInt(CharT *bytes, Unsigned value) {
    ChainedAccessor::WriteBigEndianUInt(bytes, value);
  }
};

// The least-aligned case for MemoryAccessor is 8-bit alignment, and the default
// version of MemoryAccessor will devolve to this one if there is no more
// specific override.
//
// If the system byte order is known, then these routines can use memcpy and
// (possibly) a byte swap; otherwise they can read individual bytes and
// shift+or them together in the appropriate order.  I (bolms@) haven't found a
// compiler that will optimize the multiple reads, shifts, and ors into a single
// read, so the memcpy version is *much* faster for 32-bit and larger reads.
template <typename CharT, ::std::size_t kBits>
struct MemoryAccessor<CharT, 1, 0, kBits> {
  static_assert(kBits % 8 == 0,
                "MemoryAccessor can only read and write whole-byte values.");
  static_assert(IsChar<CharT>::value,
                "MemoryAccessor can only be used on pointers to char types.");

  using Unsigned = typename LeastWidthInteger<kBits>::Unsigned;

#if defined(EMBOSS_LITTLE_ENDIAN_TO_NATIVE)
  static inline Unsigned ReadLittleEndianUInt(const CharT *bytes) {
    Unsigned result = 0;
    ::std::memcpy(&result, bytes, kBits / 8);
    return EMBOSS_LITTLE_ENDIAN_TO_NATIVE(result);
  }
#else
  static inline Unsigned ReadLittleEndianUInt(const CharT *bytes) {
    Unsigned result = 0;
    for (decltype(kBits) i = 0; i < kBits / 8; ++i) {
      result |=
          static_cast<Unsigned>(static_cast</**/ ::std::uint8_t>(bytes[i]))
          << i * 8;
    }
    return result;
  }
#endif

#if defined(EMBOSS_NATIVE_TO_LITTLE_ENDIAN)
  static inline void WriteLittleEndianUInt(CharT *bytes, Unsigned value) {
    value = EMBOSS_NATIVE_TO_LITTLE_ENDIAN(value);
    ::std::memcpy(bytes, &value, kBits / 8);
  }
#else
  static inline void WriteLittleEndianUInt(CharT *bytes, Unsigned value) {
    for (decltype(kBits) i = 0; i < kBits / 8; ++i) {
      bytes[i] = static_cast<CharT>(static_cast</**/ ::std::uint8_t>(value));
      if (sizeof value > 1) {
        // Shifting an 8-bit type by 8 bits is undefined behavior, so skip this
        // step for uint8_t.
        value >>= 8;
      }
    }
  }
#endif

#if defined(EMBOSS_BIG_ENDIAN_TO_NATIVE)
  static inline Unsigned ReadBigEndianUInt(const CharT *bytes) {
    Unsigned result = 0;
    // When a big-endian source integer is smaller than the result, the source
    // bytes must be copied into the final bytes of the destination.  This is
    // true whether the host is big- or little-endian.
    //
    // For a little-endian host:
    //
    // source (big-endian value 0x112233):
    //
    //   byte 0   byte 1   byte 2
    // +--------+--------+--------+
    // | 0x11   | 0x22   | 0x33   |
    // +--------+--------+--------+
    //
    // result after memcpy (host-interpreted value 0x33221100):
    //
    //   byte 0   byte 1   byte 2   byte 3
    // +--------+--------+--------+--------+
    // | 0x00   | 0x11   | 0x22   | 0x33   |
    // +--------+--------+--------+--------+
    //
    // result after 32-bit byte swap (host-interpreted value 0x112233):
    //
    //   byte 0   byte 1   byte 2   byte 3
    // +--------+--------+--------+--------+
    // | 0x33   | 0x22   | 0x11   | 0x00   |
    // +--------+--------+--------+--------+
    //
    // For a big-endian host:
    //
    // source (value 0x112233):
    //
    //   byte 0   byte 1   byte 2
    // +--------+--------+--------+
    // | 0x11   | 0x22   | 0x33   |
    // +--------+--------+--------+
    //
    // result after memcpy (value 0x112233) -- no byte swap needed:
    //
    //   byte 0   byte 1   byte 2   byte 3
    // +--------+--------+--------+--------+
    // | 0x00   | 0x11   | 0x22   | 0x33   |
    // +--------+--------+--------+--------+
    ::std::memcpy(reinterpret_cast<char *>(&result) + sizeof result - kBits / 8,
                  bytes, kBits / 8);
    result = EMBOSS_BIG_ENDIAN_TO_NATIVE(result);
    return result;
  }
#else
  static inline Unsigned ReadBigEndianUInt(const CharT *bytes) {
    Unsigned result = 0;
    for (decltype(kBits) i = 0; i < kBits / 8; ++i) {
      result |=
          static_cast<Unsigned>(static_cast</**/ ::std::uint8_t>(bytes[i]))
          << (kBits - 8 - i * 8);
    }
    return result;
  }
#endif

#if defined(EMBOSS_NATIVE_TO_BIG_ENDIAN)
  static inline void WriteBigEndianUInt(CharT *bytes, Unsigned value) {
    value = EMBOSS_NATIVE_TO_BIG_ENDIAN(value);
    ::std::memcpy(bytes,
                  reinterpret_cast<char *>(&value) + sizeof value - kBits / 8,
                  kBits / 8);
  }
#else
  static inline void WriteBigEndianUInt(CharT *bytes, Unsigned value) {
    for (decltype(kBits) i = 0; i < kBits / 8; ++i) {
      bytes[kBits / 8 - 1 - i] =
          static_cast<CharT>(static_cast</**/ ::std::uint8_t>(value));
      if (sizeof value > 1) {
        // Shifting an 8-bit type by 8 bits is undefined behavior, so skip this
        // step for uint8_t.
        value >>= 8;
      }
    }
  }
#endif
};

// Specialization of UIntMemoryAccessor for 16- 32- and 64-bit-aligned reads and
// writes, using EMBOSS_ALIAS_SAFE_POINTER_CAST instead of memcpy.
#if defined(EMBOSS_ALIAS_SAFE_POINTER_CAST) && \
    defined(EMBOSS_LITTLE_ENDIAN_TO_NATIVE) && \
    defined(EMBOSS_BIG_ENDIAN_TO_NATIVE) &&    \
    defined(EMBOSS_NATIVE_TO_LITTLE_ENDIAN) && \
    defined(EMBOSS_NATIVE_TO_BIG_ENDIAN)
template <typename CharT>
struct MemoryAccessor<CharT, 8, 0, 64> {
  static inline ::std::uint64_t ReadLittleEndianUInt(const CharT *bytes) {
    return EMBOSS_LITTLE_ENDIAN_TO_NATIVE(
        *EMBOSS_ALIAS_SAFE_POINTER_CAST(const ::std::uint64_t, bytes));
  }

  static inline void WriteLittleEndianUInt(CharT *bytes,
                                           ::std::uint64_t value) {
    *EMBOSS_ALIAS_SAFE_POINTER_CAST(::std::uint64_t, bytes) =
        EMBOSS_NATIVE_TO_LITTLE_ENDIAN(value);
  }

  static inline ::std::uint64_t ReadBigEndianUInt(const CharT *bytes) {
    return EMBOSS_BIG_ENDIAN_TO_NATIVE(
        *EMBOSS_ALIAS_SAFE_POINTER_CAST(const ::std::uint64_t, bytes));
  }

  static inline void WriteBigEndianUInt(CharT *bytes, ::std::uint64_t value) {
    *EMBOSS_ALIAS_SAFE_POINTER_CAST(::std::uint64_t, bytes) =
        EMBOSS_NATIVE_TO_BIG_ENDIAN(value);
  }
};

template <typename CharT>
struct MemoryAccessor<CharT, 4, 0, 32> {
  static inline ::std::uint32_t ReadLittleEndianUInt(const CharT *bytes) {
    return EMBOSS_LITTLE_ENDIAN_TO_NATIVE(
        *EMBOSS_ALIAS_SAFE_POINTER_CAST(const ::std::uint32_t, bytes));
  }

  static inline void WriteLittleEndianUInt(CharT *bytes,
                                           ::std::uint32_t value) {
    *EMBOSS_ALIAS_SAFE_POINTER_CAST(::std::uint32_t, bytes) =
        EMBOSS_NATIVE_TO_LITTLE_ENDIAN(value);
  }

  static inline ::std::uint32_t ReadBigEndianUInt(const CharT *bytes) {
    return EMBOSS_BIG_ENDIAN_TO_NATIVE(
        *EMBOSS_ALIAS_SAFE_POINTER_CAST(const ::std::uint32_t, bytes));
  }

  static inline void WriteBigEndianUInt(CharT *bytes, ::std::uint32_t value) {
    *EMBOSS_ALIAS_SAFE_POINTER_CAST(::std::uint32_t, bytes) =
        EMBOSS_NATIVE_TO_BIG_ENDIAN(value);
  }
};

template <typename CharT>
struct MemoryAccessor<CharT, 2, 0, 16> {
  static inline ::std::uint16_t ReadLittleEndianUInt(const CharT *bytes) {
    return EMBOSS_LITTLE_ENDIAN_TO_NATIVE(
        *EMBOSS_ALIAS_SAFE_POINTER_CAST(const ::std::uint16_t, bytes));
  }

  static inline void WriteLittleEndianUInt(CharT *bytes,
                                           ::std::uint16_t value) {
    *EMBOSS_ALIAS_SAFE_POINTER_CAST(::std::uint16_t, bytes) =
        EMBOSS_NATIVE_TO_LITTLE_ENDIAN(value);
  }

  static inline ::std::uint16_t ReadBigEndianUInt(const CharT *bytes) {
    return EMBOSS_BIG_ENDIAN_TO_NATIVE(
        *EMBOSS_ALIAS_SAFE_POINTER_CAST(const ::std::uint16_t, bytes));
  }

  static inline void WriteBigEndianUInt(CharT *bytes, ::std::uint16_t value) {
    *EMBOSS_ALIAS_SAFE_POINTER_CAST(::std::uint16_t, bytes) =
        EMBOSS_NATIVE_TO_BIG_ENDIAN(value);
  }
};
#endif  // defined(EMBOSS_ALIAS_SAFE_POINTER_CAST) &&
        // defined(EMBOSS_LITTLE_ENDIAN_TO_NATIVE) &&
        // defined(EMBOSS_BIG_ENDIAN_TO_NATIVE) &&
        // defined(EMBOSS_NATIVE_TO_LITTLE_ENDIAN) &&
        // defined(EMBOSS_NATIVE_TO_BIG_ENDIAN)

// This is the Euclidean GCD algorithm, in C++11-constexpr-safe form.  The
// initial is-b-greater-than-a-if-so-swap is omitted, since gcd(b % a, a) is the
// same as gcd(b, a) when a > b.
inline constexpr ::std::size_t GreatestCommonDivisor(::std::size_t a,
                                                     ::std::size_t b) {
  return a == 0 ? b : GreatestCommonDivisor(b % a, a);
}

// ContiguousBuffer is a direct view of a fixed number of contiguous bytes in
// memory.  If Byte is a const type, it will be a read-only view; if Byte is
// non-const, then writes will be allowed.
//
// The kAlignment and kOffset parameters are used to optimize certain reads and
// writes.  static_cast<uintptr_t>(bytes_) % kAlignment must equal kOffset.
//
// This class is used extensively by generated code, and is not intended to be
// heavily used by hand-written code -- some interfaces can be tricky to call
// correctly.
template <typename Byte, ::std::size_t kAlignment, ::std::size_t kOffset>
class ContiguousBuffer final {
  // There aren't many systems with non-8-bit chars, and a quirk of POSIX
  // requires that POSIX C systems have CHAR_BIT == 8, but some DSPs use wider
  // chars.
  static_assert(CHAR_BIT == 8, "ContiguousBuffer requires 8-bit chars.");

  // ContiguousBuffer assumes that its backing store is byte-oriented.  The
  // previous check ensures that chars are 8 bits, and this one ensures that the
  // backing store uses chars.
  //
  // Note that this check is explicitly that Byte is one of the three standard
  // char types, and not that (say) it is a one-byte type with an assignment
  // operator that can be static_cast<> to and from uint8_t.  I (bolms@) have
  // chosen to lock it down to just char types to avoid running afoul of strict
  // aliasing rules anywhere.
  //
  // Of somewhat academic interest, uint8_t is not required to be a char type
  // (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66110#c10), though it is
  // unlikely that any compiler vendor will actually change it, as there is
  // probably enough real-world code that relies on uint8_t being allowed to
  // alias.
  static_assert(IsChar<Byte>::value, "ContiguousBuffer requires char type.");

  // Because real-world processors only care about power-of-2 alignments,
  // ContiguousBuffer only supports power-of-2 alignments.  Note that
  // GetOffsetStorage can handle non-power-of-2 alignments.
  static_assert(IsPowerOfTwo(kAlignment),
                "ContiguousBuffer requires power-of-two alignment.");

  // To avoid template variant explosion, ContiguousBuffer requires kOffset to
  // be strictly less than kAlignment.  Users of ContiguousBuffer are expected
  // to take the modulus of kOffset by kAlignment before passing it in as a
  // parameter.
  static_assert(
      kOffset < kAlignment,
      "ContiguousBuffer requires offset to be strictly less than alignment.");

 public:
  using ByteType = Byte;
  // OffsetStorageType<kSubAlignment, kSubOffset> is the return type of
  // GetOffsetStorage<kSubAlignment, kSubOffset>(...).  This is used in a number
  // of places in generated code to specify deeply-nested template values.
  //
  // In theory, anything that cared about this type could use
  // decltype(declval(ContiguousBuffer<...>).GetOffsetStorage<kSubAlignment,
  // kSubOffset>(0, 0)) instead, but that is much more cumbersome, and it
  // appears that at least some versions of GCC do not handle it correctly.
  template </**/ ::std::size_t kSubAlignment, ::std::size_t kSubOffset>
  using OffsetStorageType =
      ContiguousBuffer<Byte, GreatestCommonDivisor(kAlignment, kSubAlignment),
                       (kOffset + kSubOffset) %
                           GreatestCommonDivisor(kAlignment, kSubAlignment)>;

  // Constructs a default ContiguousBuffer.
  ContiguousBuffer() : bytes_(nullptr), size_(0) {}

  // Constructs a ContiguousBuffer from a contiguous container type over some
  // `char` type, such as std::string, std::vector<signed char>,
  // std::array<unsigned char, N>, or std::string_view.
  //
  // This template is only enabled if:
  //
  // 1. bytes->data() returns a pointer to some char type.
  // 2. Byte is at least as cv-qualified as decltype(*bytes->data()).
  //
  // The first requirement means that this constructor won't work on, e.g.,
  // std::vector<int> -- this is mostly a precautionary measure, since
  // ContiguousBuffer only uses alias-safe operations anyway.
  //
  // The second requirement means that const and volatile are respected in the
  // expected way: a ContiguousBuffer<const unsigned char, ...> may be
  // initialized from std::vector<char>, but a ContiguousBuffer<unsigned char,
  // ...> may not be initialized from std::string_view.
  template <
      typename T,
      typename = typename ::std::enable_if<
          IsChar<typename ::std::remove_cv<typename ::std::remove_reference<
              decltype(*(::std::declval<T>().data()))>::type>::type>::value
              && ::std::is_same<
                  typename AddSourceCV<decltype(*::std::declval<T>().data()),
                                       Byte>::Type,
                  Byte>::value>::type>
  explicit ContiguousBuffer(T *bytes)
      : bytes_{reinterpret_cast<Byte *>(bytes->data())}, size_{bytes->size()} {
    if (bytes != nullptr)
      EMBOSS_DCHECK_POINTER_ALIGNMENT(bytes, kAlignment, kOffset);
  }

  // Constructs a ContiguousBuffer from a pointer to a char type and a size.  As
  // with the constructor from a container, above, Byte must be at least as
  // cv-qualified as T.
  template <
      typename T,
      typename = typename ::std::enable_if<IsChar<T>::value && ::std::is_same<
          typename AddSourceCV<T, Byte>::Type, Byte>::value>>
  explicit ContiguousBuffer(T *bytes, ::std::size_t size)
      : bytes_{reinterpret_cast<Byte *>(bytes)},
        size_{bytes == nullptr ? 0 : size} {
    if (bytes != nullptr)
      EMBOSS_DCHECK_POINTER_ALIGNMENT(bytes, kAlignment, kOffset);
  }

  // Constructs a ContiguousBuffer from nullptr.  Equivalent to
  // ContiguousBuffer().
  //
  // TODO(bolms): Update callers and remove this constructor.
  explicit ContiguousBuffer(::std::nullptr_t) : bytes_{nullptr}, size_{0} {}

  // Implicitly constructs a ContiguousBuffer from an identical
  // ContiguousBuffer.
  ContiguousBuffer(const ContiguousBuffer &other) = default;

  // Explicitly construct a ContiguousBuffers from another, compatible
  // ContiguousBuffer.  A compatible ContiguousBuffer has an
  // equally-or-less-cv-qualified Byte type, an alignment that is an exact
  // multiple of this ContiguousBuffer's alignment, and an offset that is the
  // same when reduced to this ContiguousBuffer's alignment.
  //
  // The final !::std::is_same<...> clause prevents this constructor from
  // overlapping with the *implicit* copy constructor.
  template <
      typename OtherByte, ::std::size_t kOtherAlignment,
      ::std::size_t kOtherOffset,
      typename = typename ::std::enable_if<
          kOtherAlignment % kAlignment == 0 &&
          kOtherOffset % kAlignment ==
              kOffset && ::std::is_same<
                  typename AddSourceCV<OtherByte, Byte>::Type, Byte>::value &&
          !::std::is_same<ContiguousBuffer,
                          ContiguousBuffer<OtherByte, kOtherAlignment,
                                           kOtherOffset>>::value>::type>
  explicit ContiguousBuffer(
      const ContiguousBuffer<OtherByte, kOtherAlignment, kOtherOffset> &other)
      : bytes_{reinterpret_cast<Byte *>(other.data())},
        size_{other.SizeInBytes()} {}

  // Compare a ContiguousBuffers to another, compatible ContiguousBuffer.
  template <typename OtherByte, ::std::size_t kOtherAlignment,
            ::std::size_t kOtherOffset,
            typename = typename ::std::enable_if<
                kOtherAlignment % kAlignment == 0 &&
                kOtherOffset % kAlignment ==
                    kOffset && ::std::is_same<
                        typename AddSourceCV<OtherByte, Byte>::Type,
                        Byte>::value>::type>
  bool operator==(const ContiguousBuffer<OtherByte, kOtherAlignment,
                                         kOtherOffset> &other) const {
    return bytes_ == reinterpret_cast<Byte *>(other.data()) &&
           size_ == other.SizeInBytes();
  }

  // Compare a ContiguousBuffers to another, compatible ContiguousBuffer.
  template <typename OtherByte, ::std::size_t kOtherAlignment,
            ::std::size_t kOtherOffset,
            typename = typename ::std::enable_if<
                kOtherAlignment % kAlignment == 0 &&
                kOtherOffset % kAlignment ==
                    kOffset && ::std::is_same<
                        typename AddSourceCV<OtherByte, Byte>::Type,
                        Byte>::value>::type>
  bool operator!=(const ContiguousBuffer<OtherByte, kOtherAlignment,
                                         kOtherOffset> &other) const {
    return !(*this == other);
  }

  // Assignment from a compatible ContiguousBuffer.
  template <typename OtherByte, ::std::size_t kOtherAlignment,
            ::std::size_t kOtherOffset,
            typename = typename ::std::enable_if<
                kOtherAlignment % kAlignment == 0 &&
                kOtherOffset % kAlignment ==
                    kOffset && ::std::is_same<
                        typename AddSourceCV<OtherByte, Byte>::Type,
                        Byte>::value>::type>
  ContiguousBuffer &operator=(
      const ContiguousBuffer<OtherByte, kOtherAlignment, kOtherOffset> &other) {
    bytes_ = reinterpret_cast<Byte *>(other.data());
    size_ = other.SizeInBytes();
    return *this;
  }

  // GetOffsetStorage returns a new ContiguousBuffer that is a subsection of
  // this ContiguousBuffer, with appropriate alignment assertions.  The new
  // ContiguousBuffer will point to a region `offset` bytes into the original
  // ContiguousBuffer, with a size of `max(size, original_size - offset)`.
  //
  // The kSubAlignment and kSubOffset template parameters act as assertions
  // about the value of `offset`: `offset % (kSubAlignment / 8) - (kSubOffset /
  // 8)` must be zero.  That is, if `kSubAlignment` is 16 and `kSubOffset` is 8,
  // then `offset` may be 1, 3, 5, 7, etc.
  //
  // As a special case, if `kSubAlignment` is 0, then `offset` must exactly
  // equal `kSubOffset`.
  //
  // This method is used by generated structure views to get backing buffers for
  // views of their fields; the code generator can determine proper values for
  // `kSubAlignment` and `kSubOffset`.
  template </**/ ::std::size_t kSubAlignment, ::std::size_t kSubOffset>
  OffsetStorageType<kSubAlignment, kSubOffset> GetOffsetStorage(
      ::std::size_t offset, ::std::size_t size) const {
    static_assert(kSubAlignment == 0 || kSubAlignment > kSubOffset,
                  "kSubAlignment must be greater than kSubOffset.");
    // Emboss provides a fast, unchecked path for reads and writes like:
    //
    // view.field().subfield().UncheckedWrite().
    //
    // Each of .field() and .subfield() call GetOffsetStorage(), so
    // GetOffsetStorage() must be small and fast.
    if (kSubAlignment == 0) {
      EMBOSS_DCHECK_EQ(offset, kSubOffset);
    } else {
      // The weird ?:, below, silences -Werror=div-by-zero on versions of GCC
      // that aren't smart enough to figure out that kSubAlignment can't be zero
      // in this branch.
      EMBOSS_DCHECK_EQ(offset % (kSubAlignment == 0 ? 1 : kSubAlignment),
                       kSubOffset);
    }
    using ResultStorageType = OffsetStorageType<kSubAlignment, kSubOffset>;
    return bytes_ == nullptr
               ? ResultStorageType{nullptr}
               : ResultStorageType{
                     bytes_ + offset,
                     size_ < offset ? 0 : ::std::min(size, size_ - offset)};
  }

  // ReadLittleEndianUInt, ReadBigEndianUInt, and the unchecked versions thereof
  // provide efficient multibyte read access to the underlying buffer.  The
  // kBits template parameter should always equal the buffer size when these are
  // called.
  //
  // Generally, types other than unsigned integers can be relatively efficiently
  // converted from unsigned integers, and views should use Read...UInt to read
  // the raw value, then convert.
  //
  // Read...UInt always reads the entire buffer; to read a smaller section, use
  // GetOffsetStorage first.
  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned ReadLittleEndianUInt() const {
    EMBOSS_CHECK_EQ(SizeInBytes() * 8, kBits);
    EMBOSS_CHECK_POINTER_ALIGNMENT(bytes_, kAlignment, kOffset);
    return UncheckedReadLittleEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned UncheckedReadLittleEndianUInt()
      const {
    static_assert(kBits % 8 == 0,
                  "ContiguousBuffer::ReadLittleEndianUInt() can only read "
                  "whole-byte values.");
    return MemoryAccessor<Byte, kAlignment, kOffset,
                          kBits>::ReadLittleEndianUInt(bytes_);
  }
  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned ReadBigEndianUInt() const {
    EMBOSS_CHECK_EQ(SizeInBytes() * 8, kBits);
    EMBOSS_CHECK_POINTER_ALIGNMENT(bytes_, kAlignment, kOffset);
    return UncheckedReadBigEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned UncheckedReadBigEndianUInt()
      const {
    static_assert(kBits % 8 == 0,
                  "ContiguousBuffer::ReadBigEndianUInt() can only read "
                  "whole-byte values.");
    return MemoryAccessor<Byte, kAlignment, kOffset, kBits>::ReadBigEndianUInt(
        bytes_);
  }

  // WriteLittleEndianUInt, WriteBigEndianUInt, and the unchecked versions
  // thereof provide efficient write access to the buffer.  Similar to the Read
  // methods above, they write the entire buffer from an unsigned integer;
  // non-unsigned values should be converted to the equivalent bit pattern, then
  // written, and to write a subsection of the buffer use GetOffsetStorage
  // first.
  template </**/ ::std::size_t kBits>
  void WriteLittleEndianUInt(
      typename LeastWidthInteger<kBits>::Unsigned value) const {
    EMBOSS_CHECK_EQ(SizeInBytes() * 8, kBits);
    EMBOSS_CHECK_POINTER_ALIGNMENT(bytes_, kAlignment, kOffset);
    UncheckedWriteLittleEndianUInt<kBits>(value);
  }
  template </**/ ::std::size_t kBits>
  void UncheckedWriteLittleEndianUInt(
      typename LeastWidthInteger<kBits>::Unsigned value) const {
    static_assert(kBits % 8 == 0,
                  "ContiguousBuffer::WriteLittleEndianUInt() can only write "
                  "whole-byte values.");
    MemoryAccessor<Byte, kAlignment, kOffset, kBits>::WriteLittleEndianUInt(
        bytes_, value);
  }
  template </**/ ::std::size_t kBits>
  void WriteBigEndianUInt(
      typename LeastWidthInteger<kBits>::Unsigned value) const {
    EMBOSS_CHECK_EQ(SizeInBytes() * 8, kBits);
    EMBOSS_CHECK_POINTER_ALIGNMENT(bytes_, kAlignment, kOffset);
    return UncheckedWriteBigEndianUInt<kBits>(value);
  }
  template </**/ ::std::size_t kBits>
  void UncheckedWriteBigEndianUInt(
      typename LeastWidthInteger<kBits>::Unsigned value) const {
    static_assert(kBits % 8 == 0,
                  "ContiguousBuffer::WriteBigEndianUInt() can only write "
                  "whole-byte values.");
    MemoryAccessor<Byte, kAlignment, kOffset, kBits>::WriteBigEndianUInt(bytes_,
                                                                         value);
  }

  template <typename OtherByte, ::std::size_t kOtherAlignment,
            ::std::size_t kOtherOffset>
  void UncheckedCopyFrom(
      const ContiguousBuffer<OtherByte, kOtherAlignment, kOtherOffset> &other,
      ::std::size_t size) const {
    memmove(data(), other.data(), size);
  }
  template <typename OtherByte, ::std::size_t kOtherAlignment,
            ::std::size_t kOtherOffset>
  void CopyFrom(
      const ContiguousBuffer<OtherByte, kOtherAlignment, kOtherOffset> &other,
      ::std::size_t size) const {
    EMBOSS_CHECK(Ok());
    EMBOSS_CHECK(other.Ok());
    // It is OK if either buffer contains extra bytes that are not being copied.
    EMBOSS_CHECK_GE(SizeInBytes(), size);
    EMBOSS_CHECK_GE(other.SizeInBytes(), size);
    UncheckedCopyFrom(other, size);
  }
  template <typename OtherByte, ::std::size_t kOtherAlignment,
            ::std::size_t kOtherOffset>
  bool TryToCopyFrom(
      const ContiguousBuffer<OtherByte, kOtherAlignment, kOtherOffset> &other,
      ::std::size_t size) const {
    if (Ok() && other.Ok() && SizeInBytes() >= size &&
        other.SizeInBytes() >= size) {
      UncheckedCopyFrom(other, size);
      return true;
    }
    return false;
  }
  ::std::size_t SizeInBytes() const { return size_; }
  bool Ok() const { return bytes_ != nullptr; }
  Byte *data() const { return bytes_; }
  Byte *begin() const { return bytes_; }
  Byte *end() const { return bytes_ + size_; }

  // Constructs a string type from the underlying data; mostly intended to be
  // called as:
  //
  //     buffer.ToString<std::string>();
  //
  // or:
  //
  //     buffer.ToString<std::string_view>();
  //
  // ... but it should also work with any similar-enough classes, such as
  // std::basic_string_view<unsigned char> or Google's absl::string_view.
  //
  // Note that this may or may not make a copy of the underlying data,
  // depending on the behavior of the given string type.
  template <typename String>
  typename ::std::enable_if<
      IsChar<typename ::std::remove_reference<
          decltype(*::std::declval<String>().data())>::type>::value,
      String>::type
  ToString() const {
    return String(
        reinterpret_cast<
            const typename ::std::remove_reference<typename ::std::remove_cv<
                decltype(*::std::declval<String>().data())>::type>::type *>(
            bytes_),
        size_);
  }

 private:
  Byte *bytes_ = nullptr;
  ::std::size_t size_ = 0;
};

// TODO(bolms): Remove these aliases.
using ReadWriteContiguousBuffer = ContiguousBuffer<unsigned char, 1, 0>;
using ReadOnlyContiguousBuffer = ContiguousBuffer<const unsigned char, 1, 0>;

// LittleEndianByteOrderer is a pass-through adapter for a byte buffer class.
// It is used to implement little-endian bit blocks.
//
// When used by BitBlock, the resulting bits are numbered as if they are
// little-endian:
//
//                      bit addresses of each bit in each byte
//           +----+----+----+----+----+----+----+----+----+----+----+----+----
// bit in  7 |  7 | 15 | 23 | 31 | 39 | 47 | 55 | 63 | 71 | 79 | 87 | 95 |
// byte    6 |  6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 | 70 | 78 | 86 | 94 |
//         5 |  5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 | 69 | 77 | 85 | 93 |
//         4 |  4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 | 68 | 76 | 84 | 92 |
//         3 |  3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 | 67 | 75 | 83 | 91 | ...
//         2 |  2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 | 66 | 74 | 82 | 90 |
//         1 |  1 |  9 | 17 | 25 | 33 | 41 | 49 | 57 | 65 | 73 | 81 | 89 |
//         0 |  0 |  8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 | 80 | 88 |
//           +----+----+----+----+----+----+----+----+----+----+----+----+----
//              0    1    2    3    4    5    6    7    8    9   10   11   ...
//                                  byte address
//
// Because endian-specific reads and writes are handled in ContiguousBuffer,
// this class exists mostly to translate VerbUInt calls to VerbLittleEndianUInt.
template <class BufferT>
class LittleEndianByteOrderer final {
 public:
  // Type declaration so that BitBlock can use BufferType::BufferType.
  using BufferType = BufferT;

  LittleEndianByteOrderer() : buffer_() {}
  explicit LittleEndianByteOrderer(BufferType buffer) : buffer_{buffer} {}
  LittleEndianByteOrderer(const LittleEndianByteOrderer &other) = default;
  LittleEndianByteOrderer(LittleEndianByteOrderer &&other) = default;
  LittleEndianByteOrderer &operator=(const LittleEndianByteOrderer &other) =
      default;

  // LittleEndianByteOrderer just passes straight through to the underlying
  // buffer.
  bool Ok() const { return buffer_.Ok(); }
  ::std::size_t SizeInBytes() const { return buffer_.SizeInBytes(); }

  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned ReadUInt() const {
    return buffer_.template ReadLittleEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned UncheckedReadUInt() const {
    return buffer_.template UncheckedReadLittleEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  void WriteUInt(typename LeastWidthInteger<kBits>::Unsigned value) const {
    buffer_.template WriteLittleEndianUInt<kBits>(value);
  }
  template </**/ ::std::size_t kBits>
  void UncheckedWriteUInt(
      typename LeastWidthInteger<kBits>::Unsigned value) const {
    buffer_.template UncheckedWriteLittleEndianUInt<kBits>(value);
  }

 private:
  BufferType buffer_;
};

// BigEndianByteOrderer is an adapter for a byte buffer class which reverses
// the addresses of the underlying byte buffer.  It is used to implement
// big-endian bit blocks.
//
// When used by BitBlock, the resulting bits are numbered with "bit 0" as the
// lowest-order bit of the *last* byte in the buffer.  For example, for a
// 12-byte buffer, the bit ordering looks like:
//
//                      bit addresses of each bit in each byte
//           +----+----+----+----+----+----+----+----+----+----+----+----+
// bit in  7 | 95 | 87 | 79 | 71 | 63 | 55 | 47 | 39 | 31 | 23 | 15 |  7 |
// byte    6 | 94 | 86 | 78 | 70 | 62 | 54 | 46 | 38 | 30 | 22 | 14 |  6 |
//         5 | 93 | 85 | 77 | 69 | 61 | 53 | 45 | 37 | 29 | 21 | 13 |  5 |
//         4 | 92 | 84 | 76 | 68 | 60 | 52 | 44 | 36 | 28 | 20 | 12 |  4 |
//         3 | 91 | 83 | 75 | 67 | 59 | 51 | 43 | 35 | 27 | 19 | 11 |  3 |
//         2 | 90 | 82 | 74 | 66 | 58 | 50 | 42 | 34 | 26 | 18 | 10 |  2 |
//         1 | 89 | 81 | 73 | 65 | 57 | 49 | 41 | 33 | 25 | 17 |  9 |  1 |
//         0 | 88 | 80 | 72 | 64 | 56 | 48 | 40 | 32 | 24 | 16 |  8 |  0 |
//           +----+----+----+----+----+----+----+----+----+----+----+----+
//              0    1    2    3    4    5    6    7    8    9   10   11
//                                  byte address
//
// Note that some big-endian protocols are documented with "bit 0" being the
// *high-order* bit of a number, in which case "bit 0" would be the
// highest-order bit of the first byte in the buffer.  The "bit 0 is the
// high-order bit" style seems to be more common in older documents (e.g., RFCs
// 791 and 793, for IP and TCP), while the Emboss-style "bit 0 is in the last
// byte" seems to be more common in newer documents (e.g., the hardware user
// manuals bolms@ examined).
// TODO(bolms): Examine more documents to see if the old vs new pattern holds.
//
// Because endian-specific reads and writes are handled in ContiguousBuffer,
// this class exists mostly to translate VerbUInt calls to VerbBigEndianUInt.
template <class BufferT>
class BigEndianByteOrderer final {
 public:
  // Type declaration so that BitBlock can use BufferType::BufferType.
  using BufferType = BufferT;

  BigEndianByteOrderer() : buffer_() {}
  explicit BigEndianByteOrderer(BufferType buffer) : buffer_{buffer} {}
  BigEndianByteOrderer(const BigEndianByteOrderer &other) = default;
  BigEndianByteOrderer(BigEndianByteOrderer &&other) = default;
  BigEndianByteOrderer &operator=(const BigEndianByteOrderer &other) = default;

  // Ok() and SizeInBytes() get passed through with no changes.
  bool Ok() const { return buffer_.Ok(); }
  ::std::size_t SizeInBytes() const { return buffer_.SizeInBytes(); }

  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned ReadUInt() const {
    return buffer_.template ReadBigEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned UncheckedReadUInt() const {
    return buffer_.template UncheckedReadBigEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  void WriteUInt(typename LeastWidthInteger<kBits>::Unsigned value) const {
    buffer_.template WriteBigEndianUInt<kBits>(value);
  }
  template </**/ ::std::size_t kBits>
  void UncheckedWriteUInt(
      typename LeastWidthInteger<kBits>::Unsigned value) const {
    buffer_.template UncheckedWriteBigEndianUInt<kBits>(value);
  }

 private:
  BufferType buffer_;
};

// NullByteOrderer is a pass-through adapter for a byte buffer class.  It is
// used to implement single-byte bit blocks, where byte order does not matter.
//
// Technically, it should be valid to swap in BigEndianByteOrderer or
// LittleEndianByteOrderer anywhere that NullByteOrderer is used, but
// NullByteOrderer contains a few extra CHECKs to ensure it is being used
// correctly.
template <class BufferT>
class NullByteOrderer final {
 public:
  // Type declaration so that BitBlock can use BufferType::BufferType.
  using BufferType = BufferT;

  NullByteOrderer() : buffer_() {}
  explicit NullByteOrderer(BufferType buffer) : buffer_{buffer} {}
  NullByteOrderer(const NullByteOrderer &other) = default;
  NullByteOrderer(NullByteOrderer &&other) = default;
  NullByteOrderer &operator=(const NullByteOrderer &other) = default;

  bool Ok() const { return buffer_.Ok(); }
  ::std::size_t SizeInBytes() const { return Ok() ? 1 : 0; }

  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned ReadUInt() const {
    static_assert(kBits == 8, "NullByteOrderer may only read 8-bit values.");
    return buffer_.template ReadLittleEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  typename LeastWidthInteger<kBits>::Unsigned UncheckedReadUInt() const {
    static_assert(kBits == 8, "NullByteOrderer may only read 8-bit values.");
    return buffer_.template UncheckedReadLittleEndianUInt<kBits>();
  }
  template </**/ ::std::size_t kBits>
  void WriteUInt(typename LeastWidthInteger<kBits>::Unsigned value) const {
    static_assert(kBits == 8, "NullByteOrderer may only read 8-bit values.");
    buffer_.template WriteBigEndianUInt<kBits>(value);
  }
  template </**/ ::std::size_t kBits>
  void UncheckedWriteUInt(
      typename LeastWidthInteger<kBits>::Unsigned value) const {
    static_assert(kBits == 8, "NullByteOrderer may only read 8-bit values.");
    buffer_.template UncheckedWriteBigEndianUInt<kBits>(value);
  }

 private:
  BufferType buffer_;
};

// OffsetBitBlock is a filter on another BitBlock class, which adds a fixed
// offset to reads from underlying bit block.  This is used by Emboss generated
// classes to read bitfields: the parent provides an OffsetBitBlock of its
// buffer to the child's view.
//
// OffsetBitBlock is always statically sized, but because
// BitBlock::GetOffsetStorage and OffsetBitBlock::GetOffsetStorage must have the
// same signature as ContiguousBuffer::GetOffsetStorage, OffsetBitBlock's size
// parameter must be a runtime value.
//
// TODO(bolms): Figure out how to add size as a template parameter to
// OffsetBitBlock.
template <class UnderlyingBitBlockType>
class OffsetBitBlock final {
 public:
  using ValueType = typename UnderlyingBitBlockType::ValueType;
  // Bit blocks do not use alignment information, but generated code expects bit
  // blocks to have the same methods and types as byte blocks, so even though
  // kNewAlignment and kNewOffset are unused, they must be present as template
  // parameters.
  template </**/ ::std::size_t kNewAlignment, ::std::size_t kNewOffset>
  using OffsetStorageType = OffsetBitBlock<UnderlyingBitBlockType>;

  OffsetBitBlock() : bit_block_(), offset_(0), size_(0), ok_(false) {}
  explicit OffsetBitBlock(UnderlyingBitBlockType bit_block,
                          ::std::size_t offset, ::std::size_t size, bool ok)
      : bit_block_{bit_block},
        offset_{static_cast</**/ ::std::uint8_t>(offset)},
        size_{static_cast</**/ ::std::uint8_t>(size)},
        ok_{offset == offset_ && size == size_ && ok} {}
  OffsetBitBlock(const OffsetBitBlock &other) = default;
  OffsetBitBlock &operator=(const OffsetBitBlock &other) = default;

  template </**/ ::std::size_t kNewAlignment, ::std::size_t kNewOffset>
  OffsetStorageType<kNewAlignment, kNewOffset> GetOffsetStorage(
      ::std::size_t offset, ::std::size_t size) const {
    return OffsetStorageType<kNewAlignment, kNewOffset>{
        bit_block_, offset_ + offset, size, ok_ && offset + size <= size_};
  }

  // ReadUInt reads the entire underlying bit block, then shifts and masks to
  // the appropriate size.
  ValueType ReadUInt() const {
    EMBOSS_CHECK_GE(bit_block_.SizeInBits(), offset_ + size_);
    EMBOSS_CHECK_GE(bit_block_.SizeInBits(),
                    static_cast</**/ ::std::uint64_t>(offset_ + size_));
    EMBOSS_CHECK(Ok());
    return MaskToNBits(bit_block_.ReadUInt(), offset_ + size_) >> offset_;
  }
  ValueType UncheckedReadUInt() const {
    return MaskToNBits(bit_block_.UncheckedReadUInt(), offset_ + size_) >>
           offset_;
  }

  // WriteUInt writes the entire underlying bit block; in order to only write
  // the specific bits that should be changed, the current value is first read,
  // then masked out and or'ed with the new value, and finally the result is
  // written back to memory.
  void WriteUInt(ValueType value) const {
    EMBOSS_CHECK_EQ(value, MaskToNBits(value, size_));
    EMBOSS_CHECK(Ok());
    // OffsetBitBlock::WriteUInt *always* does a read-modify-write because it is
    // assumed that if the user wanted to read or write the entire value they
    // would just use the underlying BitBlock directly.  This is mostly true for
    // code generated by Emboss, which only uses OffsetBitBlock for subfields of
    // `bits` types; bit-oriented types such as `UInt` will use BitBlock
    // directly when they are placed directly in a `struct`.
    bit_block_.WriteUInt(MaskInValue(bit_block_.ReadUInt(), value));
  }
  void UncheckedWriteUInt(ValueType value) const {
    bit_block_.UncheckedWriteUInt(
        MaskInValue(bit_block_.UncheckedReadUInt(), value));
  }

  ::std::size_t SizeInBits() const { return size_; }
  bool Ok() const { return ok_; }

 private:
  ValueType MaskInValue(ValueType original_value, ValueType new_value) const {
    ValueType original_mask = static_cast<ValueType>(~(
        MaskToNBits(static_cast<ValueType>(~ValueType{0}), size_) << offset_));
    return static_cast<ValueType>((original_value & original_mask) |
                                  (new_value << offset_));
  }

  const UnderlyingBitBlockType bit_block_;
  const ::std::uint8_t offset_;
  const ::std::uint8_t size_;
  const ::std::uint8_t ok_;
};

// BitBlock is a view of a short, fixed-size sequence of bits somewhere in
// memory.  Big- and little-endian values are handled by BufferType, which is
// typically BigEndianByteOrderer<ContiguousBuffer<...>> or
// LittleEndianByteOrderer<ContiguousBuffer<...>>.
//
// BitBlock is implemented such that it always reads and writes its entire
// buffer; unlike ContiguousBuffer for bytes, there is no way to modify part of
// the underlying data without doing a read-modify-write of the full value.
// This sidesteps a lot of weirdness with converting between bit addresses and
// byte addresses for big-endian values, though it does mean that in certain
// cases excess bits will be read or written, particularly if care is not taken
// in the .emb definition to keep `bits` types to a minimum size.
template <class BufferType, ::std::size_t kBufferSizeInBits>
class BitBlock final {
  static_assert(kBufferSizeInBits % 8 == 0,
                "BitBlock can only operate on byte buffers.");
  static_assert(kBufferSizeInBits <= 64,
                "BitBlock can only operate on small buffers.");

 public:
  using ValueType = typename LeastWidthInteger<kBufferSizeInBits>::Unsigned;
  // As with OffsetBitBlock::OffsetStorageType, the kNewAlignment and kNewOffset
  // values are not used, but they must be template parameters so that generated
  // code can work with both BitBlock and ContiguousBuffer.
  template </**/ ::std::size_t kNewAlignment, ::std::size_t kNewOffset>
  using OffsetStorageType =
      OffsetBitBlock<BitBlock<BufferType, kBufferSizeInBits>>;

  explicit BitBlock() : buffer_() {}
  explicit BitBlock(BufferType buffer) : buffer_{buffer} {}
  explicit BitBlock(typename BufferType::BufferType buffer) : buffer_{buffer} {}
  BitBlock(const BitBlock &) = default;
  BitBlock(BitBlock &&) = default;
  BitBlock &operator=(const BitBlock &) = default;
  BitBlock &operator=(BitBlock &&) = default;
  ~BitBlock() = default;

  static constexpr ::std::size_t Bits() { return kBufferSizeInBits; }

  template </**/ ::std::size_t kNewAlignment, ::std::size_t kNewOffset>
  OffsetStorageType<kNewAlignment, kNewOffset> GetOffsetStorage(
      ::std::size_t offset, ::std::size_t size) const {
    return OffsetStorageType<kNewAlignment, kNewOffset>{
        *this, offset, size, Ok() && offset + size <= kBufferSizeInBits};
  }

  // BitBlock clients must read or write the entire BitBlock value as an
  // unsigned integer.  OffsetBitBlock can be used to extract a portion of the
  // value via shift and mask, and individual view types such as IntView or
  // BcdView are expected to convert ValueType to/from their desired types.
  ValueType ReadUInt() const {
    return buffer_.template ReadUInt<kBufferSizeInBits>();
  }
  ValueType UncheckedReadUInt() const {
    return buffer_.template UncheckedReadUInt<kBufferSizeInBits>();
  }
  void WriteUInt(ValueType value) const {
    EMBOSS_CHECK_EQ(value, MaskToNBits(value, kBufferSizeInBits));
    buffer_.template WriteUInt<kBufferSizeInBits>(value);
  }
  void UncheckedWriteUInt(ValueType value) const {
    buffer_.template UncheckedWriteUInt<kBufferSizeInBits>(value);
  }

  ::std::size_t SizeInBits() const { return kBufferSizeInBits; }
  bool Ok() const {
    return buffer_.Ok() && buffer_.SizeInBytes() * 8 == kBufferSizeInBits;
  }

 private:
  BufferType buffer_;
};

}  // namespace support
}  // namespace emboss

#endif  // EMBOSS_RUNTIME_CPP_EMBOSS_MEMORY_UTIL_H_
