// 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 FBL_STRONG_INT_H_
#define FBL_STRONG_INT_H_

#if !_KERNEL
#include <stddef.h>

#include <functional>
#endif  // !_KERNEL

#include <type_traits>

// StrongInt is a strongly-typed wrapper around integer types that supports
// standard arithmetic operations. Different types of StrongInts do not
// implicitly convert, even where the underlying integral type would.
//
// StrongInt provides the standard set of arithmetic operations, including
// basic arithmetic (such as `x + y`), bitwise operations (such as `x | y`),
// comparison operations (such as `x <= y`), and unary operators (such as
// `-x`, `~x`, `++x`, `x++`).
//
// For opaque integer types where arithmetic is not needed (such as handles or
// other identifiers), consider using the HardInt type in <fbl/hard_int.h>
// instead.
//
// StrongInt types are the same size as the underlying type.
//
// Example:
//     DEFINE_STRONG_INT(CpuCount, uint64_t);
//     DEFINE_STRONG_INT(MemoryBytes, uint64_t);
//     ...
//     CpuCount c1(3);
//     CpuCount c2(5);
//     MemoryBytes m(4096);
//     c1 + 1;                          <-- Compile error: can't implicitly convert 1 to CpuCount
//     c1 + CpuCount(1);                <-- Allowed
//     assert(c1 == 3);                 <-- Compile error: can't implicitly convert 1 to CpuCount
//     assert(c1.value() == 3);         <-- Allowed
//     assert(c1 != c2);                <-- Allowed
//     c1 = c2;                         <-- Allowed
//     m = c1;                          <-- Compile error
//
// Non-scalar arithmetic operations (addition, subtraction, etc) are allowed
// on StrongInt types with other instances of the same StrongInt type:
//
//     c1 + c2;                         <-- Allowed, producing the type CpuCount.
//     c1 += c2;                        <-- Allowed
//     c1++;                            <-- Allowed
//     c1 + m;                          <-- Compile error: mixing CpuCount and MemoryBytes
//     c1 + 1;                          <-- Compile error: mixing CpuCount and plain int.
//
// StrongInt types also supports scalar operations (multiplication, division,
// modulo, and shifting by plain integral types) by plain integral types:
//
//     CpuCount c(1);
//     auto cpu_count = c * 2;          <-- Allowed, producing the type `CpuCount`.
//     c /= 2;                          <-- Allowed
//     c << 2;                          <-- Allowed
//
// Bitwise operators are supported on the generated type, though users must
// ensure that these operations are sensible.
//
// The full set of supported arithmetic operations are as follows:
//
//     StrongInt + StrongInt --> StrongInt
//     StrongInt - StrongInt --> StrongInt
//     StrongInt & StrongInt --> StrongInt
//     StrongInt | StrongInt --> StrongInt
//     StrongInt ^ StrongInt --> StrongInt
//
//     StrongInt * Value --> StrongInt
//     Value * StrongInt --> StrongInt
//
//     StrongInt / Value --> StrongInt
//     StrongInt / StrongInt --> Value
//
//     StrongInt % StrongInt --> StrongInt
//     StrongInt % Value --> StrongInt
//
//     StrongInt << Value --> StrongInt
//     StrongInt >> Value --> StrongInt
//
//     StrongInt { <= | < | == | > | >= | != } StrongInt --> bool
//
//     StrongInt++
//     StrongInt--

// Create a wrapper around |base_type| named |type_name|.
#define DEFINE_STRONG_INT(type_name, base_type)                                  \
  struct type_name##_strong_int_type_tag_ {};                                    \
  using type_name = fbl::StrongInt<type_name##_strong_int_type_tag_, base_type>; \
  static_assert(sizeof(type_name) == sizeof(base_type))

namespace fbl {

template <typename UniqueTagType, typename T>
class StrongInt {
 public:
  constexpr StrongInt() = default;
  constexpr explicit StrongInt(T value) : value_(value) {}
  constexpr T value() const { return value_; }

  // Define comparison operators.
#define FBL_STRONG_INT_COMPARISON_OP(op)                                          \
  friend constexpr bool operator op(const StrongInt& lhs, const StrongInt& rhs) { \
    return lhs.value_ op rhs.value_;                                              \
  }
  FBL_STRONG_INT_COMPARISON_OP(==)
  FBL_STRONG_INT_COMPARISON_OP(!=)
  FBL_STRONG_INT_COMPARISON_OP(<=)
  FBL_STRONG_INT_COMPARISON_OP(>=)
  FBL_STRONG_INT_COMPARISON_OP(<)
  FBL_STRONG_INT_COMPARISON_OP(>)

  // Define binary operators where both the LHS and RHS are of the same StrongInt.
#define FBL_STRONG_INT_STRONG_STRONG_BINARY_OP(op)                                     \
  friend constexpr StrongInt operator op(const StrongInt& lhs, const StrongInt& rhs) { \
    return StrongInt(lhs.value_ op rhs.value_);                                        \
  }                                                                                    \
  constexpr StrongInt& operator op##=(const StrongInt& other) {                        \
    value_ op## = other.value_;                                                        \
    return *this;                                                                      \
  }
  FBL_STRONG_INT_STRONG_STRONG_BINARY_OP(+)
  FBL_STRONG_INT_STRONG_STRONG_BINARY_OP(-)
  FBL_STRONG_INT_STRONG_STRONG_BINARY_OP(&)
  FBL_STRONG_INT_STRONG_STRONG_BINARY_OP(|)
  FBL_STRONG_INT_STRONG_STRONG_BINARY_OP(^)
  FBL_STRONG_INT_STRONG_STRONG_BINARY_OP(%)

  // Define binary operations which can take place on a compatible numeric type
  // on the right hand side.
#define FBL_STRONG_INT_STRONG_NUMERIC_BINARY_OP(op)                            \
  friend constexpr StrongInt operator op(const StrongInt& lhs, const T& rhs) { \
    return StrongInt(lhs.value_ op rhs);                                       \
  }                                                                            \
  constexpr StrongInt& operator op##=(const T& other) {                        \
    value_ op## = other;                                                       \
    return *this;                                                              \
  }
  FBL_STRONG_INT_STRONG_NUMERIC_BINARY_OP(/)
  FBL_STRONG_INT_STRONG_NUMERIC_BINARY_OP(*)
  FBL_STRONG_INT_STRONG_NUMERIC_BINARY_OP(%)
  FBL_STRONG_INT_STRONG_NUMERIC_BINARY_OP(<<)
  FBL_STRONG_INT_STRONG_NUMERIC_BINARY_OP(>>)

  // <value type> * StrongInt. The symmetrical case is implemented in the macro above.
  friend constexpr StrongInt operator*(const T& lhs, const StrongInt& rhs) {
    return StrongInt(lhs * rhs.value_);
  }

  // StrongInt / StrongInt == value_type.
  friend constexpr T operator/(const StrongInt& lhs, const StrongInt& rhs) {
    return lhs.value_ / rhs.value_;
  }

  // Define unary operations.
  constexpr auto& operator++() {
    ++value_;
    return *this;
  }
  constexpr auto& operator--() {
    --value_;
    return *this;
  }
  constexpr auto operator++(int postfix) { return StrongInt(value_++); }
  constexpr auto operator--(int postfix) { return StrongInt(value_--); }
  constexpr auto operator+() { return StrongInt(+value_); }
  constexpr auto operator-() { return StrongInt(-value_); }
  constexpr auto operator~() { return StrongInt(~value_); }

  // Truth testing.
  explicit operator bool() { return value_ != 0; }

 private:
  static_assert(std::is_integral<T>::value, "T must be an arithmetic type.");
  static_assert(!std::is_same<T, bool>::value, "StrongInt does not support bool.");

  T value_ = 0;
};

}  // namespace fbl

#if !_KERNEL

namespace std {
template <typename UniqueTagType, typename T>
struct hash<fbl::StrongInt<UniqueTagType, T>> {
  constexpr size_t operator()(fbl::StrongInt<UniqueTagType, T> strong_int) const noexcept {
    return std::hash<T>()(strong_int.value());
  }
};
}  // namespace std

#endif  // !KERNEL

#endif  // FBL_STRONG_INT_H_
