// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_FIELD_H_
#define SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_FIELD_H_

#include <lib/stdcompat/bit.h>
#include <lib/stdcompat/type_traits.h>
#include <lib/stdcompat/utility.h>

#include <cstdint>

namespace elfldltl {

// This wraps an unsigned integer type T, which might need byte-swapping.
// If kSwap is false, this is a fancy way to just define a plain integer.
// If kSwap is true, then assignments, extractions, and comparisons (only
// == and != are supported, not all inequalities) perform byte-swapping.
// The type is constexpr friendly and safely default (zero) constructible.
// But it's usually used only via a pointer to memory holding data from an
// ELF file or target process memory.
template <typename T, bool kSwap>
class UnsignedField;

// This is like UnsignedField but for signed integer types.
// Note that T is the corresponding unsigned integer type, not
// the signed integer type.  The SignedField<T> object behaves
// for implicit conversions like the signed integer type.

template <typename T, bool kSwap>
class SignedField;

template <typename T, bool kSwap>
class FieldStorage {
 public:
  using value_type = T;

  static_assert(std::is_integral_v<value_type>);
  static_assert(std::is_unsigned_v<value_type>);

  using Unsigned = FieldStorage<T, kSwap>;
  using Signed = SignedField<T, kSwap>;

  constexpr FieldStorage() = default;

  constexpr FieldStorage(const FieldStorage&) = default;

  explicit constexpr FieldStorage(value_type x) : value_(Convert(x)) {}

  explicit constexpr FieldStorage(std::array<std::byte, sizeof(value_type)> bytes)
      : value_(Convert(bytes)) {}

  explicit constexpr FieldStorage(std::array<char, sizeof(value_type)> bytes)
      : value_(Convert(bytes)) {}

  constexpr FieldStorage& operator=(const FieldStorage&) = default;

  constexpr FieldStorage& operator=(value_type x) {
    value_ = Convert(x);
    return *this;
  }

  constexpr value_type get() const { return Convert(value_); }

 private:
  template <typename Byte, typename = std::enable_if_t<sizeof(Byte) == 1>>
  static constexpr value_type Convert(std::array<Byte, sizeof(value_type)> bytes) {
    auto [first, last] = [&bytes]() {
      if constexpr (cpp20::endian::native == cpp20::endian::little) {
        return std::make_pair(bytes.crbegin(), bytes.crend());
      } else if constexpr (cpp20::endian::native == cpp20::endian::big) {
        return std::make_pair(bytes.cbegin(), bytes.cend());
      }
    }();
    value_type x{};
    for (auto it = first; it != last; ++it) {
      x <<= 8;
      x |= cpp20::bit_cast<uint8_t>(*it);
    }
    return x;
  }

  static constexpr value_type Convert(value_type val) {
    if constexpr (kSwap) {
      // These are portable expressions for byte-swapping but the compiler will
      // recognize the pattern and emit the optimal single instruction or two.
      if constexpr (sizeof(value_type) == sizeof(uint64_t)) {
        val = (((val >> 56) & 0xff) << 0) | (((val >> 48) & 0xff) << 8) |
              (((val >> 40) & 0xff) << 16) | (((val >> 32) & 0xff) << 24) |
              (((val >> 24) & 0xff) << 32) | (((val >> 16) & 0xff) << 40) |
              (((val >> 8) & 0xff) << 48) | (((val >> 0) & 0xff) << 56);
      } else if constexpr (sizeof(value_type) == sizeof(uint32_t)) {
        val = (((val >> 24) & 0xff) << 0) | (((val >> 16) & 0xff) << 8) |
              (((val >> 8) & 0xff) << 16) | (((val >> 0) & 0xff) << 24);
      } else if constexpr (sizeof(value_type) == sizeof(uint16_t)) {
        val = static_cast<value_type>(((val >> 8) & 0xff) << 0) |
              static_cast<value_type>(((val >> 0) & 0xff) << 8);
      } else {
        static_assert(sizeof(value_type) == sizeof(uint8_t));
      }
    }
    return val;
  }

  value_type value_{};
};

template <typename T, bool kSwap>
class UnsignedField final : public FieldStorage<T, kSwap> {
 public:
  using Storage = FieldStorage<T, kSwap>;
  using typename Storage::value_type;

  using Storage::get;
  using Storage::Storage;

  constexpr UnsignedField(const UnsignedField&) = default;

  // Allow implicit conversion.
  constexpr UnsignedField(value_type x) : Storage{x} {}

  constexpr UnsignedField& operator=(const UnsignedField&) = default;

  constexpr UnsignedField& operator=(value_type x) {
    Storage::operator=(x);
    return *this;
  }

  constexpr value_type operator()() const { return get(); }

  constexpr operator value_type() const { return get(); }
};

template <typename T, bool kSwap>
class SignedField final : public FieldStorage<T, kSwap> {
 public:
  using Storage = FieldStorage<T, kSwap>;

  using value_type = std::make_signed_t<T>;

  using Storage::Storage;

  constexpr SignedField(value_type value) : Storage{cpp20::bit_cast<T>(value)} {}

  constexpr SignedField(const SignedField&) = default;

  constexpr SignedField& operator=(const SignedField&) = default;

  constexpr SignedField& operator=(value_type x) {
    Storage::operator=(cpp20::bit_cast<T>(x));
    return *this;
  }

  constexpr value_type get() const { return cpp20::bit_cast<value_type>(Storage::get()); }

  constexpr value_type operator()() const { return get(); }

  constexpr operator value_type() const { return get(); }
};

// This is like UnsignedField but for enum types defined with a specified
// underlying unsigned integer type.  The underlying type of the actual field
// to access (before possible byte-swapping) can be given as an explicit
// template argument if in case it differs from the enum's underlying type.
template <typename T, bool kSwap, typename Uint = std::underlying_type_t<T>>
class EnumField final {
 public:
  using value_type = T;
  static_assert(std::is_enum_v<value_type>);

  constexpr EnumField() = default;

  constexpr EnumField(const EnumField&) = default;

  constexpr EnumField(value_type x) : value_(static_cast<Uint>(x)) {}

  constexpr EnumField& operator=(const EnumField&) = default;

  constexpr EnumField& operator=(value_type x) {
    value_ = static_cast<Uint>(x);
    return *this;
  }

  constexpr bool operator==(const EnumField& other) { return value_ == other.value_; }
  constexpr bool operator!=(const EnumField& other) { return value_ != other.value_; }

  constexpr bool operator==(value_type other) { return *this == EnumField{other}; }
  constexpr bool operator!=(value_type other) { return *this != EnumField{other}; }

  constexpr value_type get() const { return static_cast<value_type>(value_.get()); }

  constexpr value_type operator()() const { return get(); }

  constexpr operator value_type() const { return get(); }

 private:
  UnsignedField<Uint, kSwap> value_;
};

}  // namespace elfldltl

#endif  // SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_FIELD_H_
