// 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 {
 public:
  using value_type = T;

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

  constexpr UnsignedField() = default;

  constexpr UnsignedField(const UnsignedField&) = default;

  constexpr UnsignedField(value_type x) : value_(Convert(x)) {}

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

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

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

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

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

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

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

 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 |= *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_{};
};

// 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 final : public UnsignedField<T, kSwap> {
 public:
  using Base = UnsignedField<T, kSwap>;

  using value_type = std::make_signed_t<T>;

  using Base::Base;

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

  constexpr value_type get() const { return Base::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_
