xref: /openbmc/phosphor-networkd/src/types.hpp (revision 9c441fd4)
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>
871de63a2SWilliam A. Kennington III #include <numeric>
9de70ccf6SWilliam A. Kennington III #include <optional>
101bbe3d1eSWilliam A. Kennington III #include <string>
11bb0eaccbSWilliam A. Kennington III #include <string_view>
12bb0eaccbSWilliam A. Kennington III #include <type_traits>
13dd9ef815SWilliam A. Kennington III #include <unordered_map>
14f7dce2e8SWilly Tu #include <unordered_set>
151bbe3d1eSWilliam A. Kennington III #include <variant>
161bbe3d1eSWilliam A. Kennington III 
17454a0deeSWilliam A. Kennington III constexpr bool operator==(ether_addr lhs, ether_addr rhs) noexcept
18454a0deeSWilliam A. Kennington III {
19454a0deeSWilliam A. Kennington III     return std::equal(lhs.ether_addr_octet, lhs.ether_addr_octet + 6,
20454a0deeSWilliam A. Kennington III                       rhs.ether_addr_octet);
21454a0deeSWilliam A. Kennington III }
22454a0deeSWilliam A. Kennington III 
23454a0deeSWilliam A. Kennington III constexpr bool operator==(in_addr lhs, in_addr rhs) noexcept
24454a0deeSWilliam A. Kennington III {
25454a0deeSWilliam A. Kennington III     return lhs.s_addr == rhs.s_addr;
26454a0deeSWilliam A. Kennington III }
27454a0deeSWilliam A. Kennington III 
28454a0deeSWilliam A. Kennington III constexpr bool operator==(in6_addr lhs, in6_addr rhs) noexcept
29454a0deeSWilliam A. Kennington III {
30454a0deeSWilliam A. Kennington III     return std::equal(lhs.s6_addr32, lhs.s6_addr32 + 4, rhs.s6_addr32);
31454a0deeSWilliam A. Kennington III }
32454a0deeSWilliam A. Kennington III 
331bbe3d1eSWilliam A. Kennington III namespace phosphor
341bbe3d1eSWilliam A. Kennington III {
351bbe3d1eSWilliam A. Kennington III namespace network
361bbe3d1eSWilliam A. Kennington III {
371bbe3d1eSWilliam A. Kennington III 
381bbe3d1eSWilliam A. Kennington III // Byte representations for common address types in network byte order
39bb0eaccbSWilliam A. Kennington III using InAddrAny = std::variant<in_addr, in6_addr>;
40b9d7cbacSWilliam A. Kennington III class IfAddr
41b9d7cbacSWilliam A. Kennington III {
42b9d7cbacSWilliam A. Kennington III   private:
43b9d7cbacSWilliam A. Kennington III     InAddrAny addr;
44b9d7cbacSWilliam A. Kennington III     uint8_t pfx;
45b9d7cbacSWilliam A. Kennington III 
46b9d7cbacSWilliam A. Kennington III     static void invalidPfx(uint8_t pfx);
47b9d7cbacSWilliam A. Kennington III 
48b9d7cbacSWilliam A. Kennington III   public:
4989d734b9SPatrick Williams     constexpr IfAddr() : addr({}), pfx(0) {}
50b9d7cbacSWilliam A. Kennington III 
51b9d7cbacSWilliam A. Kennington III     constexpr IfAddr(InAddrAny addr, uint8_t pfx) : addr(addr), pfx(pfx)
52b9d7cbacSWilliam A. Kennington III     {
53b9d7cbacSWilliam A. Kennington III         std::visit(
54b9d7cbacSWilliam A. Kennington III             [pfx](auto v) {
55b9d7cbacSWilliam A. Kennington III             if (sizeof(v) * 8 < pfx)
56b9d7cbacSWilliam A. Kennington III             {
57b9d7cbacSWilliam A. Kennington III                 invalidPfx(pfx);
58b9d7cbacSWilliam A. Kennington III             }
59b9d7cbacSWilliam A. Kennington III             },
60b9d7cbacSWilliam A. Kennington III             addr);
61b9d7cbacSWilliam A. Kennington III     }
62b9d7cbacSWilliam A. Kennington III 
63b9d7cbacSWilliam A. Kennington III     constexpr auto getAddr() const
64b9d7cbacSWilliam A. Kennington III     {
65b9d7cbacSWilliam A. Kennington III         return addr;
66b9d7cbacSWilliam A. Kennington III     }
67b9d7cbacSWilliam A. Kennington III 
68b9d7cbacSWilliam A. Kennington III     constexpr auto getPfx() const
69b9d7cbacSWilliam A. Kennington III     {
70b9d7cbacSWilliam A. Kennington III         return pfx;
71b9d7cbacSWilliam A. Kennington III     }
72b9d7cbacSWilliam A. Kennington III 
73b9d7cbacSWilliam A. Kennington III     constexpr bool operator==(phosphor::network::IfAddr rhs) const noexcept
74b9d7cbacSWilliam A. Kennington III     {
75b9d7cbacSWilliam A. Kennington III         return addr == rhs.addr && pfx == rhs.pfx;
76b9d7cbacSWilliam A. Kennington III     }
77b9d7cbacSWilliam A. Kennington III };
781bbe3d1eSWilliam A. Kennington III 
79454a0deeSWilliam A. Kennington III /** @class InterfaceInfo
80454a0deeSWilliam A. Kennington III  *  @brief Information about interfaces from the kernel
81454a0deeSWilliam A. Kennington III  */
82454a0deeSWilliam A. Kennington III struct InterfaceInfo
83454a0deeSWilliam A. Kennington III {
84*9c441fd4SWilliam A. Kennington III     unsigned short type;
85454a0deeSWilliam A. Kennington III     unsigned idx;
86454a0deeSWilliam A. Kennington III     unsigned flags;
87454a0deeSWilliam A. Kennington III     std::optional<std::string> name = std::nullopt;
88454a0deeSWilliam A. Kennington III     std::optional<ether_addr> mac = std::nullopt;
89454a0deeSWilliam A. Kennington III     std::optional<unsigned> mtu = std::nullopt;
90454a0deeSWilliam A. Kennington III     std::optional<unsigned> parent_idx = std::nullopt;
91454a0deeSWilliam A. Kennington III     std::optional<std::string> kind = std::nullopt;
92454a0deeSWilliam A. Kennington III     std::optional<uint16_t> vlan_id = std::nullopt;
93454a0deeSWilliam A. Kennington III 
94454a0deeSWilliam A. Kennington III     constexpr bool operator==(const InterfaceInfo& rhs) const noexcept
95454a0deeSWilliam A. Kennington III     {
96454a0deeSWilliam A. Kennington III         return idx == rhs.idx && flags == rhs.flags && name == rhs.name &&
97454a0deeSWilliam A. Kennington III                mac == rhs.mac && mtu == rhs.mtu &&
98454a0deeSWilliam A. Kennington III                parent_idx == rhs.parent_idx && kind == rhs.kind &&
99454a0deeSWilliam A. Kennington III                vlan_id == rhs.vlan_id;
100454a0deeSWilliam A. Kennington III     }
101454a0deeSWilliam A. Kennington III };
102454a0deeSWilliam A. Kennington III 
1036a92363eSWilliam A. Kennington III /** @class AddressInfo
1046a92363eSWilliam A. Kennington III  *  @brief Information about a addresses from the kernel
1056a92363eSWilliam A. Kennington III  */
1066a92363eSWilliam A. Kennington III struct AddressInfo
1076a92363eSWilliam A. Kennington III {
1086a92363eSWilliam A. Kennington III     unsigned ifidx;
1096a92363eSWilliam A. Kennington III     IfAddr ifaddr;
1106a92363eSWilliam A. Kennington III     uint8_t scope;
1116a92363eSWilliam A. Kennington III     uint32_t flags;
112454a0deeSWilliam A. Kennington III 
113454a0deeSWilliam A. Kennington III     constexpr bool operator==(const AddressInfo& rhs) const noexcept
114454a0deeSWilliam A. Kennington III     {
115454a0deeSWilliam A. Kennington III         return ifidx == rhs.ifidx && ifaddr == rhs.ifaddr &&
116454a0deeSWilliam A. Kennington III                scope == rhs.scope && flags == rhs.flags;
117454a0deeSWilliam A. Kennington III     }
1186a92363eSWilliam A. Kennington III };
1196a92363eSWilliam A. Kennington III 
120a8426902SWilliam A. Kennington III /** @class NeighborInfo
121a8426902SWilliam A. Kennington III  *  @brief Information about a neighbor from the kernel
122a8426902SWilliam A. Kennington III  */
123a8426902SWilliam A. Kennington III struct NeighborInfo
124a8426902SWilliam A. Kennington III {
125a8426902SWilliam A. Kennington III     unsigned ifidx;
126454a0deeSWilliam A. Kennington III     uint16_t state;
127d3615144SWilliam A. Kennington III     std::optional<InAddrAny> addr;
128a8426902SWilliam A. Kennington III     std::optional<ether_addr> mac;
129454a0deeSWilliam A. Kennington III 
130454a0deeSWilliam A. Kennington III     constexpr bool operator==(const NeighborInfo& rhs) const noexcept
131454a0deeSWilliam A. Kennington III     {
132454a0deeSWilliam A. Kennington III         return ifidx == rhs.ifidx && state == rhs.state && addr == rhs.addr &&
133454a0deeSWilliam A. Kennington III                mac == rhs.mac;
134454a0deeSWilliam A. Kennington III     }
135a8426902SWilliam A. Kennington III };
136a8426902SWilliam A. Kennington III 
137dd9ef815SWilliam A. Kennington III struct string_hash : public std::hash<std::string_view>
138dd9ef815SWilliam A. Kennington III {
139dd9ef815SWilliam A. Kennington III     using is_transparent = void;
140dd9ef815SWilliam A. Kennington III };
141dd9ef815SWilliam A. Kennington III template <typename V>
142dd9ef815SWilliam A. Kennington III using string_umap =
143dd9ef815SWilliam A. Kennington III     std::unordered_map<std::string, V, string_hash, std::equal_to<>>;
14496444795SWilliam A. Kennington III using string_uset =
14596444795SWilliam A. Kennington III     std::unordered_set<std::string, string_hash, std::equal_to<>>;
146dd9ef815SWilliam A. Kennington III 
1473e471c5fSWilliam A. Kennington III constexpr std::size_t hash_multi() noexcept
148991a8e81SWilliam A. Kennington III {
149991a8e81SWilliam A. Kennington III     return 0;
150991a8e81SWilliam A. Kennington III }
151991a8e81SWilliam A. Kennington III 
152991a8e81SWilliam A. Kennington III template <typename T, typename... Args>
153becda1aaSWilliam A. Kennington III constexpr std::size_t hash_multi(const T& v, const Args&... args) noexcept
154991a8e81SWilliam A. Kennington III {
155991a8e81SWilliam A. Kennington III     const std::size_t seed = hash_multi(args...);
156991a8e81SWilliam A. Kennington III     return seed ^ (std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
157991a8e81SWilliam A. Kennington III }
158991a8e81SWilliam A. Kennington III 
159bb0eaccbSWilliam A. Kennington III namespace detail
160bb0eaccbSWilliam A. Kennington III {
161bb0eaccbSWilliam A. Kennington III 
16271de63a2SWilliam A. Kennington III template <typename T, uint8_t size = sizeof(T)>
16371de63a2SWilliam A. Kennington III struct BswapAlign
16471de63a2SWilliam A. Kennington III {
16571de63a2SWilliam A. Kennington III     using type = T;
16671de63a2SWilliam A. Kennington III };
16771de63a2SWilliam A. Kennington III 
16871de63a2SWilliam A. Kennington III template <typename T>
16971de63a2SWilliam A. Kennington III struct BswapAlign<T, 2>
17071de63a2SWilliam A. Kennington III {
17171de63a2SWilliam A. Kennington III     using type alignas(uint16_t) = T;
17271de63a2SWilliam A. Kennington III };
17371de63a2SWilliam A. Kennington III 
17471de63a2SWilliam A. Kennington III template <typename T>
17571de63a2SWilliam A. Kennington III struct BswapAlign<T, 4>
17671de63a2SWilliam A. Kennington III {
17771de63a2SWilliam A. Kennington III     using type alignas(uint32_t) = T;
17871de63a2SWilliam A. Kennington III };
17971de63a2SWilliam A. Kennington III 
18071de63a2SWilliam A. Kennington III template <typename T>
18171de63a2SWilliam A. Kennington III struct BswapAlign<T, 8>
18271de63a2SWilliam A. Kennington III {
18371de63a2SWilliam A. Kennington III     using type alignas(uint64_t) = T;
18471de63a2SWilliam A. Kennington III };
18571de63a2SWilliam A. Kennington III 
18671de63a2SWilliam A. Kennington III template <typename T>
18771de63a2SWilliam A. Kennington III constexpr T bswapInt(typename BswapAlign<T>::type n) noexcept
18871de63a2SWilliam A. Kennington III {
18971de63a2SWilliam A. Kennington III     static_assert(std::is_trivially_copyable_v<T>);
19071de63a2SWilliam A. Kennington III     if constexpr (sizeof(T) == 2)
19171de63a2SWilliam A. Kennington III     {
19271de63a2SWilliam A. Kennington III         reinterpret_cast<uint16_t&>(n) =
19371de63a2SWilliam A. Kennington III             __builtin_bswap16(reinterpret_cast<uint16_t&>(n));
19471de63a2SWilliam A. Kennington III     }
19571de63a2SWilliam A. Kennington III     else if constexpr (sizeof(T) == 4)
19671de63a2SWilliam A. Kennington III     {
19771de63a2SWilliam A. Kennington III         reinterpret_cast<uint32_t&>(n) =
19871de63a2SWilliam A. Kennington III             __builtin_bswap32(reinterpret_cast<uint32_t&>(n));
19971de63a2SWilliam A. Kennington III     }
20071de63a2SWilliam A. Kennington III     else if constexpr (sizeof(T) == 8)
20171de63a2SWilliam A. Kennington III     {
20271de63a2SWilliam A. Kennington III         reinterpret_cast<uint64_t&>(n) =
20371de63a2SWilliam A. Kennington III             __builtin_bswap64(reinterpret_cast<uint64_t&>(n));
20471de63a2SWilliam A. Kennington III     }
20571de63a2SWilliam A. Kennington III     else
20671de63a2SWilliam A. Kennington III     {
20771de63a2SWilliam A. Kennington III         auto b = reinterpret_cast<std::byte*>(&n);
20871de63a2SWilliam A. Kennington III         std::reverse(b, b + sizeof(n));
20971de63a2SWilliam A. Kennington III     }
21071de63a2SWilliam A. Kennington III     return n;
21171de63a2SWilliam A. Kennington III }
21271de63a2SWilliam A. Kennington III 
21371de63a2SWilliam A. Kennington III } // namespace detail
21471de63a2SWilliam A. Kennington III 
21571de63a2SWilliam A. Kennington III template <typename T>
21671de63a2SWilliam A. Kennington III constexpr T bswap(T n) noexcept
21771de63a2SWilliam A. Kennington III {
21871de63a2SWilliam A. Kennington III     return detail::bswapInt<T>(n);
21971de63a2SWilliam A. Kennington III }
22071de63a2SWilliam A. Kennington III 
22171de63a2SWilliam A. Kennington III template <typename T>
22271de63a2SWilliam A. Kennington III constexpr T hton(T n) noexcept
22371de63a2SWilliam A. Kennington III {
22471de63a2SWilliam A. Kennington III     if constexpr (std::endian::native == std::endian::big)
22571de63a2SWilliam A. Kennington III     {
22671de63a2SWilliam A. Kennington III         return n;
22771de63a2SWilliam A. Kennington III     }
22871de63a2SWilliam A. Kennington III     else if constexpr (std::endian::native == std::endian::little)
22971de63a2SWilliam A. Kennington III     {
23071de63a2SWilliam A. Kennington III         return bswap(n);
23171de63a2SWilliam A. Kennington III     }
23271de63a2SWilliam A. Kennington III     else
23371de63a2SWilliam A. Kennington III     {
23471de63a2SWilliam A. Kennington III         static_assert(std::is_same_v<T, void>);
23571de63a2SWilliam A. Kennington III     }
23671de63a2SWilliam A. Kennington III }
23771de63a2SWilliam A. Kennington III 
23871de63a2SWilliam A. Kennington III template <typename T>
23971de63a2SWilliam A. Kennington III constexpr T ntoh(T n) noexcept
24071de63a2SWilliam A. Kennington III {
24171de63a2SWilliam A. Kennington III     return hton(n);
24271de63a2SWilliam A. Kennington III }
24371de63a2SWilliam A. Kennington III 
24471de63a2SWilliam A. Kennington III namespace detail
24571de63a2SWilliam A. Kennington III {
246238ef992SWilliam A. Kennington III inline constexpr auto charLookup = []() {
247238ef992SWilliam A. Kennington III     std::array<int8_t, 256> ret;
248238ef992SWilliam A. Kennington III     std::fill(ret.begin(), ret.end(), -1);
249238ef992SWilliam A. Kennington III     for (int8_t i = 0; i < 10; ++i)
250238ef992SWilliam A. Kennington III     {
251238ef992SWilliam A. Kennington III         ret[i + '0'] = i;
252238ef992SWilliam A. Kennington III     }
253238ef992SWilliam A. Kennington III     for (int8_t i = 0; i < 26; ++i)
254238ef992SWilliam A. Kennington III     {
255238ef992SWilliam A. Kennington III         ret[i + 'A'] = i + 10;
256238ef992SWilliam A. Kennington III         ret[i + 'a'] = i + 10;
257238ef992SWilliam A. Kennington III     }
258238ef992SWilliam A. Kennington III     return ret;
259238ef992SWilliam A. Kennington III }();
260dd7c7b34SWilliam A. Kennington III inline constexpr auto intLookup = []() {
261dd7c7b34SWilliam A. Kennington III     std::array<char, 36> ret;
262dd7c7b34SWilliam A. Kennington III     for (int8_t i = 0; i < 10; ++i)
263dd7c7b34SWilliam A. Kennington III     {
264dd7c7b34SWilliam A. Kennington III         ret[i] = i + '0';
265238ef992SWilliam A. Kennington III     }
266dd7c7b34SWilliam A. Kennington III     for (int8_t i = 0; i < 26; ++i)
267dd7c7b34SWilliam A. Kennington III     {
268dd7c7b34SWilliam A. Kennington III         ret[i + 10] = i + 'a';
269dd7c7b34SWilliam A. Kennington III     }
270dd7c7b34SWilliam A. Kennington III     return ret;
271dd7c7b34SWilliam A. Kennington III }();
272dd7c7b34SWilliam A. Kennington III } // namespace detail
273238ef992SWilliam A. Kennington III 
274238ef992SWilliam A. Kennington III template <typename T, uint8_t base>
275238ef992SWilliam A. Kennington III struct DecodeInt
276238ef992SWilliam A. Kennington III {
277238ef992SWilliam A. Kennington III     static_assert(base > 1 && base <= 36);
278238ef992SWilliam A. Kennington III     static_assert(std::is_unsigned_v<T>);
279238ef992SWilliam A. Kennington III 
280238ef992SWilliam A. Kennington III     constexpr T operator()(std::string_view str) const
281238ef992SWilliam A. Kennington III     {
282238ef992SWilliam A. Kennington III         if (str.empty())
283238ef992SWilliam A. Kennington III         {
284238ef992SWilliam A. Kennington III             throw std::invalid_argument("Empty Str");
285238ef992SWilliam A. Kennington III         }
286238ef992SWilliam A. Kennington III         constexpr auto max = std::numeric_limits<T>::max();
28789d734b9SPatrick Williams         auto ret = std::accumulate(str.begin(), str.end(), T{},
28889d734b9SPatrick Williams                                    [&](T r, char c) {
289238ef992SWilliam A. Kennington III             auto v = detail::charLookup[c];
290238ef992SWilliam A. Kennington III             if (v < 0 || v >= base)
291238ef992SWilliam A. Kennington III             {
292238ef992SWilliam A. Kennington III                 throw std::invalid_argument("Invalid numeral");
293238ef992SWilliam A. Kennington III             }
294238ef992SWilliam A. Kennington III             if constexpr (std::popcount(base) == 1)
295238ef992SWilliam A. Kennington III             {
296238ef992SWilliam A. Kennington III                 constexpr auto shift = std::countr_zero(base);
297238ef992SWilliam A. Kennington III                 constexpr auto maxshift = max >> shift;
298238ef992SWilliam A. Kennington III                 if (r > maxshift)
299238ef992SWilliam A. Kennington III                 {
300238ef992SWilliam A. Kennington III                     throw std::overflow_error("Integer Decode");
301238ef992SWilliam A. Kennington III                 }
302238ef992SWilliam A. Kennington III                 return (r << shift) | v;
303238ef992SWilliam A. Kennington III             }
304238ef992SWilliam A. Kennington III             else
305238ef992SWilliam A. Kennington III             {
306238ef992SWilliam A. Kennington III                 constexpr auto maxbase = max / base;
307238ef992SWilliam A. Kennington III                 if (r > maxbase)
308238ef992SWilliam A. Kennington III                 {
309238ef992SWilliam A. Kennington III                     throw std::overflow_error("Integer Decode");
310238ef992SWilliam A. Kennington III                 }
311238ef992SWilliam A. Kennington III                 r *= base;
312238ef992SWilliam A. Kennington III                 if (max - v < r)
313238ef992SWilliam A. Kennington III                 {
314238ef992SWilliam A. Kennington III                     throw std::overflow_error("Integer Decode");
315238ef992SWilliam A. Kennington III                 }
316238ef992SWilliam A. Kennington III                 return r + v;
317238ef992SWilliam A. Kennington III             }
318238ef992SWilliam A. Kennington III         });
319238ef992SWilliam A. Kennington III         return ret;
320238ef992SWilliam A. Kennington III     }
321238ef992SWilliam A. Kennington III };
322238ef992SWilliam A. Kennington III 
323dd7c7b34SWilliam A. Kennington III template <typename T, uint8_t base>
324dd7c7b34SWilliam A. Kennington III struct EncodeInt
325dd7c7b34SWilliam A. Kennington III {
326dd7c7b34SWilliam A. Kennington III     static_assert(base > 1 && base <= 36);
327dd7c7b34SWilliam A. Kennington III     static_assert(std::is_unsigned_v<T>);
328dd7c7b34SWilliam A. Kennington III 
329dd7c7b34SWilliam A. Kennington III     static constexpr uint8_t buf_size = []() {
330dd7c7b34SWilliam A. Kennington III         T v = std::numeric_limits<T>::max();
331dd7c7b34SWilliam A. Kennington III         uint8_t i = 0;
332dd7c7b34SWilliam A. Kennington III         for (; v != 0; ++i)
333dd7c7b34SWilliam A. Kennington III         {
334dd7c7b34SWilliam A. Kennington III             v /= base;
335dd7c7b34SWilliam A. Kennington III         }
336dd7c7b34SWilliam A. Kennington III         return i;
337dd7c7b34SWilliam A. Kennington III     }();
338dd7c7b34SWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
339dd7c7b34SWilliam A. Kennington III 
340dd7c7b34SWilliam A. Kennington III     constexpr uint8_t reverseFill(char* buf, T v) const noexcept
341dd7c7b34SWilliam A. Kennington III     {
342dd7c7b34SWilliam A. Kennington III         uint8_t i = 0;
343dd7c7b34SWilliam A. Kennington III         do
344dd7c7b34SWilliam A. Kennington III         {
345dd7c7b34SWilliam A. Kennington III             if constexpr (std::popcount(base) == 1)
346dd7c7b34SWilliam A. Kennington III             {
347dd7c7b34SWilliam A. Kennington III                 buf[i++] = detail::intLookup[v & 0xf];
348dd7c7b34SWilliam A. Kennington III                 v >>= 4;
349dd7c7b34SWilliam A. Kennington III             }
350dd7c7b34SWilliam A. Kennington III             else
351dd7c7b34SWilliam A. Kennington III             {
352dd7c7b34SWilliam A. Kennington III                 buf[i++] = detail::intLookup[v % base];
353dd7c7b34SWilliam A. Kennington III                 v /= base;
354dd7c7b34SWilliam A. Kennington III             }
355dd7c7b34SWilliam A. Kennington III         } while (v > 0);
356dd7c7b34SWilliam A. Kennington III         return i;
357dd7c7b34SWilliam A. Kennington III     }
358dd7c7b34SWilliam A. Kennington III 
359dd7c7b34SWilliam A. Kennington III     constexpr char* operator()(char* buf, T v) const noexcept
360dd7c7b34SWilliam A. Kennington III     {
361dd7c7b34SWilliam A. Kennington III         uint8_t i = reverseFill(buf, v);
362dd7c7b34SWilliam A. Kennington III         std::reverse(buf, buf + i);
363dd7c7b34SWilliam A. Kennington III         return buf + i;
364dd7c7b34SWilliam A. Kennington III     }
365dd7c7b34SWilliam A. Kennington III 
366dd7c7b34SWilliam A. Kennington III     constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
367dd7c7b34SWilliam A. Kennington III     {
368dd7c7b34SWilliam A. Kennington III         uint8_t i = reverseFill(buf, v);
369dd7c7b34SWilliam A. Kennington III         auto end = buf + std::max(i, min_width);
370dd7c7b34SWilliam A. Kennington III         std::fill(buf + i, end, '0');
371dd7c7b34SWilliam A. Kennington III         std::reverse(buf, end);
372dd7c7b34SWilliam A. Kennington III         return end;
373dd7c7b34SWilliam A. Kennington III     }
374dd7c7b34SWilliam A. Kennington III };
375dd7c7b34SWilliam A. Kennington III 
376b01d08fdSWilliam A. Kennington III template <typename T>
377b01d08fdSWilliam A. Kennington III struct ToAddr
37889d734b9SPatrick Williams {};
379b01d08fdSWilliam A. Kennington III 
380b01d08fdSWilliam A. Kennington III template <>
381b01d08fdSWilliam A. Kennington III struct ToAddr<ether_addr>
382b01d08fdSWilliam A. Kennington III {
383b01d08fdSWilliam A. Kennington III     constexpr ether_addr operator()(std::string_view str) const
384b01d08fdSWilliam A. Kennington III     {
385b01d08fdSWilliam A. Kennington III         constexpr DecodeInt<uint8_t, 16> di;
386b01d08fdSWilliam A. Kennington III         ether_addr ret;
387b01d08fdSWilliam A. Kennington III         if (str.size() == 12 && str.find(":") == str.npos)
388b01d08fdSWilliam A. Kennington III         {
389b01d08fdSWilliam A. Kennington III             for (size_t i = 0; i < 6; ++i)
390b01d08fdSWilliam A. Kennington III             {
391b01d08fdSWilliam A. Kennington III                 ret.ether_addr_octet[i] = di(str.substr(i * 2, 2));
392b01d08fdSWilliam A. Kennington III             }
393b01d08fdSWilliam A. Kennington III         }
394b01d08fdSWilliam A. Kennington III         else
395b01d08fdSWilliam A. Kennington III         {
396b01d08fdSWilliam A. Kennington III             for (size_t i = 0; i < 5; ++i)
397b01d08fdSWilliam A. Kennington III             {
398b01d08fdSWilliam A. Kennington III                 auto loc = str.find(":");
399b01d08fdSWilliam A. Kennington III                 ret.ether_addr_octet[i] = di(str.substr(0, loc));
400b01d08fdSWilliam A. Kennington III                 str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
401b01d08fdSWilliam A. Kennington III                 if (str.empty())
402b01d08fdSWilliam A. Kennington III                 {
403b01d08fdSWilliam A. Kennington III                     throw std::invalid_argument("Missing mac data");
404b01d08fdSWilliam A. Kennington III                 }
405b01d08fdSWilliam A. Kennington III             }
406b01d08fdSWilliam A. Kennington III             ret.ether_addr_octet[5] = di(str);
407b01d08fdSWilliam A. Kennington III         }
408b01d08fdSWilliam A. Kennington III         return ret;
409b01d08fdSWilliam A. Kennington III     }
410b01d08fdSWilliam A. Kennington III };
411b01d08fdSWilliam A. Kennington III 
412df1178e0SWilliam A. Kennington III template <>
413df1178e0SWilliam A. Kennington III struct ToAddr<in_addr>
414df1178e0SWilliam A. Kennington III {
415df1178e0SWilliam A. Kennington III     constexpr in_addr operator()(std::string_view str) const
416df1178e0SWilliam A. Kennington III     {
417df1178e0SWilliam A. Kennington III         constexpr DecodeInt<uint8_t, 10> di;
418df1178e0SWilliam A. Kennington III         uint32_t addr = {};
419df1178e0SWilliam A. Kennington III         for (size_t i = 0; i < 3; ++i)
420df1178e0SWilliam A. Kennington III         {
421df1178e0SWilliam A. Kennington III             auto loc = str.find(".");
422df1178e0SWilliam A. Kennington III             addr |= di(str.substr(0, loc));
423df1178e0SWilliam A. Kennington III             addr <<= 8;
424df1178e0SWilliam A. Kennington III             str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
425df1178e0SWilliam A. Kennington III             if (str.empty())
426df1178e0SWilliam A. Kennington III             {
427df1178e0SWilliam A. Kennington III                 throw std::invalid_argument("Missing addr data");
428df1178e0SWilliam A. Kennington III             }
429df1178e0SWilliam A. Kennington III         }
430df1178e0SWilliam A. Kennington III         addr |= di(str);
431df1178e0SWilliam A. Kennington III         return {hton(addr)};
432df1178e0SWilliam A. Kennington III     }
433df1178e0SWilliam A. Kennington III };
434df1178e0SWilliam A. Kennington III 
435ec496a86SWilliam A. Kennington III template <>
436ec496a86SWilliam A. Kennington III struct ToAddr<in6_addr>
437ec496a86SWilliam A. Kennington III {
438ec496a86SWilliam A. Kennington III     constexpr in6_addr operator()(std::string_view str) const
439ec496a86SWilliam A. Kennington III     {
440ec496a86SWilliam A. Kennington III         constexpr DecodeInt<uint16_t, 16> di;
441ec496a86SWilliam A. Kennington III         in6_addr ret = {};
442ec496a86SWilliam A. Kennington III         size_t i = 0;
443ec496a86SWilliam A. Kennington III         while (i < 8)
444ec496a86SWilliam A. Kennington III         {
445ec496a86SWilliam A. Kennington III             auto loc = str.find(':');
446ec496a86SWilliam A. Kennington III             if (i == 6 && loc == str.npos)
447ec496a86SWilliam A. Kennington III             {
448ec496a86SWilliam A. Kennington III                 ret.s6_addr32[3] = ToAddr<in_addr>{}(str).s_addr;
449ec496a86SWilliam A. Kennington III                 return ret;
450ec496a86SWilliam A. Kennington III             }
451ec496a86SWilliam A. Kennington III             if (loc != 0 && !str.empty())
452ec496a86SWilliam A. Kennington III             {
453ec496a86SWilliam A. Kennington III                 ret.s6_addr16[i++] = hton(di(str.substr(0, loc)));
454ec496a86SWilliam A. Kennington III             }
455ec496a86SWilliam A. Kennington III             if (i < 8 && str.size() > loc + 1 && str[loc + 1] == ':')
456ec496a86SWilliam A. Kennington III             {
457ec496a86SWilliam A. Kennington III                 str.remove_prefix(loc + 2);
458ec496a86SWilliam A. Kennington III                 break;
459ec496a86SWilliam A. Kennington III             }
460ec496a86SWilliam A. Kennington III             else if (str.empty())
461ec496a86SWilliam A. Kennington III             {
462ec496a86SWilliam A. Kennington III                 throw std::invalid_argument("IPv6 Data");
463ec496a86SWilliam A. Kennington III             }
464ec496a86SWilliam A. Kennington III             str.remove_prefix(loc == str.npos ? str.size() : loc + 1);
465ec496a86SWilliam A. Kennington III         }
466ec496a86SWilliam A. Kennington III         if (str.starts_with(':'))
467ec496a86SWilliam A. Kennington III         {
468ec496a86SWilliam A. Kennington III             throw std::invalid_argument("Extra separator");
469ec496a86SWilliam A. Kennington III         }
470ec496a86SWilliam A. Kennington III         size_t j = 7;
471ec496a86SWilliam A. Kennington III         if (!str.empty() && i < 6 && str.find('.') != str.npos)
472ec496a86SWilliam A. Kennington III         {
473ec496a86SWilliam A. Kennington III             auto loc = str.rfind(':');
474ec496a86SWilliam A. Kennington III             ret.s6_addr32[3] =
475ec496a86SWilliam A. Kennington III                 ToAddr<in_addr>{}(str.substr(loc == str.npos ? 0 : loc + 1))
476ec496a86SWilliam A. Kennington III                     .s_addr;
477ec496a86SWilliam A. Kennington III             str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
478ec496a86SWilliam A. Kennington III             j -= 2;
479ec496a86SWilliam A. Kennington III         }
480ec496a86SWilliam A. Kennington III         while (!str.empty() && j > i)
481ec496a86SWilliam A. Kennington III         {
482ec496a86SWilliam A. Kennington III             auto loc = str.rfind(':');
483ec496a86SWilliam A. Kennington III             ret.s6_addr16[j--] =
484ec496a86SWilliam A. Kennington III                 hton(di(str.substr(loc == str.npos ? 0 : loc + 1)));
485ec496a86SWilliam A. Kennington III             str.remove_suffix(loc == str.npos ? str.size() : str.size() - loc);
486ec496a86SWilliam A. Kennington III         }
487ec496a86SWilliam A. Kennington III         if (!str.empty())
488ec496a86SWilliam A. Kennington III         {
489ec496a86SWilliam A. Kennington III             throw std::invalid_argument("Too much data");
490ec496a86SWilliam A. Kennington III         }
491ec496a86SWilliam A. Kennington III         return ret;
492ec496a86SWilliam A. Kennington III     }
493ec496a86SWilliam A. Kennington III };
494ec496a86SWilliam A. Kennington III 
495ead7198cSWilliam A. Kennington III template <>
496ead7198cSWilliam A. Kennington III struct ToAddr<InAddrAny>
497ead7198cSWilliam A. Kennington III {
498ead7198cSWilliam A. Kennington III     constexpr InAddrAny operator()(std::string_view str) const
499ead7198cSWilliam A. Kennington III     {
500ead7198cSWilliam A. Kennington III         if (str.find(':') == str.npos)
501ead7198cSWilliam A. Kennington III         {
502ead7198cSWilliam A. Kennington III             return ToAddr<in_addr>{}(str);
503ead7198cSWilliam A. Kennington III         }
504ead7198cSWilliam A. Kennington III         return ToAddr<in6_addr>{}(str);
505ead7198cSWilliam A. Kennington III     }
506ead7198cSWilliam A. Kennington III };
507ead7198cSWilliam A. Kennington III 
508ead7198cSWilliam A. Kennington III template <>
509ead7198cSWilliam A. Kennington III struct ToAddr<IfAddr>
510ead7198cSWilliam A. Kennington III {
511ead7198cSWilliam A. Kennington III     constexpr IfAddr operator()(std::string_view str) const
512ead7198cSWilliam A. Kennington III     {
513ead7198cSWilliam A. Kennington III         auto pos = str.rfind('/');
514ead7198cSWilliam A. Kennington III         if (pos == str.npos)
515ead7198cSWilliam A. Kennington III         {
516ead7198cSWilliam A. Kennington III             throw std::invalid_argument("Invalid IfAddr");
517ead7198cSWilliam A. Kennington III         }
518ead7198cSWilliam A. Kennington III         return {ToAddr<InAddrAny>{}(str.substr(0, pos)),
519ead7198cSWilliam A. Kennington III                 DecodeInt<uint8_t, 10>{}(str.substr(pos + 1))};
520ead7198cSWilliam A. Kennington III     }
521ead7198cSWilliam A. Kennington III };
522ead7198cSWilliam A. Kennington III 
52355bdc36cSWilliam A. Kennington III template <typename T>
52455bdc36cSWilliam A. Kennington III struct ToStr
52589d734b9SPatrick Williams {};
52655bdc36cSWilliam A. Kennington III 
52755bdc36cSWilliam A. Kennington III template <>
52855bdc36cSWilliam A. Kennington III struct ToStr<char>
52955bdc36cSWilliam A. Kennington III {
53055bdc36cSWilliam A. Kennington III     static constexpr uint8_t buf_size = 1;
53155bdc36cSWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
53255bdc36cSWilliam A. Kennington III 
53355bdc36cSWilliam A. Kennington III     constexpr char* operator()(char* buf, char v) const noexcept
53455bdc36cSWilliam A. Kennington III     {
53555bdc36cSWilliam A. Kennington III         buf[0] = v;
53655bdc36cSWilliam A. Kennington III         return buf + 1;
53755bdc36cSWilliam A. Kennington III     }
53855bdc36cSWilliam A. Kennington III };
53955bdc36cSWilliam A. Kennington III 
54055bdc36cSWilliam A. Kennington III template <>
54155bdc36cSWilliam A. Kennington III struct ToStr<ether_addr>
54255bdc36cSWilliam A. Kennington III {
54355bdc36cSWilliam A. Kennington III     // 6 octets * 2 hex chars + 5 separators
54455bdc36cSWilliam A. Kennington III     static constexpr uint8_t buf_size = 17;
54555bdc36cSWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
54655bdc36cSWilliam A. Kennington III 
54755bdc36cSWilliam A. Kennington III     constexpr char* operator()(char* buf, ether_addr v) const noexcept
54855bdc36cSWilliam A. Kennington III     {
54955bdc36cSWilliam A. Kennington III         for (char* ptr = buf + 2; ptr < buf + buf_size; ptr += 3)
55055bdc36cSWilliam A. Kennington III         {
55155bdc36cSWilliam A. Kennington III             *ptr = ':';
55255bdc36cSWilliam A. Kennington III         }
55355bdc36cSWilliam A. Kennington III         for (size_t i = 0; i < 6; ++i)
55455bdc36cSWilliam A. Kennington III         {
55555bdc36cSWilliam A. Kennington III             char* tmp = buf + i * 3;
55655bdc36cSWilliam A. Kennington III             uint8_t byte = v.ether_addr_octet[i];
55755bdc36cSWilliam A. Kennington III             EncodeInt<uint8_t, 16>{}(tmp, byte, 2);
55855bdc36cSWilliam A. Kennington III         }
55955bdc36cSWilliam A. Kennington III         return buf + buf_size;
56055bdc36cSWilliam A. Kennington III     }
56155bdc36cSWilliam A. Kennington III };
56255bdc36cSWilliam A. Kennington III 
56355bdc36cSWilliam A. Kennington III template <>
56455bdc36cSWilliam A. Kennington III struct ToStr<in_addr>
56555bdc36cSWilliam A. Kennington III {
56655bdc36cSWilliam A. Kennington III     // 4 octets * 3 dec chars + 3 separators
56755bdc36cSWilliam A. Kennington III     static constexpr uint8_t buf_size = 15;
56855bdc36cSWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
56955bdc36cSWilliam A. Kennington III 
57055bdc36cSWilliam A. Kennington III     constexpr char* operator()(char* buf, in_addr v) const noexcept
57155bdc36cSWilliam A. Kennington III     {
57255bdc36cSWilliam A. Kennington III         auto n = bswap(ntoh(v.s_addr));
57355bdc36cSWilliam A. Kennington III         for (size_t i = 0; i < 3; ++i)
57455bdc36cSWilliam A. Kennington III         {
57555bdc36cSWilliam A. Kennington III             buf = ToStr<char>{}(EncodeInt<uint8_t, 10>{}(buf, n & 0xff), '.');
57655bdc36cSWilliam A. Kennington III             n >>= 8;
57755bdc36cSWilliam A. Kennington III         }
57855bdc36cSWilliam A. Kennington III         return EncodeInt<uint8_t, 10>{}(buf, n & 0xff);
57955bdc36cSWilliam A. Kennington III     }
58055bdc36cSWilliam A. Kennington III };
58155bdc36cSWilliam A. Kennington III 
58255bdc36cSWilliam A. Kennington III template <>
58355bdc36cSWilliam A. Kennington III struct ToStr<in6_addr>
58455bdc36cSWilliam A. Kennington III {
58555bdc36cSWilliam A. Kennington III     // 8 hextets * 4 hex chars + 7 separators
58655bdc36cSWilliam A. Kennington III     static constexpr uint8_t buf_size = 39;
58755bdc36cSWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
58855bdc36cSWilliam A. Kennington III 
58955bdc36cSWilliam A. Kennington III     constexpr char* operator()(char* buf, in6_addr v) const noexcept
59055bdc36cSWilliam A. Kennington III     {
59155bdc36cSWilliam A. Kennington III         // IPv4 in IPv6 Addr
59255bdc36cSWilliam A. Kennington III         if (v.s6_addr32[0] == 0 && v.s6_addr32[1] == 0 &&
59355bdc36cSWilliam A. Kennington III             v.s6_addr32[2] == hton(uint32_t(0xffff)))
59455bdc36cSWilliam A. Kennington III         {
59555bdc36cSWilliam A. Kennington III             constexpr auto prefix = std::string_view("::ffff:");
59655bdc36cSWilliam A. Kennington III             return ToStr<in_addr>{}(
59755bdc36cSWilliam A. Kennington III                 std::copy(prefix.begin(), prefix.end(), buf), {v.s6_addr32[3]});
59855bdc36cSWilliam A. Kennington III         }
59955bdc36cSWilliam A. Kennington III 
60055bdc36cSWilliam A. Kennington III         size_t skip_start = 0;
60155bdc36cSWilliam A. Kennington III         size_t skip_size = 0;
60255bdc36cSWilliam A. Kennington III         {
60355bdc36cSWilliam A. Kennington III             size_t new_start = 0;
60455bdc36cSWilliam A. Kennington III             size_t new_size = 0;
60555bdc36cSWilliam A. Kennington III             for (size_t i = 0; i < 9; ++i)
60655bdc36cSWilliam A. Kennington III             {
60755bdc36cSWilliam A. Kennington III                 if (i < 8 && v.s6_addr16[i] == 0)
60855bdc36cSWilliam A. Kennington III                 {
60955bdc36cSWilliam A. Kennington III                     if (new_start + new_size == i)
61055bdc36cSWilliam A. Kennington III                     {
61155bdc36cSWilliam A. Kennington III                         new_size++;
61255bdc36cSWilliam A. Kennington III                     }
61355bdc36cSWilliam A. Kennington III                     else
61455bdc36cSWilliam A. Kennington III                     {
61555bdc36cSWilliam A. Kennington III                         new_start = i;
61655bdc36cSWilliam A. Kennington III                         new_size = 1;
61755bdc36cSWilliam A. Kennington III                     }
61855bdc36cSWilliam A. Kennington III                 }
61955bdc36cSWilliam A. Kennington III                 else if (new_start + new_size == i && new_size > skip_size)
62055bdc36cSWilliam A. Kennington III                 {
62155bdc36cSWilliam A. Kennington III                     skip_start = new_start;
62255bdc36cSWilliam A. Kennington III                     skip_size = new_size;
62355bdc36cSWilliam A. Kennington III                 }
62455bdc36cSWilliam A. Kennington III             }
62555bdc36cSWilliam A. Kennington III         }
62655bdc36cSWilliam A. Kennington III         for (size_t i = 0; i < 8; ++i)
62755bdc36cSWilliam A. Kennington III         {
62855bdc36cSWilliam A. Kennington III             if (i == skip_start && skip_size > 1)
62955bdc36cSWilliam A. Kennington III             {
63055bdc36cSWilliam A. Kennington III                 if (i == 0)
63155bdc36cSWilliam A. Kennington III                 {
63255bdc36cSWilliam A. Kennington III                     *(buf++) = ':';
63355bdc36cSWilliam A. Kennington III                 }
63455bdc36cSWilliam A. Kennington III                 *(buf++) = ':';
63555bdc36cSWilliam A. Kennington III                 i += skip_size - 1;
63655bdc36cSWilliam A. Kennington III                 continue;
63755bdc36cSWilliam A. Kennington III             }
63855bdc36cSWilliam A. Kennington III             buf = EncodeInt<uint16_t, 16>{}(buf, ntoh(v.s6_addr16[i]));
63955bdc36cSWilliam A. Kennington III             if (i < 7)
64055bdc36cSWilliam A. Kennington III             {
64155bdc36cSWilliam A. Kennington III                 *(buf++) = ':';
64255bdc36cSWilliam A. Kennington III             }
64355bdc36cSWilliam A. Kennington III         }
64455bdc36cSWilliam A. Kennington III         return buf;
64555bdc36cSWilliam A. Kennington III     }
64655bdc36cSWilliam A. Kennington III };
64755bdc36cSWilliam A. Kennington III 
64855bdc36cSWilliam A. Kennington III template <>
64955bdc36cSWilliam A. Kennington III struct ToStr<InAddrAny>
65055bdc36cSWilliam A. Kennington III {
65155bdc36cSWilliam A. Kennington III     // IPv6 is the bigger of the addrs
65255bdc36cSWilliam A. Kennington III     static constexpr uint8_t buf_size = ToStr<in6_addr>::buf_size;
65355bdc36cSWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
65455bdc36cSWilliam A. Kennington III 
65555bdc36cSWilliam A. Kennington III     constexpr char* operator()(char* buf, InAddrAny v) const noexcept
65655bdc36cSWilliam A. Kennington III     {
65755bdc36cSWilliam A. Kennington III         return std::visit([=](auto v) { return ToStr<decltype(v)>{}(buf, v); },
65855bdc36cSWilliam A. Kennington III                           v);
65955bdc36cSWilliam A. Kennington III     }
66055bdc36cSWilliam A. Kennington III };
66155bdc36cSWilliam A. Kennington III 
66255bdc36cSWilliam A. Kennington III template <>
66355bdc36cSWilliam A. Kennington III struct ToStr<IfAddr>
66455bdc36cSWilliam A. Kennington III {
66555bdc36cSWilliam A. Kennington III     // InAddrAny + sep + 3 prefix chars
66655bdc36cSWilliam A. Kennington III     static constexpr uint8_t buf_size = ToStr<InAddrAny>::buf_size + 4;
66755bdc36cSWilliam A. Kennington III     using buf_type = std::array<char, buf_size>;
66855bdc36cSWilliam A. Kennington III 
66955bdc36cSWilliam A. Kennington III     constexpr char* operator()(char* buf, IfAddr v) const noexcept
67055bdc36cSWilliam A. Kennington III     {
67155bdc36cSWilliam A. Kennington III         buf = ToStr<InAddrAny>{}(buf, v.getAddr());
67255bdc36cSWilliam A. Kennington III         buf = ToStr<char>{}(buf, '/');
67355bdc36cSWilliam A. Kennington III         return EncodeInt<uint8_t, 10>{}(buf, v.getPfx());
67455bdc36cSWilliam A. Kennington III     }
67555bdc36cSWilliam A. Kennington III };
67655bdc36cSWilliam A. Kennington III 
677238ef992SWilliam A. Kennington III namespace detail
678238ef992SWilliam A. Kennington III {
67971de63a2SWilliam A. Kennington III 
680bb0eaccbSWilliam A. Kennington III template <typename T>
681bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept
682bb0eaccbSWilliam A. Kennington III {
683bb0eaccbSWilliam A. Kennington III     return false;
684bb0eaccbSWilliam A. Kennington III }
685bb0eaccbSWilliam A. Kennington III 
686bb0eaccbSWilliam A. Kennington III template <typename T, typename V, typename... Vs>
687bb0eaccbSWilliam A. Kennington III constexpr bool vcontains() noexcept
688bb0eaccbSWilliam A. Kennington III {
689bb0eaccbSWilliam A. Kennington III     return vcontains<T, Vs...>() || std::is_same_v<T, V>;
690bb0eaccbSWilliam A. Kennington III }
691bb0eaccbSWilliam A. Kennington III 
692bb0eaccbSWilliam A. Kennington III template <typename T, typename... Types>
693bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<vcontains<T, Types...>(), bool>
694bb0eaccbSWilliam A. Kennington III     veq(T t, std::variant<Types...> v) noexcept
695bb0eaccbSWilliam A. Kennington III {
696bb0eaccbSWilliam A. Kennington III     return std::visit(
697bb0eaccbSWilliam A. Kennington III         [t](auto v) {
698bb0eaccbSWilliam A. Kennington III         if constexpr (std::is_same_v<T, decltype(v)>)
699bb0eaccbSWilliam A. Kennington III         {
700bb0eaccbSWilliam A. Kennington III             return v == t;
701bb0eaccbSWilliam A. Kennington III         }
702bb0eaccbSWilliam A. Kennington III         else
703bb0eaccbSWilliam A. Kennington III         {
704bb0eaccbSWilliam A. Kennington III             return false;
705bb0eaccbSWilliam A. Kennington III         }
706bb0eaccbSWilliam A. Kennington III         },
707bb0eaccbSWilliam A. Kennington III         v);
708bb0eaccbSWilliam A. Kennington III }
709bb0eaccbSWilliam A. Kennington III 
710bb0eaccbSWilliam A. Kennington III template <typename T>
71155bdc36cSWilliam A. Kennington III struct ToStrBuf
712bb0eaccbSWilliam A. Kennington III {
713bb0eaccbSWilliam A. Kennington III   public:
71455bdc36cSWilliam A. Kennington III     constexpr std::string_view operator()(T v) noexcept
715bb0eaccbSWilliam A. Kennington III     {
71655bdc36cSWilliam A. Kennington III         return {buf.data(), ToStr<T>{}(buf.data(), v)};
71755bdc36cSWilliam A. Kennington III     }
718bb0eaccbSWilliam A. Kennington III 
719bb0eaccbSWilliam A. Kennington III   private:
72055bdc36cSWilliam A. Kennington III     typename ToStr<T>::buf_type buf;
721bb0eaccbSWilliam A. Kennington III };
722bb0eaccbSWilliam A. Kennington III 
72355bdc36cSWilliam A. Kennington III template <typename T>
72455bdc36cSWilliam A. Kennington III struct Format
725bb0eaccbSWilliam A. Kennington III {
726bb0eaccbSWilliam A. Kennington III   private:
727bb0eaccbSWilliam A. Kennington III     fmt::formatter<std::string_view> formatter;
728bb0eaccbSWilliam A. Kennington III 
729bb0eaccbSWilliam A. Kennington III   public:
730bb0eaccbSWilliam A. Kennington III     template <typename ParseContext>
731bb0eaccbSWilliam A. Kennington III     constexpr auto parse(ParseContext& ctx)
732bb0eaccbSWilliam A. Kennington III     {
733bb0eaccbSWilliam A. Kennington III         return ctx.begin();
734bb0eaccbSWilliam A. Kennington III     }
735bb0eaccbSWilliam A. Kennington III 
736bb0eaccbSWilliam A. Kennington III     template <typename FormatContext>
737bb0eaccbSWilliam A. Kennington III     auto format(auto v, FormatContext& ctx) const
738bb0eaccbSWilliam A. Kennington III     {
73955bdc36cSWilliam A. Kennington III         return formatter.format(ToStrBuf<T>{}(v), ctx);
740bb0eaccbSWilliam A. Kennington III     }
741bb0eaccbSWilliam A. Kennington III };
742bb0eaccbSWilliam A. Kennington III } // namespace detail
7431bbe3d1eSWilliam A. Kennington III } // namespace network
7441bbe3d1eSWilliam A. Kennington III } // namespace phosphor
7453e471c5fSWilliam A. Kennington III 
7463e471c5fSWilliam A. Kennington III template <typename... Ts>
7473e471c5fSWilliam A. Kennington III struct std::hash<std::tuple<Ts...>>
7483e471c5fSWilliam A. Kennington III {
7493e471c5fSWilliam A. Kennington III     constexpr auto operator()(const std::tuple<Ts...>& t) const noexcept
7503e471c5fSWilliam A. Kennington III     {
7513e471c5fSWilliam A. Kennington III         return std::apply(phosphor::network::hash_multi<Ts...>, t);
7523e471c5fSWilliam A. Kennington III     }
7533e471c5fSWilliam A. Kennington III };
754bb0eaccbSWilliam A. Kennington III 
755653114fcSWilliam A. Kennington III template <>
756653114fcSWilliam A. Kennington III struct std::hash<in_addr>
757653114fcSWilliam A. Kennington III {
758653114fcSWilliam A. Kennington III     std::size_t operator()(in_addr addr) const noexcept;
759653114fcSWilliam A. Kennington III };
760653114fcSWilliam A. Kennington III 
761653114fcSWilliam A. Kennington III template <>
762653114fcSWilliam A. Kennington III struct std::hash<in6_addr>
763653114fcSWilliam A. Kennington III {
764653114fcSWilliam A. Kennington III     std::size_t operator()(in6_addr addr) const noexcept;
765653114fcSWilliam A. Kennington III };
766653114fcSWilliam A. Kennington III 
767b9d7cbacSWilliam A. Kennington III template <>
768b9d7cbacSWilliam A. Kennington III struct std::hash<phosphor::network::IfAddr>
769b9d7cbacSWilliam A. Kennington III {
770b9d7cbacSWilliam A. Kennington III     std::size_t operator()(phosphor::network::IfAddr addr) const noexcept;
771b9d7cbacSWilliam A. Kennington III };
772b9d7cbacSWilliam A. Kennington III 
773bb0eaccbSWilliam A. Kennington III namespace fmt
774bb0eaccbSWilliam A. Kennington III {
775bb0eaccbSWilliam A. Kennington III template <>
77655bdc36cSWilliam A. Kennington III struct formatter<ether_addr> : phosphor::network::detail::Format<ether_addr>
77789d734b9SPatrick Williams {};
778bb0eaccbSWilliam A. Kennington III template <>
77955bdc36cSWilliam A. Kennington III struct formatter<in_addr> : phosphor::network::detail::Format<in_addr>
78089d734b9SPatrick Williams {};
781bb0eaccbSWilliam A. Kennington III template <>
78255bdc36cSWilliam A. Kennington III struct formatter<in6_addr> : phosphor::network::detail::Format<in6_addr>
78389d734b9SPatrick Williams {};
784bb0eaccbSWilliam A. Kennington III template <>
78589d734b9SPatrick Williams struct formatter<phosphor::network::InAddrAny> :
78689d734b9SPatrick Williams     phosphor::network::detail::Format<phosphor::network::InAddrAny>
78789d734b9SPatrick Williams {};
788b9d7cbacSWilliam A. Kennington III template <>
78989d734b9SPatrick Williams struct formatter<phosphor::network::IfAddr> :
79089d734b9SPatrick Williams     phosphor::network::detail::Format<phosphor::network::IfAddr>
79189d734b9SPatrick Williams {};
792bb0eaccbSWilliam A. Kennington III } // namespace fmt
793bb0eaccbSWilliam A. Kennington III 
794bb0eaccbSWilliam A. Kennington III namespace std
795bb0eaccbSWilliam A. Kennington III {
796bb0eaccbSWilliam A. Kennington III string to_string(ether_addr value);
797bb0eaccbSWilliam A. Kennington III string to_string(in_addr value);
798bb0eaccbSWilliam A. Kennington III string to_string(in6_addr value);
799bb0eaccbSWilliam A. Kennington III string to_string(phosphor::network::InAddrAny value);
800b9d7cbacSWilliam A. Kennington III string to_string(phosphor::network::IfAddr value);
801bb0eaccbSWilliam A. Kennington III } // namespace std
802bb0eaccbSWilliam A. Kennington III 
803bb0eaccbSWilliam A. Kennington III template <typename T>
804bb0eaccbSWilliam A. Kennington III constexpr std::enable_if_t<!std::is_same_v<phosphor::network::InAddrAny, T>,
805bb0eaccbSWilliam A. Kennington III                            bool>
806bb0eaccbSWilliam A. Kennington III     operator==(phosphor::network::InAddrAny lhs, T rhs) noexcept
807bb0eaccbSWilliam A. Kennington III {
808bb0eaccbSWilliam A. Kennington III     return phosphor::network::detail::veq(rhs, lhs);
809bb0eaccbSWilliam A. Kennington III }
810bb0eaccbSWilliam A. Kennington III 
81186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, ether_addr v)
812bb0eaccbSWilliam A. Kennington III {
81355bdc36cSWilliam A. Kennington III     return os << phosphor::network::detail::ToStrBuf<ether_addr>{}(v);
814bb0eaccbSWilliam A. Kennington III }
815bb0eaccbSWilliam A. Kennington III 
81686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in_addr v)
817bb0eaccbSWilliam A. Kennington III {
81855bdc36cSWilliam A. Kennington III     return os << phosphor::network::detail::ToStrBuf<in_addr>{}(v);
819bb0eaccbSWilliam A. Kennington III }
820bb0eaccbSWilliam A. Kennington III 
82186eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, in6_addr v)
822bb0eaccbSWilliam A. Kennington III {
82355bdc36cSWilliam A. Kennington III     return os << phosphor::network::detail::ToStrBuf<in6_addr>{}(v);
824bb0eaccbSWilliam A. Kennington III }
825bb0eaccbSWilliam A. Kennington III 
82686eb8b70SWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::InAddrAny v)
827bb0eaccbSWilliam A. Kennington III {
82855bdc36cSWilliam A. Kennington III     phosphor::network::detail::ToStrBuf<phosphor::network::InAddrAny> tsb;
82955bdc36cSWilliam A. Kennington III     return os << tsb(v);
830bb0eaccbSWilliam A. Kennington III }
831b9d7cbacSWilliam A. Kennington III 
832b9d7cbacSWilliam A. Kennington III auto& operator<<(auto& os, phosphor::network::IfAddr v)
833b9d7cbacSWilliam A. Kennington III {
83455bdc36cSWilliam A. Kennington III     phosphor::network::detail::ToStrBuf<phosphor::network::IfAddr> tsb;
83555bdc36cSWilliam A. Kennington III     return os << tsb(v);
836b9d7cbacSWilliam A. Kennington III }
83713d665caSWilliam A. Kennington III 
83813d665caSWilliam A. Kennington III namespace phosphor::network
83913d665caSWilliam A. Kennington III {
84013d665caSWilliam A. Kennington III 
84113d665caSWilliam A. Kennington III /** @brief Contains all of the object information about the interface */
84213d665caSWilliam A. Kennington III struct AllIntfInfo
84313d665caSWilliam A. Kennington III {
84413d665caSWilliam A. Kennington III     InterfaceInfo intf;
84513d665caSWilliam A. Kennington III     std::optional<in_addr> defgw4 = std::nullopt;
84613d665caSWilliam A. Kennington III     std::optional<in6_addr> defgw6 = std::nullopt;
84713d665caSWilliam A. Kennington III     std::unordered_map<IfAddr, AddressInfo> addrs = {};
84813d665caSWilliam A. Kennington III     std::unordered_map<InAddrAny, NeighborInfo> staticNeighs = {};
84913d665caSWilliam A. Kennington III };
85013d665caSWilliam A. Kennington III 
85113d665caSWilliam A. Kennington III } // namespace phosphor::network
852