net/addr/ip: Add basic IP comparison and hash ops
Change-Id: I79ab9c225ff031da7df0c788078f2a8e5c486990
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/meson.build b/include/meson.build
index 8b8b1dd..6d02351 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -9,6 +9,7 @@
'stdplus/hash.hpp',
'stdplus/hash/array.hpp',
'stdplus/hash/tuple.hpp',
+ 'stdplus/net/addr/ip.hpp',
'stdplus/numeric/endian.hpp',
'stdplus/pinned.hpp',
'stdplus/raw.hpp',
diff --git a/include/stdplus/net/addr/ip.hpp b/include/stdplus/net/addr/ip.hpp
new file mode 100644
index 0000000..71bb7f6
--- /dev/null
+++ b/include/stdplus/net/addr/ip.hpp
@@ -0,0 +1,90 @@
+#pragma once
+#include <netinet/in.h>
+
+#include <stdplus/hash.hpp>
+
+#include <algorithm>
+#include <variant>
+
+namespace stdplus
+{
+namespace detail
+{
+struct In4AddrInner
+{
+ union
+ {
+ in_addr a;
+ uint32_t s4_addr32;
+ uint8_t s4_addr[4];
+ };
+};
+static_assert(sizeof(In4AddrInner) == sizeof(in_addr));
+} // namespace detail
+
+struct In4Addr : detail::In4AddrInner
+{
+ constexpr In4Addr() noexcept : detail::In4AddrInner() {}
+ constexpr In4Addr(in_addr a) noexcept : detail::In4AddrInner({a}) {}
+ explicit constexpr In4Addr(std::initializer_list<uint8_t> a) noexcept :
+ detail::In4AddrInner()
+ {
+ std::copy(a.begin(), a.end(), s4_addr);
+ }
+
+ constexpr operator in_addr() const noexcept
+ {
+ return a;
+ }
+
+ constexpr bool operator==(in_addr rhs) const noexcept
+ {
+ return a.s_addr == rhs.s_addr;
+ }
+
+ constexpr bool operator==(In4Addr rhs) const noexcept
+ {
+ return a.s_addr == rhs.a.s_addr;
+ }
+};
+
+struct In6Addr : in6_addr
+{
+ constexpr In6Addr() noexcept : in6_addr() {}
+ constexpr In6Addr(in6_addr a) noexcept : in6_addr(a) {}
+ explicit constexpr In6Addr(std::initializer_list<uint8_t> a) noexcept :
+ in6_addr()
+ {
+ std::copy(a.begin(), a.end(), s6_addr);
+ }
+
+ constexpr bool operator==(in6_addr rhs) const noexcept
+ {
+ return std::equal(s6_addr32, s6_addr32 + 4, rhs.s6_addr32);
+ }
+
+ constexpr bool operator==(In6Addr rhs) const noexcept
+ {
+ return *this == static_cast<in6_addr&>(rhs);
+ }
+};
+
+} // namespace stdplus
+
+template <>
+struct std::hash<stdplus::In4Addr>
+{
+ constexpr std::size_t operator()(in_addr addr) const noexcept
+ {
+ return stdplus::hashMulti(addr.s_addr);
+ }
+};
+
+template <>
+struct std::hash<stdplus::In6Addr>
+{
+ constexpr std::size_t operator()(in6_addr addr) const noexcept
+ {
+ return stdplus::hashMulti(addr.s6_addr32);
+ }
+};