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

// This header contains implementations of the types in the Emboss Prelude
// (UInt, Int, Flag, etc.)
#ifndef EMBOSS_RUNTIME_CPP_EMBOSS_PRELUDE_H_
#define EMBOSS_RUNTIME_CPP_EMBOSS_PRELUDE_H_

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include <limits>
#include <type_traits>
#include <utility>

#include "runtime/cpp/emboss_cpp_util.h"

// This namespace must match the [(cpp) namespace] in the Emboss prelude.
namespace emboss {
namespace prelude {

// FlagView is the C++ implementation of the Emboss "Flag" type, which is a
// 1-bit value.
template <class Parameters, class BitBlock>
class FlagView final {
 public:
  static_assert(Parameters::kBits == 1, "FlagView must be 1 bit.");

  explicit FlagView(BitBlock bits) : bit_block_{bits} {}
  FlagView() : bit_block_() {}
  FlagView(const FlagView &) = default;
  FlagView(FlagView &&) = default;
  FlagView &operator=(const FlagView &) = default;
  FlagView &operator=(FlagView &&) = default;
  ~FlagView() = default;

  bool Read() const {
    bool result = bit_block_.ReadUInt();
    EMBOSS_CHECK(Parameters::ValueIsOk(result));
    return result;
  }
  bool UncheckedRead() const { return bit_block_.UncheckedReadUInt(); }
  void Write(bool value) const { EMBOSS_CHECK(TryToWrite(value)); }
  bool TryToWrite(bool value) const {
    if (!CouldWriteValue(value)) return false;
    if (!IsComplete()) return false;
    bit_block_.WriteUInt(value);
    return true;
  }
  static constexpr bool CouldWriteValue(bool value) {
    return Parameters::ValueIsOk(value);
  }
  void UncheckedWrite(bool value) const {
    bit_block_.UncheckedWriteUInt(value);
  }

  template <typename OtherView>
  void CopyFrom(const OtherView &other) const {
    Write(other.Read());
  }
  template <typename OtherView>
  void UncheckedCopyFrom(const OtherView &other) const {
    UncheckedWrite(other.UncheckedRead());
  }
  template <typename OtherView>
  bool TryToCopyFrom(const OtherView &other) const {
    return TryToWrite(other.Read());
  }

  bool Ok() const {
    return IsComplete() && Parameters::ValueIsOk(UncheckedRead());
  }
  template <class OtherBitBlock>
  bool Equals(const FlagView<Parameters, OtherBitBlock> &other) const {
    return Read() == other.Read();
  }
  template <class OtherBitBlock>
  bool UncheckedEquals(const FlagView<Parameters, OtherBitBlock> &other) const {
    return UncheckedRead() == other.UncheckedRead();
  }
  bool IsComplete() const {
    return bit_block_.Ok() && bit_block_.SizeInBits() > 0;
  }

  template <class Stream>
  bool UpdateFromTextStream(Stream *stream) const {
    ::std::string token;
    if (!::emboss::support::ReadToken(stream, &token)) return false;
    if (token == "true") {
      return TryToWrite(true);
    } else if (token == "false") {
      return TryToWrite(false);
    }
    // TODO(bolms): Provide a way to get an error message on parse failure.
    return false;
  }

  template <class Stream>
  void WriteToTextStream(Stream *stream,
                         const ::emboss::TextOutputOptions &options) const {
    ::emboss::support::WriteBooleanViewToTextStream(this, stream, options);
  }

 private:
  BitBlock bit_block_;
};

// UIntView is a view for UInts inside of bitfields.
template <class Parameters, class BitViewType>
class UIntView final {
 public:
  using ValueType = typename ::emboss::support::LeastWidthInteger<
      Parameters::kBits>::Unsigned;

  static_assert(
      Parameters::kBits <= sizeof(ValueType) * 8,
      "UIntView requires sizeof(ValueType) * 8 >= Parameters::kBits.");

  template <typename... Args>
  explicit UIntView(Args &&... args) : buffer_{::std::forward<Args>(args)...} {}
  UIntView() : buffer_() {}
  UIntView(const UIntView &) = default;
  UIntView(UIntView &&) = default;
  UIntView &operator=(const UIntView &) = default;
  UIntView &operator=(UIntView &&) = default;
  ~UIntView() = default;

  ValueType Read() const {
    ValueType result = buffer_.ReadUInt();
    EMBOSS_CHECK(Parameters::ValueIsOk(result));
    return result;
  }
  ValueType UncheckedRead() const { return buffer_.UncheckedReadUInt(); }

  // The Write, TryToWrite, and CouldWriteValue methods are templated in order
  // to avoid surprises due to implicit narrowing.
  //
  // In C++, you can pass (say) an `int` to a function expecting `uint8_t`, and
  // the compiler will silently cast the `int` to `uint8_t`, which can change
  // the value.  Even with fairly aggressive warnings, something like this will
  // silently compile, and print `256 is not >= 128!`:
  //
  //    bool is_big_uint8(uint8_t value) { return value >= 128; }
  //    bool is_big(uint32_t value) { return is_big_uint8(value); }
  //    int main() {
  //        assert(!is_big(256));  // big is truncated to 0.
  //        std::cout << 256 << " is not >= 128!\n";
  //        return 0;
  //    }
  //
  // (Most compilers will give a warning when directly passing a *constant* that
  // gets truncated; for example, GCC will throw -Woverflow on
  // `is_big_uint8(256U)`.)
  template <typename IntT,
            typename = typename ::std::enable_if<
                (::std::numeric_limits<typename ::std::remove_cv<
                     typename ::std::remove_reference<IntT>::type>::type>::
                     is_integer &&
                 !::std::is_same<bool, typename ::std::remove_cv<
                                           typename ::std::remove_reference<
                                               IntT>::type>::type>::value) ||
                ::std::is_enum<IntT>::value>::type>
  void Write(IntT value) const {
    EMBOSS_CHECK(TryToWrite(value));
  }

  template <typename IntT,
            typename = typename ::std::enable_if<
                (::std::numeric_limits<typename ::std::remove_cv<
                     typename ::std::remove_reference<IntT>::type>::type>::
                     is_integer &&
                 !::std::is_same<bool, typename ::std::remove_cv<
                                           typename ::std::remove_reference<
                                               IntT>::type>::type>::value) ||
                ::std::is_enum<IntT>::value>::type>
  bool TryToWrite(IntT value) const {
    if (!CouldWriteValue(value)) return false;
    if (!IsComplete()) return false;
    buffer_.WriteUInt(value);
    return true;
  }

  template <typename IntT,
            typename = typename ::std::enable_if<
                (::std::numeric_limits<typename ::std::remove_cv<
                     typename ::std::remove_reference<IntT>::type>::type>::
                     is_integer &&
                 !::std::is_same<bool, typename ::std::remove_cv<
                                           typename ::std::remove_reference<
                                               IntT>::type>::type>::value) ||
                ::std::is_enum<IntT>::value>::type>
  static constexpr bool CouldWriteValue(IntT value) {
    // Implicit conversions are doing some work here, but the upshot is that the
    // value must be at least 0, and at most (2**kBits)-1.  The clause to
    // compute (2**kBits)-1 should not be "simplified" further.
    //
    // Because of C++ implicit integer promotions, the (2**kBits)-1 computation
    // works differently when `ValueType` is smaller than `unsigned int` than it
    // does when `ValueType` is at least as big as `unsigned int`.
    //
    // For example, when `ValueType` is `uint8_t` and `kBits` is 8:
    //
    // 1.   `static_cast<ValueType>(1)` becomes `uint8_t(1)`.
    // 2.   `uint8_t(1) << (kBits - 1)` is `uint8_t(1) << 7`.
    // 3.   The shift operator `<<` promotes its left operand to `unsigned`,
    //      giving `unsigned(1) << 7`.
    // 4.   `unsigned(1) << 7` becomes `unsigned(0x80)`.
    // 5.   `unsigned(0x80) << 1` becomes `unsigned(0x100)`.
    // 6.   Finally, `unsigned(0x100) - 1` is `unsigned(0xff)`.
    //
    // (Note that the cases where `kBits` is less than `sizeof(ValueType) * 8`
    // are very similar.)
    //
    // When `ValueType` is `uint32_t`, `unsigned` is 32 bits, and `kBits` is 32:
    //
    // 1.   `static_cast<ValueType>(1)` becomes `uint32_t(1)`.
    // 2.   `uint32_t(1) << (kBits - 1)` is `uint32_t(1) << 31`.
    // 3.   The shift operator `<<` does *not* further promote `uint32_t`.
    // 4.   `uint32_t(1) << 31` becomes `uint32_t(0x80000000)`.  Note that
    //      `uint32_t(1) << 32` would be undefined behavior (shift of >= the
    //      size of the left operand type), which is why the shift is broken
    //      into two parts.
    // 5.   `uint32_t(0x80000000) << 1` overflows, leaving `uint32_t(0)`.
    // 6.   `uint32_t(0) - 1` underflows, leaving `uint32_t(0xffffffff)`.
    //
    // Because unsigned overflow and underflow are defined to be modulo 2**N,
    // where N is the number of bits in the type, this is entirely
    // standards-compliant.
    return value >= 0 &&
           static_cast</**/ ::std::uint64_t>(value) <=
               ((static_cast<ValueType>(1) << (Parameters::kBits - 1)) << 1) -
                   1 &&
           Parameters::ValueIsOk(value);
  }
  void UncheckedWrite(ValueType value) const {
    buffer_.UncheckedWriteUInt(value);
  }

  template <typename OtherView>
  void CopyFrom(const OtherView &other) const {
    Write(other.Read());
  }
  template <typename OtherView>
  void UncheckedCopyFrom(const OtherView &other) const {
    UncheckedWrite(other.UncheckedRead());
  }
  template <typename OtherView>
  bool TryToCopyFrom(const OtherView &other) const {
    return other.Ok() && TryToWrite(other.Read());
  }

  // All bit patterns in the underlying buffer are valid, so Ok() is always
  // true if IsComplete() is true.
  bool Ok() const {
    return IsComplete() && Parameters::ValueIsOk(UncheckedRead());
  }
  template <class OtherBitViewType>
  bool Equals(const UIntView<Parameters, OtherBitViewType> &other) const {
    return Read() == other.Read();
  }
  template <class OtherBitViewType>
  bool UncheckedEquals(
      const UIntView<Parameters, OtherBitViewType> &other) const {
    return UncheckedRead() == other.UncheckedRead();
  }
  bool IsComplete() const {
    return buffer_.Ok() && buffer_.SizeInBits() >= Parameters::kBits;
  }

  template <class Stream>
  bool UpdateFromTextStream(Stream *stream) const {
    return support::ReadIntegerFromTextStream(this, stream);
  }

  template <class Stream>
  void WriteToTextStream(Stream *stream,
                         ::emboss::TextOutputOptions options) const {
    support::WriteIntegerViewToTextStream(this, stream, options);
  }

  static constexpr int SizeInBits() { return Parameters::kBits; }

 private:
  BitViewType buffer_;
};

// IntView is a view for Ints inside of bitfields.
template <class Parameters, class BitViewType>
class IntView final {
 public:
  using ValueType =
      typename ::emboss::support::LeastWidthInteger<Parameters::kBits>::Signed;

  static_assert(Parameters::kBits <= sizeof(ValueType) * 8,
                "IntView requires sizeof(ValueType) * 8 >= Parameters::kBits.");

  template <typename... Args>
  explicit IntView(Args &&... args) : buffer_{::std::forward<Args>(args)...} {}
  IntView() : buffer_() {}
  IntView(const IntView &) = default;
  IntView(IntView &&) = default;
  IntView &operator=(const IntView &) = default;
  IntView &operator=(IntView &&) = default;
  ~IntView() = default;

  ValueType Read() const {
    ValueType value = ConvertToSigned(buffer_.ReadUInt());
    EMBOSS_CHECK(Parameters::ValueIsOk(value));
    return value;
  }
  ValueType UncheckedRead() const {
    return ConvertToSigned(buffer_.UncheckedReadUInt());
  }
  // As with UIntView, above, Write, TryToWrite, and CouldWriteValue need to be
  // templated in order to avoid surprises due to implicit narrowing
  // conversions.
  template <typename IntT,
            typename = typename ::std::enable_if<
                (::std::numeric_limits<typename ::std::remove_cv<
                     typename ::std::remove_reference<IntT>::type>::type>::
                     is_integer &&
                 !::std::is_same<bool, typename ::std::remove_cv<
                                           typename ::std::remove_reference<
                                               IntT>::type>::type>::value) ||
                ::std::is_enum<IntT>::value>::type>
  void Write(IntT value) const {
    EMBOSS_CHECK(TryToWrite(value));
  }

  template <typename IntT,
            typename = typename ::std::enable_if<
                (::std::numeric_limits<typename ::std::remove_cv<
                     typename ::std::remove_reference<IntT>::type>::type>::
                     is_integer &&
                 !::std::is_same<bool, typename ::std::remove_cv<
                                           typename ::std::remove_reference<
                                               IntT>::type>::type>::value) ||
                ::std::is_enum<IntT>::value>::type>
  bool TryToWrite(IntT value) const {
    if (!CouldWriteValue(value)) return false;
    if (!IsComplete()) return false;
    buffer_.WriteUInt(::emboss::support::MaskToNBits(
        static_cast<typename BitViewType::ValueType>(value),
        Parameters::kBits));
    return true;
  }

  template <typename IntT,
            typename = typename ::std::enable_if<
                (::std::numeric_limits<typename ::std::remove_cv<
                     typename ::std::remove_reference<IntT>::type>::type>::
                     is_integer &&
                 !::std::is_same<bool, typename ::std::remove_cv<
                                           typename ::std::remove_reference<
                                               IntT>::type>::type>::value) ||
                ::std::is_enum<IntT>::value>::type>
  static constexpr bool CouldWriteValue(IntT value) {
    // This effectively checks that value >= -(2**(kBits-1) and value <=
    // (2**(kBits-1))-1.
    //
    // This has to be done somewhat piecemeal, in order to avoid various bits of
    // undefined and implementation-defined behavior.
    //
    // First, if IntT is an unsigned type, the check that value >=
    // -(2**(kBits-1)) is skipped, in order to avoid any signed <-> unsigned
    // conversions.
    //
    // Second, if kBits is 1, then the limits -1 and 0 are explicit, so that
    // there is never a shift by -1 (which is undefined behavior).
    //
    // Third, the shifts are by (kBits - 2), so that they do not alter sign
    // bits.  To get the final bounds, we use a bit of addition and
    // multiplication.  For example, for 8 bits, the lower bound is (1 << 6) *
    // -2, which is 64 * -2, which is -128.  The corresponding upper bound is
    // ((1 << 6) - 1) * 2 + 1, which is (64 - 1) * 2 + 1, which is 63 * 2 + 1,
    // which is 126 + 1, which is 127.  The upper bound must be computed in
    // multiple steps like this in order to avoid overflow.
    return (!::std::is_signed<typename ::std::remove_cv<
                typename ::std::remove_reference<IntT>::type>::type>::value ||
            static_cast</**/ ::std::int64_t>(value) >=
                (Parameters::kBits == 1
                     ? -1
                     : (static_cast<ValueType>(1) << (Parameters::kBits - 2)) *
                           -2)) &&
           value <=
               (Parameters::kBits == 1
                    ? 0
                    : ((static_cast<ValueType>(1) << (Parameters::kBits - 2)) -
                       1) * 2 +
                          1) &&
           Parameters::ValueIsOk(value);
  }

  void UncheckedWrite(ValueType value) const {
    buffer_.UncheckedWriteUInt(::emboss::support::MaskToNBits(
        static_cast<typename BitViewType::ValueType>(value),
        Parameters::kBits));
  }

  template <typename OtherView>
  void CopyFrom(const OtherView &other) const {
    Write(other.Read());
  }
  template <typename OtherView>
  void UncheckedCopyFrom(const IntView &other) const {
    UncheckedWrite(other.UncheckedRead());
  }
  template <typename OtherView>
  bool TryToCopyFrom(const OtherView &other) const {
    return other.Ok() && TryToWrite(other.Read());
  }

  // All bit patterns in the underlying buffer are valid, so Ok() is always
  // true if IsComplete() is true.
  bool Ok() const {
    return IsComplete() && Parameters::ValueIsOk(UncheckedRead());
  }
  template <class OtherBitViewType>
  bool Equals(const IntView<Parameters, OtherBitViewType> &other) const {
    return Read() == other.Read();
  }
  template <class OtherBitViewType>
  bool UncheckedEquals(
      const IntView<Parameters, OtherBitViewType> &other) const {
    return UncheckedRead() == other.UncheckedRead();
  }
  bool IsComplete() const {
    return buffer_.Ok() && buffer_.SizeInBits() >= Parameters::kBits;
  }

  template <class Stream>
  bool UpdateFromTextStream(Stream *stream) const {
    return support::ReadIntegerFromTextStream(this, stream);
  }

  template <class Stream>
  void WriteToTextStream(Stream *stream,
                         ::emboss::TextOutputOptions options) const {
    support::WriteIntegerViewToTextStream(this, stream, options);
  }

  static constexpr int SizeInBits() { return Parameters::kBits; }

 private:
  static ValueType ConvertToSigned(typename BitViewType::ValueType data) {
    static_assert(sizeof(ValueType) <= sizeof(typename BitViewType::ValueType),
                  "Integer types wider than BitViewType::ValueType are not "
                  "supported.");
#if EMBOSS_SYSTEM_IS_TWOS_COMPLEMENT
    // static_cast from unsigned to signed is implementation-defined when the
    // value does not fit in the signed type (in this case, when the final value
    // should be negative).  Most implementations use a reasonable definition,
    // so on most systems we can just cast.
    //
    // If the integer does not take up the full width of ValueType, it needs to
    // be sign-extended until it does.  The easiest way to do this is to shift
    // until the sign bit is in the topmost position, then cast to signed, then
    // shift back.  The shift back will copy the sign bit.
    return static_cast<ValueType>(
               data << (sizeof(ValueType) * 8 - Parameters::kBits)) >>
           (sizeof(ValueType) * 8 - Parameters::kBits);
#else
    // Otherwise, in order to convert without running into
    // implementation-defined behavior, first mask out the sign bit.  This
    // results in (final result MOD 2 ** (width of int in bits - 1)).  That
    // value can be safely converted to the signed ValueType.
    //
    // Finally, if the sign bit was set, subtract (2 ** (width of int in bits -
    // 2)) twice.
    //
    // The 1-bit signed integer case must be handled separately, but it is
    // (fortunately) quite easy to enumerate both possible values.
    if (Parameters::kBits == 1) {
      if (data == 0) {
        return 0;
      } else if (data == 1) {
        return -1;
      } else {
        EMBOSS_CHECK(false);
      }
    } else {
      typename BitViewType::ValueType sign_bit =
          static_cast<typename BitViewType::ValueType>(1)
          << (Parameters::kBits - 1);
      typename BitViewType::ValueType mask = sign_bit - 1;
      typename BitViewType::ValueType data_mod2_to_n = mask & data;
      ValueType result_sign_bit =
          static_cast<ValueType>((data & sign_bit) >> 1);
      return data_mod2_to_n - result_sign_bit - result_sign_bit;
    }
#endif
  }

  BitViewType buffer_;
};

// The maximum Binary-Coded Decimal (BCD) value that fits in a particular number
// of bits.
template <typename ValueType>
constexpr inline ValueType MaxBcd(int bits) {
  return bits < 4 ? (1 << bits) - 1
                  : 10 * (MaxBcd<ValueType>(bits - 4) + 1) - 1;
}

template <typename ValueType>
inline bool IsBcd(ValueType x) {
  // Adapted from:
  // https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord
  //
  // This determines if any nibble has a value greater than 9.  It does
  // this by treating operations on the n-bit value as parallel operations
  // on n/4 4-bit values.
  //
  // The result is computed in the high bit of each nibble: if any of those
  // bits is set in the end, then at least one nibble had a value in the
  // range 10-15.
  //
  // The first check is subtle: ~x is equivalent to (nibble = 15 - nibble).
  // Then, 6 is subtracted from each nibble.  This operation will underflow
  // if the original value was more than 9, leaving the high bit of the
  // nibble set.  It will also leave the high bit of the nibble set
  // (without underflow) if the original value was 0 or 1.
  //
  // The second check is just x: the high bit of each nibble in x is set if
  // that nibble's value is 8-15.
  //
  // Thus, the first check leaves the high bit set in any nibble with the
  // value 0, 1, or 10-15, and the second check leaves the high bit set in
  // any nibble with the value 8-15.  Bitwise-anding these results, high
  // bits are only set if the original value was 10-15.
  //
  // The underflow condition in the first check can screw up the condition
  // for nibbles in higher positions than the underflowing nibble.  This
  // cannot affect the overall boolean result, because the underflow
  // condition only happens if a nibble was greater than 9, and therefore
  // *that* nibble's final value will be nonzero, and therefore the whole
  // result will be nonzero, no matter what happens in the higher-order
  // nibbles.
  //
  // A couple of examples in 16 bit:
  //
  // x = 0x09a8
  // (~0x09a8 - 0x6666) & 0x09a8 & 0x8888
  // ( 0xf657 - 0x6666) & 0x09a8 & 0x8888
  //            0x8ff1  & 0x09a8 & 0x8888
  //                      0x09a0 & 0x8888
  //                               0x0880  Note the underflow into nibble 2
  //
  // x = 0x1289
  // (~0x1289 - 0x6666) & 0x1289 & 0x8888
  // ( 0xed76 - 0x6666) & 0x1289 & 0x8888
  //            0x8710  & 0x1289 & 0x8888
  //                      0x0200 & 0x8888
  //                               0x0000
  static_assert(!::std::is_signed<ValueType>::value,
                "IsBcd only works on unsigned values.");
  if (sizeof(ValueType) < sizeof(unsigned)) {
    // For types with lower integer conversion rank than unsigned int, integer
    // promotion rules cause many implicit conversions to signed int in the math
    // below, which makes the math go wrong.  Rather than add a dozen explicit
    // casts back to ValueType, just do the math as 'unsigned'.
    return IsBcd<unsigned>(x);
  } else {
    return ((~x - (~ValueType{0} / 0xf * 0x6 /* 0x6666...6666 */)) & x &
            (~ValueType{0} / 0xf * 0x8 /* 0x8888...8888 */)) == 0;
  }
}

// Base template for Binary-Coded Decimal (BCD) unsigned integer readers.
template <class Parameters, class BitViewType>
class BcdView final {
 public:
  using ValueType = typename ::emboss::support::LeastWidthInteger<
      Parameters::kBits>::Unsigned;

  static_assert(Parameters::kBits <= sizeof(ValueType) * 8,
                "BcdView requires sizeof(ValueType) * 8 >= Parameters::kBits.");

  template <typename... Args>
  explicit BcdView(Args &&... args) : buffer_{::std::forward<Args>(args)...} {}
  BcdView() : buffer_() {}
  BcdView(const BcdView &) = default;
  BcdView(BcdView &&) = default;
  BcdView &operator=(const BcdView &) = default;
  BcdView &operator=(BcdView &&) = default;
  ~BcdView() = default;

  ValueType Read() const {
    EMBOSS_CHECK(Ok());
    return ConvertToBinary(buffer_.ReadUInt());
  }
  ValueType UncheckedRead() const {
    return ConvertToBinary(buffer_.UncheckedReadUInt());
  }
  void Write(ValueType value) const { EMBOSS_CHECK(TryToWrite(value)); }
  bool TryToWrite(ValueType value) const {
    if (!CouldWriteValue(value)) return false;
    if (!IsComplete()) return false;
    buffer_.WriteUInt(ConvertToBcd(value));
    return true;
  }
  static constexpr bool CouldWriteValue(ValueType value) {
    return value <= MaxValue() && Parameters::ValueIsOk(value);
  }
  void UncheckedWrite(ValueType value) const {
    buffer_.UncheckedWriteUInt(ConvertToBcd(value));
  }

  template <class Stream>
  bool UpdateFromTextStream(Stream *stream) const {
    return support::ReadIntegerFromTextStream(this, stream);
  }

  template <class Stream>
  void WriteToTextStream(Stream *stream,
                         ::emboss::TextOutputOptions options) const {
    // TODO(bolms): This shares the numeric_base() option with IntView and
    // UIntView (and EnumView, for unknown enum values).  It seems like an end
    // user might prefer to see BCD values in decimal, even if they want to see
    // values of other numeric types in hex or binary.  It seems like there
    // could be some fancy C++ trickery to allow separate options for separate
    // view types.
    support::WriteIntegerViewToTextStream(this, stream, options);
  }

  template <typename OtherView>
  void CopyFrom(const OtherView &other) const {
    Write(other.Read());
  }
  template <typename OtherView>
  void UncheckedCopyFrom(const OtherView &other) const {
    UncheckedWrite(other.UncheckedRead());
  }
  template <typename OtherView>
  bool TryToCopyFrom(const OtherView &other) const {
    return other.Ok() && TryToWrite(other.Read());
  }

  bool Ok() const {
    if (!IsComplete()) return false;
    if (!IsBcd(buffer_.ReadUInt())) return false;
    if (!Parameters::ValueIsOk(UncheckedRead())) return false;
    return true;
  }
  template <class OtherBitViewType>
  bool Equals(const BcdView<Parameters, OtherBitViewType> &other) const {
    return Read() == other.Read();
  }
  template <class OtherBitViewType>
  bool UncheckedEquals(
      const BcdView<Parameters, OtherBitViewType> &other) const {
    return UncheckedRead() == other.UncheckedRead();
  }
  bool IsComplete() const {
    return buffer_.Ok() && buffer_.SizeInBits() >= Parameters::kBits;
  }

  static constexpr int SizeInBits() { return Parameters::kBits; }

 private:
  static ValueType ConvertToBinary(ValueType bcd_value) {
    ValueType result = 0;
    ValueType multiplier = 1;
    for (int shift = 0; shift < Parameters::kBits; shift += 4) {
      result += ((bcd_value >> shift) & 0xf) * multiplier;
      multiplier *= 10;
    }
    return result;
  }

  static ValueType ConvertToBcd(ValueType value) {
    ValueType bcd_value = 0;
    for (int shift = 0; shift < Parameters::kBits; shift += 4) {
      bcd_value |= (value % 10) << shift;
      value /= 10;
    }
    return bcd_value;
  }

  static constexpr ValueType MaxValue() {
    return MaxBcd<ValueType>(Parameters::kBits);
  }

  BitViewType buffer_;
};

// FloatView is the view for the Emboss Float type.
template <class Parameters, class BitViewType>
class FloatView final {
  static_assert(Parameters::kBits == 32 || Parameters::kBits == 64,
                "Only 32- and 64-bit floats are currently supported.");

 public:
  using ValueType = typename support::FloatType<Parameters::kBits>::Type;

  template <typename... Args>
  explicit FloatView(Args &&... args)
      : buffer_{::std::forward<Args>(args)...} {}
  FloatView() : buffer_() {}
  FloatView(const FloatView &) = default;
  FloatView(FloatView &&) = default;
  FloatView &operator=(const FloatView &) = default;
  FloatView &operator=(FloatView &&) = default;
  ~FloatView() = default;

  ValueType Read() const { return ConvertToFloat(buffer_.ReadUInt()); }
  ValueType UncheckedRead() const {
    return ConvertToFloat(buffer_.UncheckedReadUInt());
  }
  void Write(ValueType value) const { EMBOSS_CHECK(TryToWrite(value)); }
  bool TryToWrite(ValueType value) const {
    if (!CouldWriteValue(value)) return false;
    if (!IsComplete()) return false;
    buffer_.WriteUInt(ConvertToUInt(value));
    return true;
  }
  static constexpr bool CouldWriteValue(ValueType value) { return true; }
  void UncheckedWrite(ValueType value) const {
    buffer_.UncheckedWriteUInt(ConvertToUInt(value));
  }

  template <typename OtherView>
  void CopyFrom(const OtherView &other) const {
    Write(other.Read());
  }
  template <typename OtherView>
  void UncheckedCopyFrom(const OtherView &other) const {
    UncheckedWrite(other.UncheckedRead());
  }
  template <typename OtherView>
  bool TryToCopyFrom(const OtherView &other) const {
    return other.Ok() && TryToWrite(other.Read());
  }

  // All bit patterns in the underlying buffer are valid, so Ok() is always
  // true if IsComplete() is true.
  bool Ok() const { return IsComplete(); }
  template <class OtherBitViewType>
  bool Equals(const FloatView<Parameters, OtherBitViewType> &other) const {
    return Read() == other.Read();
  }
  template <class OtherBitViewType>
  bool UncheckedEquals(
      const FloatView<Parameters, OtherBitViewType> &other) const {
    return UncheckedRead() == other.UncheckedRead();
  }
  bool IsComplete() const {
    return buffer_.Ok() && buffer_.SizeInBits() >= Parameters::kBits;
  }

  template <class Stream>
  bool UpdateFromTextStream(Stream *stream) const {
    return support::ReadFloatFromTextStream(this, stream);
  }

  template <class Stream>
  void WriteToTextStream(Stream *stream,
                         ::emboss::TextOutputOptions options) const {
    support::WriteFloatToTextStream(Read(), stream, options);
  }

  static constexpr int SizeInBits() { return Parameters::kBits; }

 private:
  using UIntType = typename support::FloatType<Parameters::kBits>::UIntType;
  static ValueType ConvertToFloat(UIntType bits) {
    // TODO(bolms): This method assumes a few things that are not always
    // strictly true; e.g., that uint32_t and float have the same endianness.
    ValueType result;
    memcpy(static_cast<void *>(&result), static_cast<void *>(&bits),
           sizeof result);
    return result;
  }

  static UIntType ConvertToUInt(ValueType value) {
    // TODO(bolms): This method assumes a few things that are not always
    // strictly true; e.g., that uint32_t and float have the same endianness.
    UIntType bits;
    memcpy(static_cast<void *>(&bits), static_cast<void *>(&value),
           sizeof bits);
    return bits;
  }

  BitViewType buffer_;
};

}  // namespace prelude
}  // namespace emboss

#endif  // EMBOSS_RUNTIME_CPP_EMBOSS_PRELUDE_H_
