12#include <sys/socket.h> 
   14#include <fmt/format.h> 
   16USERVER_NAMESPACE_BEGIN
 
   24template <std::size_t N>
 
   25class AddressBase 
final {
 
   26  static_assert(N == 4 || N == 16, 
"Address can only be 4 or 16 bytes size");
 
   29  static constexpr std::size_t AddressSize = N;
 
   30  using BytesType = std::array<
unsigned char, N>;
 
   32  AddressBase() 
noexcept : address_({0}) {}
 
   33  explicit AddressBase(
const BytesType& address) : address_(address) {}
 
   36  const BytesType& 
GetBytes() 
const noexcept { 
return address_; }
 
   38  friend bool operator==(
const AddressBase<N>& a1,
 
   39                         const AddressBase<N>& a2) 
noexcept {
 
   40    return a1.address_ == a2.address_;
 
   43  friend bool operator!=(
const AddressBase<N>& a1,
 
   44                         const AddressBase<N>& a2) 
noexcept {
 
   45    return a1.address_ != a2.address_;
 
   55using AddressV4 = AddressBase<4>;
 
   60using AddressV6 = AddressBase<16>;
 
   63inline constexpr bool kIsAddressType =
 
   64    std::is_same_v<T, AddressV4> || std::is_same_v<T, AddressV6>;
 
   84template <
typename Address,
 
   85          typename = std::enable_if_t<kIsAddressType<Address>>>
 
   86class NetworkBase 
final {
 
   88  using AddressType = Address;
 
   89  static constexpr unsigned char kMaximumPrefixLength =
 
   90      std::is_same_v<Address, AddressV4> ? 32 : 128;
 
   92  NetworkBase() 
noexcept = 
default;
 
   94  NetworkBase(
const AddressType& address, 
unsigned short prefix_length)
 
   95      : address_(address), prefix_length_(prefix_length) {
 
   96    if (prefix_length > kMaximumPrefixLength) {
 
   97      throw std::out_of_range(fmt::format(
 
   98          "{} prefix length is too large",
 
   99          std::is_same_v<Address, AddressV4> ? 
"NetworkV4" : 
"NetworkV6"));
 
  109  friend bool operator==(
const NetworkBase<Address>& a,
 
  110                         const NetworkBase<Address>& b) 
noexcept {
 
  111    return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_;
 
  114  friend bool operator!=(
const NetworkBase<Address>& a,
 
  115                         const NetworkBase<Address>& b) 
noexcept {
 
  120  AddressType address_;
 
  121  unsigned char prefix_length_ = 0;
 
  127using NetworkV4 = NetworkBase<AddressV4>;
 
  132using NetworkV6 = NetworkBase<AddressV6>;
 
  161class InetNetwork 
final {
 
  163  enum class AddressFamily : 
unsigned char { IPv4 = AF_INET, IPv6 = AF_INET6 };
 
  167  InetNetwork(std::vector<
unsigned char>&& bytes, 
unsigned char prefix_length,
 
  168              AddressFamily address_family);
 
  179  friend bool operator==(
const InetNetwork& lhs, 
const InetNetwork& rhs) {
 
  180    return lhs.address_family_ == rhs.address_family_ &&
 
  181           lhs.prefix_length_ == rhs.prefix_length_ && lhs.bytes_ == rhs.bytes_;
 
  184  friend bool operator!=(
const InetNetwork& lhs, 
const InetNetwork& rhs) {
 
  185    return !operator==(lhs, rhs);
 
  189  std::vector<
unsigned char> bytes_;
 
  190  unsigned char prefix_length_;
 
  191  AddressFamily address_family_;
 
  207class AddressSystemError 
final : 
public std::exception {
 
  209  AddressSystemError(std::error_code code, std::string_view msg)
 
  210      : msg_(msg), code_(code) {}
 
  213  const std::error_code& 
Code() 
const { 
return code_; }
 
  215  const char* what() 
const noexcept final { 
return msg_.c_str(); }
 
  219  std::error_code code_;