net/addr/sock: Fix SockAddrBuf alignment and layout

We want it to be trivial to discover the familty and we need to
guarantee the storage alignment works for all converted class types.

Change-Id: I848021c425e96de6ca16ee9067f1b9d0522ba03c
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 dc97a9a..970fbd2 100644
--- a/include/stdplus/net/addr/sock.hpp
+++ b/include/stdplus/net/addr/sock.hpp
@@ -17,16 +17,36 @@
 namespace stdplus
 {
 
-struct SockAddrBuf : sockaddr
+struct SockAddrBuf
 {
-    static inline constexpr std::size_t maxLen =
-        std::max(
-            {sizeof(sockaddr_in), sizeof(sockaddr_in6), sizeof(sockaddr_un)}) -
-        sizeof(sockaddr);
-    std::array<std::uint8_t, maxLen> buf;
+    union
+    {
+        sa_family_t fam;
+        sockaddr_storage ss_;
+    };
     std::uint8_t len;
+
+    static inline constexpr std::size_t maxLen = sizeof(ss_);
     static_assert(maxLen <= std::numeric_limits<decltype(len)>::max());
+
+    inline operator const sockaddr*() const
+    {
+        return reinterpret_cast<const sockaddr*>(&ss_);
+    }
+    inline operator sockaddr*()
+    {
+        return reinterpret_cast<sockaddr*>(&ss_);
+    }
 };
+static_assert(std::is_standard_layout_v<SockAddrBuf>);
+static_assert(offsetof(SockAddrBuf, ss_) == 0);
+static_assert(offsetof(SockAddrBuf, fam) ==
+              offsetof(sockaddr_storage, ss_family));
+static_assert(SockAddrBuf::maxLen <= offsetof(SockAddrBuf, len));
+static_assert(alignof(SockAddrBuf) % alignof(sockaddr) == 0);
+static_assert(alignof(SockAddrBuf) % alignof(sockaddr_in) == 0);
+static_assert(alignof(SockAddrBuf) % alignof(sockaddr_in6) == 0);
+static_assert(alignof(SockAddrBuf) % alignof(sockaddr_un) == 0);
 
 template <typename T>
 struct IsSockAddr : std::false_type