net/addr/sock: Add inet only type
Change-Id: I54737280e5eb7eb208afaca8ef4abb225d0a3b38
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/include/stdplus/net/addr/sock.hpp b/include/stdplus/net/addr/sock.hpp
index 2830f83..dc97a9a 100644
--- a/include/stdplus/net/addr/sock.hpp
+++ b/include/stdplus/net/addr/sock.hpp
@@ -214,14 +214,14 @@
namespace detail
{
+using SockInAddrV = std::variant<Sock4Addr, Sock6Addr>;
using SockAnyAddrV = std::variant<Sock4Addr, Sock6Addr, SockUAddr>;
-} // namespace detail
-
-struct SockAnyAddr : detail::SockAnyAddrV
+template <typename V>
+struct SockAnyAddr : V
{
- constexpr SockAnyAddr(auto&&... a) noexcept :
- detail::SockAnyAddrV(std::forward<decltype(a)>(a)...)
+ constexpr SockAnyAddr(auto&&... args) :
+ V(std::forward<decltype(args)>(args)...)
{}
template <SockAddr T>
@@ -250,6 +250,59 @@
}
};
+} // namespace detail
+
+struct SockInAddr : detail::SockAnyAddr<detail::SockInAddrV>
+{
+ constexpr SockInAddr(In4Addr a, std::uint16_t p) noexcept :
+ detail::SockAnyAddr<detail::SockInAddrV>(std::in_place_type<Sock4Addr>,
+ a, p)
+ {}
+ constexpr SockInAddr(Sock4Addr a) noexcept :
+ detail::SockAnyAddr<detail::SockInAddrV>(a)
+ {}
+ constexpr SockInAddr(In6Addr a, std::uint16_t p) noexcept :
+ detail::SockAnyAddr<detail::SockInAddrV>(std::in_place_type<Sock6Addr>,
+ a, p)
+ {}
+ constexpr SockInAddr(Sock6Addr a) noexcept :
+ detail::SockAnyAddr<detail::SockInAddrV>(a)
+ {}
+};
+
+template <>
+struct IsSockAddr<SockInAddr> : std::true_type
+{};
+
+struct SockAnyAddr : detail::SockAnyAddr<detail::SockAnyAddrV>
+{
+ constexpr SockAnyAddr(In4Addr a, std::uint16_t p) noexcept :
+ detail::SockAnyAddr<detail::SockAnyAddrV>(std::in_place_type<Sock4Addr>,
+ a, p)
+ {}
+ constexpr SockAnyAddr(Sock4Addr a) noexcept :
+ detail::SockAnyAddr<detail::SockAnyAddrV>(a)
+ {}
+ constexpr SockAnyAddr(In6Addr a, std::uint16_t p) noexcept :
+ detail::SockAnyAddr<detail::SockAnyAddrV>(std::in_place_type<Sock6Addr>,
+ a, p)
+ {}
+ constexpr SockAnyAddr(Sock6Addr a) noexcept :
+ detail::SockAnyAddr<detail::SockAnyAddrV>(a)
+ {}
+ constexpr SockAnyAddr(std::string_view p) :
+ detail::SockAnyAddr<detail::SockAnyAddrV>(std::in_place_type<SockUAddr>,
+ p)
+ {}
+ constexpr SockAnyAddr(SockUAddr a) noexcept :
+ detail::SockAnyAddr<detail::SockAnyAddrV>(a)
+ {}
+ constexpr SockAnyAddr(SockInAddr a) noexcept :
+ detail::SockAnyAddr<detail::SockAnyAddrV>(
+ std::visit([](auto v) { return detail::SockAnyAddrV(v); }, a))
+ {}
+};
+
template <>
struct IsSockAddr<SockAnyAddr> : std::true_type
{};
@@ -367,6 +420,35 @@
};
template <>
+struct FromStr<SockInAddr>
+{
+ template <typename CharT>
+ constexpr SockInAddr operator()(std::basic_string_view<CharT> sv) const
+ {
+ if (sv.starts_with('['))
+ {
+ return FromStr<Sock6Addr>{}(sv);
+ }
+ return FromStr<Sock4Addr>{}(sv);
+ }
+};
+
+template <>
+struct ToStr<SockInAddr>
+{
+ using type = SockInAddr;
+ static inline constexpr std::size_t buf_size =
+ std::max({ToStr<Sock4Addr>::buf_size, ToStr<Sock6Addr>::buf_size});
+
+ template <typename CharT>
+ constexpr CharT* operator()(CharT* buf, const SockInAddr& v) const noexcept
+ {
+ return std::visit(
+ [buf]<typename T>(const T& t) { return ToStr<T>{}(buf, t); }, v);
+ }
+};
+
+template <>
struct FromStr<SockAnyAddr>
{
template <typename CharT>
diff --git a/test/net/addr/sock.cpp b/test/net/addr/sock.cpp
index e326572..e5ed833 100644
--- a/test/net/addr/sock.cpp
+++ b/test/net/addr/sock.cpp
@@ -152,11 +152,40 @@
EXPECT_EQ("a unix:a b", std::format("a {} b", SockUAddr("a"sv)));
}
+TEST(SockInAddr, Basic)
+{
+ constexpr SockInAddr addr1(In4Addr{255}, 3959);
+ constexpr SockInAddr addr2(In6Addr{255}, 3959);
+ EXPECT_NE(addr1, addr2);
+ EXPECT_EQ(addr1, addr1);
+ auto buf = addr1.buf();
+ EXPECT_EQ(buf.len, sizeof(sockaddr_in));
+ EXPECT_EQ(addr1.sockaddrLen(), sizeof(sockaddr_in));
+ EXPECT_EQ(addr2.sockaddrLen(), sizeof(sockaddr_in6));
+}
+
+TEST(SockInAddr, FromStr)
+{
+ constexpr FromStr<SockInAddr> fs;
+ EXPECT_THROW(fs("abcd"sv), std::invalid_argument);
+ EXPECT_THROW(fs("/nope"sv), std::invalid_argument);
+ EXPECT_EQ((Sock4Addr{In4Addr{}, 30}), fs("0.0.0.0:30"sv));
+ EXPECT_EQ((Sock6Addr{In6Addr{}, 80, 0}), fs("[::]:80"sv));
+ EXPECT_THROW(fs("unix:/nope"sv), std::invalid_argument);
+}
+
+TEST(SockInAddr, ToStr)
+{
+ ToStrHandle<ToStr<SockInAddr>> tsh;
+ EXPECT_EQ("0.0.0.0:3949", tsh(Sock4Addr(In4Addr{}, 3949)));
+ EXPECT_EQ("a [::]:356 b",
+ std::format("a {} b", Sock6Addr(In6Addr{}, 356, 0)));
+}
+
TEST(SockAnyAddr, Basic)
{
- constexpr SockAnyAddr addr1(std::in_place_type<Sock4Addr>, In4Addr{255},
- 3959);
- constexpr SockAnyAddr addr2(std::in_place_type<SockUAddr>, "/hi"sv);
+ constexpr SockAnyAddr addr1(In4Addr{255}, 3959);
+ constexpr SockAnyAddr addr2("/hi"sv);
EXPECT_NE(addr1, addr2);
EXPECT_EQ(addr1, addr1);
auto buf = addr1.buf();