11bbe3d1eSWilliam A. Kennington III #pragma once 2bb0eaccbSWilliam A. Kennington III #include <fmt/core.h> 3bb0eaccbSWilliam A. Kennington III #include <net/ethernet.h> 41bbe3d1eSWilliam A. Kennington III #include <netinet/in.h> 51bbe3d1eSWilliam A. Kennington III 6bb0eaccbSWilliam A. Kennington III #include <algorithm> 7bb0eaccbSWilliam A. Kennington III #include <array> 81bbe3d1eSWilliam A. Kennington III #include <chrono> 971de63a2SWilliam A. Kennington III #include <numeric> 101bbe3d1eSWilliam A. Kennington III #include <sdeventplus/clock.hpp> 111bbe3d1eSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp> 121bbe3d1eSWilliam A. Kennington III #include <string> 13bb0eaccbSWilliam A. Kennington III #include <string_view> 14bb0eaccbSWilliam A. Kennington III #include <type_traits> 15dd9ef815SWilliam A. Kennington III #include <unordered_map> 16f7dce2e8SWilly Tu #include <unordered_set> 171bbe3d1eSWilliam A. Kennington III #include <variant> 181bbe3d1eSWilliam A. Kennington III 19*454a0deeSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept 20*454a0deeSWilliam A. Kennington III { 21*454a0deeSWilliam A. Kennington III return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6, 22*454a0deeSWilliam A. Kennington III rhs.ether_addr_octet); 23*454a0deeSWilliam A. Kennington III } 24*454a0deeSWilliam A. Kennington III 25*454a0deeSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept 26*454a0deeSWilliam A. Kennington III { 27*454a0deeSWilliam A. Kennington III return lhs.s_addr == rhs.s_addr; 28*454a0deeSWilliam A. Kennington III } 29*454a0deeSWilliam A. Kennington III 30*454a0deeSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept 31*454a0deeSWilliam A. Kennington III { 32*454a0deeSWilliam A. Kennington III return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32); 33*454a0deeSWilliam A. Kennington III } 34*454a0deeSWilliam A. Kennington III 351bbe3d1eSWilliam A. Kennington III namespace phosphor 361bbe3d1eSWilliam A. Kennington III { 371bbe3d1eSWilliam A. Kennington III namespace network 381bbe3d1eSWilliam A. Kennington III { 391bbe3d1eSWilliam A. Kennington III 401bbe3d1eSWilliam A. Kennington III using namespace std::chrono_literals; 411bbe3d1eSWilliam A. Kennington III 42c7cf25f7SWilliam A. Kennington III // wait for three seconds before reloading systemd-networkd 43c7cf25f7SWilliam A. Kennington III constexpr auto reloadTimeout = 3s; 441bbe3d1eSWilliam A. Kennington III 45d41db383SWilliam A. Kennington III // refresh the objets after four seconds as network 46d41db383SWilliam A. Kennington III // configuration takes 3-4 sec to reconfigure at most. 47d41db383SWilliam A. Kennington III constexpr auto refreshTimeout = 4s; 481bbe3d1eSWilliam A. Kennington III 491bbe3d1eSWilliam A. Kennington III // Byte representations for common address types in network byte order 50bb0eaccbSWilliam A. Kennington III using InAddrAny = std::variant<in_addr, in6_addr>; 51b9d7cbacSWilliam A. Kennington III class IfAddr 52b9d7cbacSWilliam A. Kennington III { 53b9d7cbacSWilliam A. Kennington III private: 54b9d7cbacSWilliam A. Kennington III InAddrAny addr; 55b9d7cbacSWilliam A. Kennington III uint8_t pfx; 56b9d7cbacSWilliam A. Kennington III 57b9d7cbacSWilliam A. Kennington III static void invalidPfx(uint8_t pfx); 58b9d7cbacSWilliam A. Kennington III 59b9d7cbacSWilliam A. Kennington III public: 60b9d7cbacSWilliam A. Kennington III constexpr IfAddr() : addr({}), pfx(0) 61b9d7cbacSWilliam A. Kennington III { 62b9d7cbacSWilliam A. Kennington III } 63b9d7cbacSWilliam A. Kennington III 64b9d7cbacSWilliam A. Kennington III constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx) 65b9d7cbacSWilliam A. Kennington III { 66b9d7cbacSWilliam A. Kennington III std::visit( 67b9d7cbacSWilliam A. Kennington III [pfx](auto v) { 68b9d7cbacSWilliam A. Kennington III if (sizeof(v) * 8 < pfx) 69b9d7cbacSWilliam A. Kennington III { 70b9d7cbacSWilliam A. Kennington III invalidPfx(pfx); 71b9d7cbacSWilliam A. Kennington III } 72b9d7cbacSWilliam A. Kennington III }, 73b9d7cbacSWilliam A. Kennington III addr); 74b9d7cbacSWilliam A. Kennington III } 75b9d7cbacSWilliam A. Kennington III 76b9d7cbacSWilliam A. Kennington III constexpr auto getAddr() const 77b9d7cbacSWilliam A. Kennington III { 78b9d7cbacSWilliam A. Kennington III return addr; 79b9d7cbacSWilliam A. Kennington III } 80b9d7cbacSWilliam A. Kennington III 81b9d7cbacSWilliam A. Kennington III constexpr auto getPfx() const 82b9d7cbacSWilliam A. Kennington III { 83b9d7cbacSWilliam A. Kennington III return pfx; 84b9d7cbacSWilliam A. Kennington III } 85b9d7cbacSWilliam A. Kennington III 86b9d7cbacSWilliam A. Kennington III constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept 87b9d7cbacSWilliam A. Kennington III { 88b9d7cbacSWilliam A. Kennington III return addr == rhs.addr && pfx == rhs.pfx; 89b9d7cbacSWilliam A. Kennington III } 90b9d7cbacSWilliam A. Kennington III }; 911bbe3d1eSWilliam A. Kennington III 921bbe3d1eSWilliam A. Kennington III using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>; 931bbe3d1eSWilliam A. Kennington III 94*454a0deeSWilliam A. Kennington III /** @class InterfaceInfo 95*454a0deeSWilliam A. Kennington III * @brief Information about interfaces from the kernel 96*454a0deeSWilliam A. Kennington III */ 97*454a0deeSWilliam A. Kennington III struct InterfaceInfo 98*454a0deeSWilliam A. Kennington III { 99*454a0deeSWilliam A. Kennington III unsigned idx; 100*454a0deeSWilliam A. Kennington III unsigned flags; 101*454a0deeSWilliam A. Kennington III std::optional<std::string> name = std::nullopt; 102*454a0deeSWilliam A. Kennington III std::optional<ether_addr> mac = std::nullopt; 103*454a0deeSWilliam A. Kennington III std::optional<unsigned> mtu = std::nullopt; 104*454a0deeSWilliam A. Kennington III std::optional<unsigned> parent_idx = std::nullopt; 105*454a0deeSWilliam A. Kennington III std::optional<std::string> kind = std::nullopt; 106*454a0deeSWilliam A. Kennington III std::optional<uint16_t> vlan_id = std::nullopt; 107*454a0deeSWilliam A. Kennington III 108*454a0deeSWilliam A. Kennington III constexpr bool operator==(const InterfaceInfo& rhs) const noexcept 109*454a0deeSWilliam A. Kennington III { 110*454a0deeSWilliam A. Kennington III return idx == rhs.idx && flags == rhs.flags && name == rhs.name && 111*454a0deeSWilliam A. Kennington III mac == rhs.mac && mtu == rhs.mtu && 112*454a0deeSWilliam A. Kennington III parent_idx == rhs.parent_idx && kind == rhs.kind && 113*454a0deeSWilliam A. Kennington III vlan_id == rhs.vlan_id; 114*454a0deeSWilliam A. Kennington III } 115*454a0deeSWilliam A. Kennington III }; 116*454a0deeSWilliam A. Kennington III 1176a92363eSWilliam A. Kennington III /** @class AddressInfo 1186a92363eSWilliam A. Kennington III * @brief Information about a addresses from the kernel 1196a92363eSWilliam A. Kennington III */ 1206a92363eSWilliam A. Kennington III struct AddressInfo 1216a92363eSWilliam A. Kennington III { 1226a92363eSWilliam A. Kennington III unsigned ifidx; 1236a92363eSWilliam A. Kennington III IfAddr ifaddr; 1246a92363eSWilliam A. Kennington III uint8_t scope; 1256a92363eSWilliam A. Kennington III uint32_t flags; 126*454a0deeSWilliam A. Kennington III 127*454a0deeSWilliam A. Kennington III constexpr bool operator==(const AddressInfo& rhs) const noexcept 128*454a0deeSWilliam A. Kennington III { 129*454a0deeSWilliam A. Kennington III return ifidx == rhs.ifidx && ifaddr == rhs.ifaddr && 130*454a0deeSWilliam A. Kennington III scope == rhs.scope && flags == rhs.flags; 131*454a0deeSWilliam A. Kennington III } 1326a92363eSWilliam A. Kennington III }; 1336a92363eSWilliam A. Kennington III 134a8426902SWilliam A. Kennington III /** @class NeighborInfo 135a8426902SWilliam A. Kennington III * @brief Information about a neighbor from the kernel 136a8426902SWilliam A. Kennington III */ 137a8426902SWilliam A. Kennington III struct NeighborInfo 138a8426902SWilliam A. Kennington III { 139a8426902SWilliam A. Kennington III unsigned ifidx; 140*454a0deeSWilliam A. Kennington III uint16_t state; 141a8426902SWilliam A. Kennington III InAddrAny addr; 142a8426902SWilliam A. Kennington III std::optional<ether_addr> mac; 143*454a0deeSWilliam A. Kennington III 144*454a0deeSWilliam A. Kennington III constexpr bool operator==(const NeighborInfo& rhs) const noexcept 145*454a0deeSWilliam A. Kennington III { 146*454a0deeSWilliam A. Kennington III return ifidx == rhs.ifidx && state == rhs.state && addr == rhs.addr && 147*454a0deeSWilliam A. Kennington III mac == rhs.mac; 148*454a0deeSWilliam A. Kennington III } 149a8426902SWilliam A. Kennington III }; 150a8426902SWilliam A. Kennington III 151dd9ef815SWilliam A. Kennington III struct string_hash : public std::hash<std::string_view> 152dd9ef815SWilliam A. Kennington III { 153dd9ef815SWilliam A. Kennington III using is_transparent = void; 154dd9ef815SWilliam A. Kennington III }; 155dd9ef815SWilliam A. Kennington III template <typename V> 156dd9ef815SWilliam A. Kennington III using string_umap = 157dd9ef815SWilliam A. Kennington III std::unordered_map<std::string, V, string_hash, std::equal_to<>>; 15896444795SWilliam A. Kennington III using string_uset = 15996444795SWilliam A. Kennington III std::unordered_set<std::string, string_hash, std::equal_to<>>; 160dd9ef815SWilliam A. Kennington III 1613e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi() noexcept 162991a8e81SWilliam A. Kennington III { 163991a8e81SWilliam A. Kennington III return 0; 164991a8e81SWilliam A. Kennington III } 165991a8e81SWilliam A. Kennington III 166991a8e81SWilliam A. Kennington III template <typename T, typename... Args> 167becda1aaSWilliam A. Kennington III constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept 168991a8e81SWilliam A. Kennington III { 169991a8e81SWilliam A. Kennington III const std::size_t seed = hash_multi(args...); 170991a8e81SWilliam A. Kennington III return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); 171991a8e81SWilliam A. Kennington III } 172991a8e81SWilliam A. Kennington III 173bb0eaccbSWilliam A. Kennington III namespace detail 174bb0eaccbSWilliam A. Kennington III { 175bb0eaccbSWilliam A. Kennington III 17671de63a2SWilliam A. Kennington III template <typename T, uint8_t size = sizeof(T)> 17771de63a2SWilliam A. Kennington III struct BswapAlign 17871de63a2SWilliam A. Kennington III { 17971de63a2SWilliam A. Kennington III using type = T; 18071de63a2SWilliam A. Kennington III }; 18171de63a2SWilliam A. Kennington III 18271de63a2SWilliam A. Kennington III template <typename T> 18371de63a2SWilliam A. Kennington III struct BswapAlign<T, 2> 18471de63a2SWilliam A. Kennington III { 18571de63a2SWilliam A. Kennington III using type alignas(uint16_t) = T; 18671de63a2SWilliam A. Kennington III }; 18771de63a2SWilliam A. Kennington III 18871de63a2SWilliam A. Kennington III template <typename T> 18971de63a2SWilliam A. Kennington III struct BswapAlign<T, 4> 19071de63a2SWilliam A. Kennington III { 19171de63a2SWilliam A. Kennington III using type alignas(uint32_t) = T; 19271de63a2SWilliam A. Kennington III }; 19371de63a2SWilliam A. Kennington III 19471de63a2SWilliam A. Kennington III template <typename T> 19571de63a2SWilliam A. Kennington III struct BswapAlign<T, 8> 19671de63a2SWilliam A. Kennington III { 19771de63a2SWilliam A. Kennington III using type alignas(uint64_t) = T; 19871de63a2SWilliam A. Kennington III }; 19971de63a2SWilliam A. Kennington III 20071de63a2SWilliam A. Kennington III template <typename T> 20171de63a2SWilliam A. Kennington III constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept 20271de63a2SWilliam A. Kennington III { 20371de63a2SWilliam A. Kennington III static_assert(std::is_trivially_copyable_v<T>); 20471de63a2SWilliam A. Kennington III if constexpr (sizeof(T) == 2) 20571de63a2SWilliam A. Kennington III { 20671de63a2SWilliam A. Kennington III reinterpret_cast<uint16_t&>(n) = 20771de63a2SWilliam A. Kennington III __builtin_bswap16(reinterpret_cast<uint16_t&>(n)); 20871de63a2SWilliam A. Kennington III } 20971de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 4) 21071de63a2SWilliam A. Kennington III { 21171de63a2SWilliam A. Kennington III reinterpret_cast<uint32_t&>(n) = 21271de63a2SWilliam A. Kennington III __builtin_bswap32(reinterpret_cast<uint32_t&>(n)); 21371de63a2SWilliam A. Kennington III } 21471de63a2SWilliam A. Kennington III else if constexpr (sizeof(T) == 8) 21571de63a2SWilliam A. Kennington III { 21671de63a2SWilliam A. Kennington III reinterpret_cast<uint64_t&>(n) = 21771de63a2SWilliam A. Kennington III __builtin_bswap64(reinterpret_cast<uint64_t&>(n)); 21871de63a2SWilliam A. Kennington III } 21971de63a2SWilliam A. Kennington III else 22071de63a2SWilliam A. Kennington III { 22171de63a2SWilliam A. Kennington III auto b = reinterpret_cast<std::byte*>(&n); 22271de63a2SWilliam A. Kennington III std::reverse(b, b + sizeof(n)); 22371de63a2SWilliam A. Kennington III } 22471de63a2SWilliam A. Kennington III return n; 22571de63a2SWilliam A. Kennington III } 22671de63a2SWilliam A. Kennington III 22771de63a2SWilliam A. Kennington III } // namespace detail 22871de63a2SWilliam A. Kennington III 22971de63a2SWilliam A. Kennington III template <typename T> 23071de63a2SWilliam A. Kennington III constexpr T bswap(T n) noexcept 23171de63a2SWilliam A. Kennington III { 23271de63a2SWilliam A. Kennington III return detail::bswapInt<T>(n); 23371de63a2SWilliam A. Kennington III } 23471de63a2SWilliam A. Kennington III 23571de63a2SWilliam A. Kennington III template <typename T> 23671de63a2SWilliam A. Kennington III constexpr T hton(T n) noexcept 23771de63a2SWilliam A. Kennington III { 23871de63a2SWilliam A. Kennington III if constexpr (std::endian::native == std::endian::big) 23971de63a2SWilliam A. Kennington III { 24071de63a2SWilliam A. Kennington III return n; 24171de63a2SWilliam A. Kennington III } 24271de63a2SWilliam A. Kennington III else if constexpr (std::endian::native == std::endian::little) 24371de63a2SWilliam A. Kennington III { 24471de63a2SWilliam A. Kennington III return bswap(n); 24571de63a2SWilliam A. Kennington III } 24671de63a2SWilliam A. Kennington III else 24771de63a2SWilliam A. Kennington III { 24871de63a2SWilliam A. Kennington III static_assert(std::is_same_v<T, void>); 24971de63a2SWilliam A. Kennington III } 25071de63a2SWilliam A. Kennington III } 25171de63a2SWilliam A. Kennington III 25271de63a2SWilliam A. Kennington III template <typename T> 25371de63a2SWilliam A. Kennington III constexpr T ntoh(T n) noexcept 25471de63a2SWilliam A. Kennington III { 25571de63a2SWilliam A. Kennington III return hton(n); 25671de63a2SWilliam A. Kennington III } 25771de63a2SWilliam A. Kennington III 25871de63a2SWilliam A. Kennington III namespace detail 25971de63a2SWilliam A. Kennington III { 260238ef992SWilliam A. Kennington III inline constexpr auto charLookup = []() { 261238ef992SWilliam A. Kennington III std::array<int8_t, 256> ret; 262238ef992SWilliam A. Kennington III std::fill(ret.begin(), ret.end(), -1); 263238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 10; ++i) 264238ef992SWilliam A. Kennington III { 265238ef992SWilliam A. Kennington III ret[i + '0'] = i; 266238ef992SWilliam A. Kennington III } 267238ef992SWilliam A. Kennington III for (int8_t i = 0; i < 26; ++i) 268238ef992SWilliam A. Kennington III { 269238ef992SWilliam A. Kennington III ret[i + 'A'] = i + 10; 270238ef992SWilliam A. Kennington III ret[i + 'a'] = i + 10; 271238ef992SWilliam A. Kennington III } 272238ef992SWilliam A. Kennington III return ret; 273238ef992SWilliam A. Kennington III }(); 274dd7c7b34SWilliam A. Kennington III inline constexpr auto intLookup = []() { 275dd7c7b34SWilliam A. Kennington III std::array<char, 36> ret; 276dd7c7b34SWilliam A. Kennington III for (int8_t i = 0; i < 10; ++i) 277dd7c7b34SWilliam A. Kennington III { 278dd7c7b34SWilliam A. Kennington III ret[i] = i + '0'; 279238ef992SWilliam A. Kennington III } 280dd7c7b34SWilliam A. Kennington III for (int8_t i = 0; i < 26; ++i) 281dd7c7b34SWilliam A. Kennington III { 282dd7c7b34SWilliam A. Kennington III ret[i + 10] = i + 'a'; 283dd7c7b34SWilliam A. Kennington III } 284dd7c7b34SWilliam A. Kennington III return ret; 285dd7c7b34SWilliam A. Kennington III }(); 286dd7c7b34SWilliam A. Kennington III } // namespace detail 287238ef992SWilliam A. Kennington III 288238ef992SWilliam A. Kennington III template <typename T, uint8_t base> 289238ef992SWilliam A. Kennington III struct DecodeInt 290238ef992SWilliam A. Kennington III { 291238ef992SWilliam A. Kennington III static_assert(base > 1 && base <= 36); 292238ef992SWilliam A. Kennington III static_assert(std::is_unsigned_v<T>); 293238ef992SWilliam A. Kennington III 294238ef992SWilliam A. Kennington III constexpr T operator()(std::string_view str) const 295238ef992SWilliam A. Kennington III { 296238ef992SWilliam A. Kennington III if (str.empty()) 297238ef992SWilliam A. Kennington III { 298238ef992SWilliam A. Kennington III throw std::invalid_argument("Empty Str"); 299238ef992SWilliam A. Kennington III } 300238ef992SWilliam A. Kennington III constexpr auto max = std::numeric_limits<T>::max(); 301238ef992SWilliam A. Kennington III auto ret = 302238ef992SWilliam A. Kennington III std::accumulate(str.begin(), str.end(), T{}, [&](T r, char c) { 303238ef992SWilliam A. Kennington III auto v = detail::charLookup[c]; 304238ef992SWilliam A. Kennington III if (v < 0 || v >= base) 305238ef992SWilliam A. Kennington III { 306238ef992SWilliam A. Kennington III throw std::invalid_argument("Invalid numeral"); 307238ef992SWilliam A. Kennington III } 308238ef992SWilliam A. Kennington III if constexpr (std::popcount(base) == 1) 309238ef992SWilliam A. Kennington III { 310238ef992SWilliam A. Kennington III constexpr auto shift = std::countr_zero(base); 311238ef992SWilliam A. Kennington III constexpr auto maxshift = max >> shift; 312238ef992SWilliam A. Kennington III if (r > maxshift) 313238ef992SWilliam A. Kennington III { 314238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 315238ef992SWilliam A. Kennington III } 316238ef992SWilliam A. Kennington III return (r << shift) | v; 317238ef992SWilliam A. Kennington III } 318238ef992SWilliam A. Kennington III else 319238ef992SWilliam A. Kennington III { 320238ef992SWilliam A. Kennington III constexpr auto maxbase = max / base; 321238ef992SWilliam A. Kennington III if (r > maxbase) 322238ef992SWilliam A. Kennington III { 323238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 324238ef992SWilliam A. Kennington III } 325238ef992SWilliam A. Kennington III r *= base; 326238ef992SWilliam A. Kennington III if (max - v < r) 327238ef992SWilliam A. Kennington III { 328238ef992SWilliam A. Kennington III throw std::overflow_error("Integer Decode"); 329238ef992SWilliam A. Kennington III } 330238ef992SWilliam A. Kennington III return r + v; 331238ef992SWilliam A. Kennington III } 332238ef992SWilliam A. Kennington III }); 333238ef992SWilliam A. Kennington III return ret; 334238ef992SWilliam A. Kennington III } 335238ef992SWilliam A. Kennington III }; 336238ef992SWilliam A. Kennington III 337dd7c7b34SWilliam A. Kennington III template <typename T, uint8_t base> 338dd7c7b34SWilliam A. Kennington III struct EncodeInt 339dd7c7b34SWilliam A. Kennington III { 340dd7c7b34SWilliam A. Kennington III static_assert(base > 1 && base <= 36); 341dd7c7b34SWilliam A. Kennington III static_assert(std::is_unsigned_v<T>); 342dd7c7b34SWilliam A. Kennington III 343dd7c7b34SWilliam A. Kennington III static constexpr uint8_t buf_size = []() { 344dd7c7b34SWilliam A. Kennington III T v = std::numeric_limits<T>::max(); 345dd7c7b34SWilliam A. Kennington III uint8_t i = 0; 346dd7c7b34SWilliam A. Kennington III for (; v != 0; ++i) 347dd7c7b34SWilliam A. Kennington III { 348dd7c7b34SWilliam A. Kennington III v /= base; 349dd7c7b34SWilliam A. Kennington III } 350dd7c7b34SWilliam A. Kennington III return i; 351dd7c7b34SWilliam A. Kennington III }(); 352dd7c7b34SWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 353dd7c7b34SWilliam A. Kennington III 354dd7c7b34SWilliam A. Kennington III constexpr uint8_t reverseFill(char* buf, T v) const noexcept 355dd7c7b34SWilliam A. Kennington III { 356dd7c7b34SWilliam A. Kennington III uint8_t i = 0; 357dd7c7b34SWilliam A. Kennington III do 358dd7c7b34SWilliam A. Kennington III { 359dd7c7b34SWilliam A. Kennington III if constexpr (std::popcount(base) == 1) 360dd7c7b34SWilliam A. Kennington III { 361dd7c7b34SWilliam A. Kennington III buf[i++] = detail::intLookup[v & 0xf]; 362dd7c7b34SWilliam A. Kennington III v >>= 4; 363dd7c7b34SWilliam A. Kennington III } 364dd7c7b34SWilliam A. Kennington III else 365dd7c7b34SWilliam A. Kennington III { 366dd7c7b34SWilliam A. Kennington III buf[i++] = detail::intLookup[v % base]; 367dd7c7b34SWilliam A. Kennington III v /= base; 368dd7c7b34SWilliam A. Kennington III } 369dd7c7b34SWilliam A. Kennington III } while (v > 0); 370dd7c7b34SWilliam A. Kennington III return i; 371dd7c7b34SWilliam A. Kennington III } 372dd7c7b34SWilliam A. Kennington III 373dd7c7b34SWilliam A. Kennington III constexpr char* operator()(char* buf, T v) const noexcept 374dd7c7b34SWilliam A. Kennington III { 375dd7c7b34SWilliam A. Kennington III uint8_t i = reverseFill(buf, v); 376dd7c7b34SWilliam A. Kennington III std::reverse(buf, buf + i); 377dd7c7b34SWilliam A. Kennington III return buf + i; 378dd7c7b34SWilliam A. Kennington III } 379dd7c7b34SWilliam A. Kennington III 380dd7c7b34SWilliam A. Kennington III constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept 381dd7c7b34SWilliam A. Kennington III { 382dd7c7b34SWilliam A. Kennington III uint8_t i = reverseFill(buf, v); 383dd7c7b34SWilliam A. Kennington III auto end = buf + std::max(i, min_width); 384dd7c7b34SWilliam A. Kennington III std::fill(buf + i, end, '0'); 385dd7c7b34SWilliam A. Kennington III std::reverse(buf, end); 386dd7c7b34SWilliam A. Kennington III return end; 387dd7c7b34SWilliam A. Kennington III } 388dd7c7b34SWilliam A. Kennington III }; 389dd7c7b34SWilliam A. Kennington III 390b01d08fdSWilliam A. Kennington III template <typename T> 391b01d08fdSWilliam A. Kennington III struct ToAddr 392b01d08fdSWilliam A. Kennington III { 393b01d08fdSWilliam A. Kennington III }; 394b01d08fdSWilliam A. Kennington III 395b01d08fdSWilliam A. Kennington III template <> 396b01d08fdSWilliam A. Kennington III struct ToAddr<ether_addr> 397b01d08fdSWilliam A. Kennington III { 398b01d08fdSWilliam A. Kennington III constexpr ether_addr operator()(std::string_view str) const 399b01d08fdSWilliam A. Kennington III { 400b01d08fdSWilliam A. Kennington III constexpr DecodeInt<uint8_t, 16> di; 401b01d08fdSWilliam A. Kennington III ether_addr ret; 402b01d08fdSWilliam A. Kennington III if (str.size() == 12 && str.find(":") == str.npos) 403b01d08fdSWilliam A. Kennington III { 404b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 6; ++i) 405b01d08fdSWilliam A. Kennington III { 406b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(i * 2, 2)); 407b01d08fdSWilliam A. Kennington III } 408b01d08fdSWilliam A. Kennington III } 409b01d08fdSWilliam A. Kennington III else 410b01d08fdSWilliam A. Kennington III { 411b01d08fdSWilliam A. Kennington III for (size_t i = 0; i < 5; ++i) 412b01d08fdSWilliam A. Kennington III { 413b01d08fdSWilliam A. Kennington III auto loc = str.find(":"); 414b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[i] = di(str.substr(0, loc)); 415b01d08fdSWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 416b01d08fdSWilliam A. Kennington III if (str.empty()) 417b01d08fdSWilliam A. Kennington III { 418b01d08fdSWilliam A. Kennington III throw std::invalid_argument("Missing mac data"); 419b01d08fdSWilliam A. Kennington III } 420b01d08fdSWilliam A. Kennington III } 421b01d08fdSWilliam A. Kennington III ret.ether_addr_octet[5] = di(str); 422b01d08fdSWilliam A. Kennington III } 423b01d08fdSWilliam A. Kennington III return ret; 424b01d08fdSWilliam A. Kennington III } 425b01d08fdSWilliam A. Kennington III }; 426b01d08fdSWilliam A. Kennington III 427df1178e0SWilliam A. Kennington III template <> 428df1178e0SWilliam A. Kennington III struct ToAddr<in_addr> 429df1178e0SWilliam A. Kennington III { 430df1178e0SWilliam A. Kennington III constexpr in_addr operator()(std::string_view str) const 431df1178e0SWilliam A. Kennington III { 432df1178e0SWilliam A. Kennington III constexpr DecodeInt<uint8_t, 10> di; 433df1178e0SWilliam A. Kennington III uint32_t addr = {}; 434df1178e0SWilliam A. Kennington III for (size_t i = 0; i < 3; ++i) 435df1178e0SWilliam A. Kennington III { 436df1178e0SWilliam A. Kennington III auto loc = str.find("."); 437df1178e0SWilliam A. Kennington III addr |= di(str.substr(0, loc)); 438df1178e0SWilliam A. Kennington III addr <<= 8; 439df1178e0SWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 440df1178e0SWilliam A. Kennington III if (str.empty()) 441df1178e0SWilliam A. Kennington III { 442df1178e0SWilliam A. Kennington III throw std::invalid_argument("Missing addr data"); 443df1178e0SWilliam A. Kennington III } 444df1178e0SWilliam A. Kennington III } 445df1178e0SWilliam A. Kennington III addr |= di(str); 446df1178e0SWilliam A. Kennington III return {hton(addr)}; 447df1178e0SWilliam A. Kennington III } 448df1178e0SWilliam A. Kennington III }; 449df1178e0SWilliam A. Kennington III 450ec496a86SWilliam A. Kennington III template <> 451ec496a86SWilliam A. Kennington III struct ToAddr<in6_addr> 452ec496a86SWilliam A. Kennington III { 453ec496a86SWilliam A. Kennington III constexpr in6_addr operator()(std::string_view str) const 454ec496a86SWilliam A. Kennington III { 455ec496a86SWilliam A. Kennington III constexpr DecodeInt<uint16_t, 16> di; 456ec496a86SWilliam A. Kennington III in6_addr ret = {}; 457ec496a86SWilliam A. Kennington III size_t i = 0; 458ec496a86SWilliam A. Kennington III while (i < 8) 459ec496a86SWilliam A. Kennington III { 460ec496a86SWilliam A. Kennington III auto loc = str.find(':'); 461ec496a86SWilliam A. Kennington III if (i == 6 && loc == str.npos) 462ec496a86SWilliam A. Kennington III { 463ec496a86SWilliam A. Kennington III ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr; 464ec496a86SWilliam A. Kennington III return ret; 465ec496a86SWilliam A. Kennington III } 466ec496a86SWilliam A. Kennington III if (loc != 0 && !str.empty()) 467ec496a86SWilliam A. Kennington III { 468ec496a86SWilliam A. Kennington III ret.s6_addr16[i++] = hton(di(str.substr(0, loc))); 469ec496a86SWilliam A. Kennington III } 470ec496a86SWilliam A. Kennington III if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':') 471ec496a86SWilliam A. Kennington III { 472ec496a86SWilliam A. Kennington III str.remove_prefix(loc + 2); 473ec496a86SWilliam A. Kennington III break; 474ec496a86SWilliam A. Kennington III } 475ec496a86SWilliam A. Kennington III else if (str.empty()) 476ec496a86SWilliam A. Kennington III { 477ec496a86SWilliam A. Kennington III throw std::invalid_argument("IPv6 Data"); 478ec496a86SWilliam A. Kennington III } 479ec496a86SWilliam A. Kennington III str.remove_prefix(loc == str.npos ? str.size() : loc + 1); 480ec496a86SWilliam A. Kennington III } 481ec496a86SWilliam A. Kennington III if (str.starts_with(':')) 482ec496a86SWilliam A. Kennington III { 483ec496a86SWilliam A. Kennington III throw std::invalid_argument("Extra separator"); 484ec496a86SWilliam A. Kennington III } 485ec496a86SWilliam A. Kennington III size_t j = 7; 486ec496a86SWilliam A. Kennington III if (!str.empty() && i < 6 && str.find('.') != str.npos) 487ec496a86SWilliam A. Kennington III { 488ec496a86SWilliam A. Kennington III auto loc = str.rfind(':'); 489ec496a86SWilliam A. Kennington III ret.s6_addr32[3] = 490ec496a86SWilliam A. Kennington III ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1)) 491ec496a86SWilliam A. Kennington III .s_addr; 492ec496a86SWilliam A. Kennington III str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc); 493ec496a86SWilliam A. Kennington III j -= 2; 494ec496a86SWilliam A. Kennington III } 495ec496a86SWilliam A. Kennington III while (!str.empty() && j > i) 496ec496a86SWilliam A. Kennington III { 497ec496a86SWilliam A. Kennington III auto loc = str.rfind(':'); 498ec496a86SWilliam A. Kennington III ret.s6_addr16[j--] = 499ec496a86SWilliam A. Kennington III hton(di(str.substr(loc == str.npos ? 0 : loc + 1))); 500ec496a86SWilliam A. Kennington III str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc); 501ec496a86SWilliam A. Kennington III } 502ec496a86SWilliam A. Kennington III if (!str.empty()) 503ec496a86SWilliam A. Kennington III { 504ec496a86SWilliam A. Kennington III throw std::invalid_argument("Too much data"); 505ec496a86SWilliam A. Kennington III } 506ec496a86SWilliam A. Kennington III return ret; 507ec496a86SWilliam A. Kennington III } 508ec496a86SWilliam A. Kennington III }; 509ec496a86SWilliam A. Kennington III 510ead7198cSWilliam A. Kennington III template <> 511ead7198cSWilliam A. Kennington III struct ToAddr<InAddrAny> 512ead7198cSWilliam A. Kennington III { 513ead7198cSWilliam A. Kennington III constexpr InAddrAny operator()(std::string_view str) const 514ead7198cSWilliam A. Kennington III { 515ead7198cSWilliam A. Kennington III if (str.find(':') == str.npos) 516ead7198cSWilliam A. Kennington III { 517ead7198cSWilliam A. Kennington III return ToAddr<in_addr>{}(str); 518ead7198cSWilliam A. Kennington III } 519ead7198cSWilliam A. Kennington III return ToAddr<in6_addr>{}(str); 520ead7198cSWilliam A. Kennington III } 521ead7198cSWilliam A. Kennington III }; 522ead7198cSWilliam A. Kennington III 523ead7198cSWilliam A. Kennington III template <> 524ead7198cSWilliam A. Kennington III struct ToAddr<IfAddr> 525ead7198cSWilliam A. Kennington III { 526ead7198cSWilliam A. Kennington III constexpr IfAddr operator()(std::string_view str) const 527ead7198cSWilliam A. Kennington III { 528ead7198cSWilliam A. Kennington III auto pos = str.rfind('/'); 529ead7198cSWilliam A. Kennington III if (pos == str.npos) 530ead7198cSWilliam A. Kennington III { 531ead7198cSWilliam A. Kennington III throw std::invalid_argument("Invalid IfAddr"); 532ead7198cSWilliam A. Kennington III } 533ead7198cSWilliam A. Kennington III return {ToAddr<InAddrAny>{}(str.substr(0, pos)), 534ead7198cSWilliam A. Kennington III DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))}; 535ead7198cSWilliam A. Kennington III } 536ead7198cSWilliam A. Kennington III }; 537ead7198cSWilliam A. Kennington III 53855bdc36cSWilliam A. Kennington III template <typename T> 53955bdc36cSWilliam A. Kennington III struct ToStr 54055bdc36cSWilliam A. Kennington III { 54155bdc36cSWilliam A. Kennington III }; 54255bdc36cSWilliam A. Kennington III 54355bdc36cSWilliam A. Kennington III template <> 54455bdc36cSWilliam A. Kennington III struct ToStr<char> 54555bdc36cSWilliam A. Kennington III { 54655bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 1; 54755bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 54855bdc36cSWilliam A. Kennington III 54955bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, char v) const noexcept 55055bdc36cSWilliam A. Kennington III { 55155bdc36cSWilliam A. Kennington III buf[0] = v; 55255bdc36cSWilliam A. Kennington III return buf + 1; 55355bdc36cSWilliam A. Kennington III } 55455bdc36cSWilliam A. Kennington III }; 55555bdc36cSWilliam A. Kennington III 55655bdc36cSWilliam A. Kennington III template <> 55755bdc36cSWilliam A. Kennington III struct ToStr<ether_addr> 55855bdc36cSWilliam A. Kennington III { 55955bdc36cSWilliam A. Kennington III // 6 octets * 2 hex chars + 5 separators 56055bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 17; 56155bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 56255bdc36cSWilliam A. Kennington III 56355bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, ether_addr v) const noexcept 56455bdc36cSWilliam A. Kennington III { 56555bdc36cSWilliam A. Kennington III for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3) 56655bdc36cSWilliam A. Kennington III { 56755bdc36cSWilliam A. Kennington III *ptr = ':'; 56855bdc36cSWilliam A. Kennington III } 56955bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 6; ++i) 57055bdc36cSWilliam A. Kennington III { 57155bdc36cSWilliam A. Kennington III char* tmp = buf + i * 3; 57255bdc36cSWilliam A. Kennington III uint8_t byte = v.ether_addr_octet[i]; 57355bdc36cSWilliam A. Kennington III EncodeInt<uint8_t, 16>{}(tmp, byte, 2); 57455bdc36cSWilliam A. Kennington III } 57555bdc36cSWilliam A. Kennington III return buf + buf_size; 57655bdc36cSWilliam A. Kennington III } 57755bdc36cSWilliam A. Kennington III }; 57855bdc36cSWilliam A. Kennington III 57955bdc36cSWilliam A. Kennington III template <> 58055bdc36cSWilliam A. Kennington III struct ToStr<in_addr> 58155bdc36cSWilliam A. Kennington III { 58255bdc36cSWilliam A. Kennington III // 4 octets * 3 dec chars + 3 separators 58355bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 15; 58455bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 58555bdc36cSWilliam A. Kennington III 58655bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, in_addr v) const noexcept 58755bdc36cSWilliam A. Kennington III { 58855bdc36cSWilliam A. Kennington III auto n = bswap(ntoh(v.s_addr)); 58955bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 3; ++i) 59055bdc36cSWilliam A. Kennington III { 59155bdc36cSWilliam A. Kennington III buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.'); 59255bdc36cSWilliam A. Kennington III n >>= 8; 59355bdc36cSWilliam A. Kennington III } 59455bdc36cSWilliam A. Kennington III return EncodeInt<uint8_t, 10>{}(buf, n & 0xff); 59555bdc36cSWilliam A. Kennington III } 59655bdc36cSWilliam A. Kennington III }; 59755bdc36cSWilliam A. Kennington III 59855bdc36cSWilliam A. Kennington III template <> 59955bdc36cSWilliam A. Kennington III struct ToStr<in6_addr> 60055bdc36cSWilliam A. Kennington III { 60155bdc36cSWilliam A. Kennington III // 8 hextets * 4 hex chars + 7 separators 60255bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = 39; 60355bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 60455bdc36cSWilliam A. Kennington III 60555bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, in6_addr v) const noexcept 60655bdc36cSWilliam A. Kennington III { 60755bdc36cSWilliam A. Kennington III // IPv4 in IPv6 Addr 60855bdc36cSWilliam A. Kennington III if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 && 60955bdc36cSWilliam A. Kennington III v.s6_addr32[2] == hton(uint32_t(0xffff))) 61055bdc36cSWilliam A. Kennington III { 61155bdc36cSWilliam A. Kennington III constexpr auto prefix = std::string_view("::ffff:"); 61255bdc36cSWilliam A. Kennington III return ToStr<in_addr>{}( 61355bdc36cSWilliam A. Kennington III std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]}); 61455bdc36cSWilliam A. Kennington III } 61555bdc36cSWilliam A. Kennington III 61655bdc36cSWilliam A. Kennington III size_t skip_start = 0; 61755bdc36cSWilliam A. Kennington III size_t skip_size = 0; 61855bdc36cSWilliam A. Kennington III { 61955bdc36cSWilliam A. Kennington III size_t new_start = 0; 62055bdc36cSWilliam A. Kennington III size_t new_size = 0; 62155bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 9; ++i) 62255bdc36cSWilliam A. Kennington III { 62355bdc36cSWilliam A. Kennington III if (i < 8 && v.s6_addr16[i] == 0) 62455bdc36cSWilliam A. Kennington III { 62555bdc36cSWilliam A. Kennington III if (new_start + new_size == i) 62655bdc36cSWilliam A. Kennington III { 62755bdc36cSWilliam A. Kennington III new_size++; 62855bdc36cSWilliam A. Kennington III } 62955bdc36cSWilliam A. Kennington III else 63055bdc36cSWilliam A. Kennington III { 63155bdc36cSWilliam A. Kennington III new_start = i; 63255bdc36cSWilliam A. Kennington III new_size = 1; 63355bdc36cSWilliam A. Kennington III } 63455bdc36cSWilliam A. Kennington III } 63555bdc36cSWilliam A. Kennington III else if (new_start + new_size == i && new_size > skip_size) 63655bdc36cSWilliam A. Kennington III { 63755bdc36cSWilliam A. Kennington III skip_start = new_start; 63855bdc36cSWilliam A. Kennington III skip_size = new_size; 63955bdc36cSWilliam A. Kennington III } 64055bdc36cSWilliam A. Kennington III } 64155bdc36cSWilliam A. Kennington III } 64255bdc36cSWilliam A. Kennington III for (size_t i = 0; i < 8; ++i) 64355bdc36cSWilliam A. Kennington III { 64455bdc36cSWilliam A. Kennington III if (i == skip_start && skip_size > 1) 64555bdc36cSWilliam A. Kennington III { 64655bdc36cSWilliam A. Kennington III if (i == 0) 64755bdc36cSWilliam A. Kennington III { 64855bdc36cSWilliam A. Kennington III *(buf++) = ':'; 64955bdc36cSWilliam A. Kennington III } 65055bdc36cSWilliam A. Kennington III *(buf++) = ':'; 65155bdc36cSWilliam A. Kennington III i += skip_size - 1; 65255bdc36cSWilliam A. Kennington III continue; 65355bdc36cSWilliam A. Kennington III } 65455bdc36cSWilliam A. Kennington III buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i])); 65555bdc36cSWilliam A. Kennington III if (i < 7) 65655bdc36cSWilliam A. Kennington III { 65755bdc36cSWilliam A. Kennington III *(buf++) = ':'; 65855bdc36cSWilliam A. Kennington III } 65955bdc36cSWilliam A. Kennington III } 66055bdc36cSWilliam A. Kennington III return buf; 66155bdc36cSWilliam A. Kennington III } 66255bdc36cSWilliam A. Kennington III }; 66355bdc36cSWilliam A. Kennington III 66455bdc36cSWilliam A. Kennington III template <> 66555bdc36cSWilliam A. Kennington III struct ToStr<InAddrAny> 66655bdc36cSWilliam A. Kennington III { 66755bdc36cSWilliam A. Kennington III // IPv6 is the bigger of the addrs 66855bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size; 66955bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 67055bdc36cSWilliam A. Kennington III 67155bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, InAddrAny v) const noexcept 67255bdc36cSWilliam A. Kennington III { 67355bdc36cSWilliam A. Kennington III return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); }, 67455bdc36cSWilliam A. Kennington III v); 67555bdc36cSWilliam A. Kennington III } 67655bdc36cSWilliam A. Kennington III }; 67755bdc36cSWilliam A. Kennington III 67855bdc36cSWilliam A. Kennington III template <> 67955bdc36cSWilliam A. Kennington III struct ToStr<IfAddr> 68055bdc36cSWilliam A. Kennington III { 68155bdc36cSWilliam A. Kennington III // InAddrAny + sep + 3 prefix chars 68255bdc36cSWilliam A. Kennington III static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4; 68355bdc36cSWilliam A. Kennington III using buf_type = std::array<char, buf_size>; 68455bdc36cSWilliam A. Kennington III 68555bdc36cSWilliam A. Kennington III constexpr char* operator()(char* buf, IfAddr v) const noexcept 68655bdc36cSWilliam A. Kennington III { 68755bdc36cSWilliam A. Kennington III buf = ToStr<InAddrAny>{}(buf, v.getAddr()); 68855bdc36cSWilliam A. Kennington III buf = ToStr<char>{}(buf, '/'); 68955bdc36cSWilliam A. Kennington III return EncodeInt<uint8_t, 10>{}(buf, v.getPfx()); 69055bdc36cSWilliam A. Kennington III } 69155bdc36cSWilliam A. Kennington III }; 69255bdc36cSWilliam A. Kennington III 693238ef992SWilliam A. Kennington III namespace detail 694238ef992SWilliam A. Kennington III { 69571de63a2SWilliam A. Kennington III 696bb0eaccbSWilliam A. Kennington III template <typename T> 697bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 698bb0eaccbSWilliam A. Kennington III { 699bb0eaccbSWilliam A. Kennington III return false; 700bb0eaccbSWilliam A. Kennington III } 701bb0eaccbSWilliam A. Kennington III 702bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs> 703bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept 704bb0eaccbSWilliam A. Kennington III { 705bb0eaccbSWilliam A. Kennington III return vcontains<T, Vs...>() || std::is_same_v<T, V>; 706bb0eaccbSWilliam A. Kennington III } 707bb0eaccbSWilliam A. Kennington III 708bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types> 709bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool> 710bb0eaccbSWilliam A. Kennington III veq(T t, std::variant<Types...> v) noexcept 711bb0eaccbSWilliam A. Kennington III { 712bb0eaccbSWilliam A. Kennington III return std::visit( 713bb0eaccbSWilliam A. Kennington III [t](auto v) { 714bb0eaccbSWilliam A. Kennington III if constexpr (std::is_same_v<T, decltype(v)>) 715bb0eaccbSWilliam A. Kennington III { 716bb0eaccbSWilliam A. Kennington III return v == t; 717bb0eaccbSWilliam A. Kennington III } 718bb0eaccbSWilliam A. Kennington III else 719bb0eaccbSWilliam A. Kennington III { 720bb0eaccbSWilliam A. Kennington III return false; 721bb0eaccbSWilliam A. Kennington III } 722bb0eaccbSWilliam A. Kennington III }, 723bb0eaccbSWilliam A. Kennington III v); 724bb0eaccbSWilliam A. Kennington III } 725bb0eaccbSWilliam A. Kennington III 726bb0eaccbSWilliam A. Kennington III template <typename T> 72755bdc36cSWilliam A. Kennington III struct ToStrBuf 728bb0eaccbSWilliam A. Kennington III { 729bb0eaccbSWilliam A. Kennington III public: 73055bdc36cSWilliam A. Kennington III constexpr std::string_view operator()(T v) noexcept 731bb0eaccbSWilliam A. Kennington III { 73255bdc36cSWilliam A. Kennington III return {buf.data(), ToStr<T>{}(buf.data(), v)}; 73355bdc36cSWilliam A. Kennington III } 734bb0eaccbSWilliam A. Kennington III 735bb0eaccbSWilliam A. Kennington III private: 73655bdc36cSWilliam A. Kennington III typename ToStr<T>::buf_type buf; 737bb0eaccbSWilliam A. Kennington III }; 738bb0eaccbSWilliam A. Kennington III 73955bdc36cSWilliam A. Kennington III template <typename T> 74055bdc36cSWilliam A. Kennington III struct Format 741bb0eaccbSWilliam A. Kennington III { 742bb0eaccbSWilliam A. Kennington III private: 743bb0eaccbSWilliam A. Kennington III fmt::formatter<std::string_view> formatter; 744bb0eaccbSWilliam A. Kennington III 745bb0eaccbSWilliam A. Kennington III public: 746bb0eaccbSWilliam A. Kennington III template <typename ParseContext> 747bb0eaccbSWilliam A. Kennington III constexpr auto parse(ParseContext& ctx) 748bb0eaccbSWilliam A. Kennington III { 749bb0eaccbSWilliam A. Kennington III return ctx.begin(); 750bb0eaccbSWilliam A. Kennington III } 751bb0eaccbSWilliam A. Kennington III 752bb0eaccbSWilliam A. Kennington III template <typename FormatContext> 753bb0eaccbSWilliam A. Kennington III auto format(auto v, FormatContext& ctx) const 754bb0eaccbSWilliam A. Kennington III { 75555bdc36cSWilliam A. Kennington III return formatter.format(ToStrBuf<T>{}(v), ctx); 756bb0eaccbSWilliam A. Kennington III } 757bb0eaccbSWilliam A. Kennington III }; 758bb0eaccbSWilliam A. Kennington III } // namespace detail 7591bbe3d1eSWilliam A. Kennington III } // namespace network 7601bbe3d1eSWilliam A. Kennington III } // namespace phosphor 7613e471c5fSWilliam A. Kennington III 7623e471c5fSWilliam A. Kennington III template <typename... Ts> 7633e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>> 7643e471c5fSWilliam A. Kennington III { 7653e471c5fSWilliam A. Kennington III constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept 7663e471c5fSWilliam A. Kennington III { 7673e471c5fSWilliam A. Kennington III return std::apply(phosphor::network::hash_multi<Ts...>, t); 7683e471c5fSWilliam A. Kennington III } 7693e471c5fSWilliam A. Kennington III }; 770bb0eaccbSWilliam A. Kennington III 771653114fcSWilliam A. Kennington III template <> 772653114fcSWilliam A. Kennington III struct std::hash<in_addr> 773653114fcSWilliam A. Kennington III { 774653114fcSWilliam A. Kennington III std::size_t operator()(in_addr addr) const noexcept; 775653114fcSWilliam A. Kennington III }; 776653114fcSWilliam A. Kennington III 777653114fcSWilliam A. Kennington III template <> 778653114fcSWilliam A. Kennington III struct std::hash<in6_addr> 779653114fcSWilliam A. Kennington III { 780653114fcSWilliam A. Kennington III std::size_t operator()(in6_addr addr) const noexcept; 781653114fcSWilliam A. Kennington III }; 782653114fcSWilliam A. Kennington III 783b9d7cbacSWilliam A. Kennington III template <> 784b9d7cbacSWilliam A. Kennington III struct std::hash<phosphor::network::IfAddr> 785b9d7cbacSWilliam A. Kennington III { 786b9d7cbacSWilliam A. Kennington III std::size_t operator()(phosphor::network::IfAddr addr) const noexcept; 787b9d7cbacSWilliam A. Kennington III }; 788b9d7cbacSWilliam A. Kennington III 789bb0eaccbSWilliam A. Kennington III namespace fmt 790bb0eaccbSWilliam A. Kennington III { 791bb0eaccbSWilliam A. Kennington III template <> 79255bdc36cSWilliam A. Kennington III struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr> 793bb0eaccbSWilliam A. Kennington III { 794bb0eaccbSWilliam A. Kennington III }; 795bb0eaccbSWilliam A. Kennington III template <> 79655bdc36cSWilliam A. Kennington III struct formatter<in_addr> : phosphor::network::detail::Format<in_addr> 797bb0eaccbSWilliam A. Kennington III { 798bb0eaccbSWilliam A. Kennington III }; 799bb0eaccbSWilliam A. Kennington III template <> 80055bdc36cSWilliam A. Kennington III struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr> 801bb0eaccbSWilliam A. Kennington III { 802bb0eaccbSWilliam A. Kennington III }; 803bb0eaccbSWilliam A. Kennington III template <> 804bb0eaccbSWilliam A. Kennington III struct formatter<phosphor::network::InAddrAny> 80555bdc36cSWilliam A. Kennington III : phosphor::network::detail::Format<phosphor::network::InAddrAny> 806bb0eaccbSWilliam A. Kennington III { 807bb0eaccbSWilliam A. Kennington III }; 808b9d7cbacSWilliam A. Kennington III template <> 809b9d7cbacSWilliam A. Kennington III struct formatter<phosphor::network::IfAddr> 81055bdc36cSWilliam A. Kennington III : phosphor::network::detail::Format<phosphor::network::IfAddr> 811b9d7cbacSWilliam A. Kennington III { 812b9d7cbacSWilliam A. Kennington III }; 813bb0eaccbSWilliam A. Kennington III } // namespace fmt 814bb0eaccbSWilliam A. Kennington III 815bb0eaccbSWilliam A. Kennington III namespace std 816bb0eaccbSWilliam A. Kennington III { 817bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value); 818bb0eaccbSWilliam A. Kennington III string to_string(in_addr value); 819bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value); 820bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value); 821b9d7cbacSWilliam A. Kennington III string to_string(phosphor::network::IfAddr value); 822bb0eaccbSWilliam A. Kennington III } // namespace std 823bb0eaccbSWilliam A. Kennington III 824bb0eaccbSWilliam A. Kennington III template <typename T> 825bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>, 826bb0eaccbSWilliam A. Kennington III bool> 827bb0eaccbSWilliam A. Kennington III operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept 828bb0eaccbSWilliam A. Kennington III { 829bb0eaccbSWilliam A. Kennington III return phosphor::network::detail::veq(rhs, lhs); 830bb0eaccbSWilliam A. Kennington III } 831bb0eaccbSWilliam A. Kennington III 83286eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v) 833bb0eaccbSWilliam A. Kennington III { 83455bdc36cSWilliam A. Kennington III return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v); 835bb0eaccbSWilliam A. Kennington III } 836bb0eaccbSWilliam A. Kennington III 83786eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v) 838bb0eaccbSWilliam A. Kennington III { 83955bdc36cSWilliam A. Kennington III return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v); 840bb0eaccbSWilliam A. Kennington III } 841bb0eaccbSWilliam A. Kennington III 84286eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v) 843bb0eaccbSWilliam A. Kennington III { 84455bdc36cSWilliam A. Kennington III return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v); 845bb0eaccbSWilliam A. Kennington III } 846bb0eaccbSWilliam A. Kennington III 84786eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v) 848bb0eaccbSWilliam A. Kennington III { 84955bdc36cSWilliam A. Kennington III phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb; 85055bdc36cSWilliam A. Kennington III return os << tsb(v); 851bb0eaccbSWilliam A. Kennington III } 852b9d7cbacSWilliam A. Kennington III 853b9d7cbacSWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::IfAddr v) 854b9d7cbacSWilliam A. Kennington III { 85555bdc36cSWilliam A. Kennington III phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb; 85655bdc36cSWilliam A. Kennington III return os << tsb(v); 857b9d7cbacSWilliam A. Kennington III } 858