util: Refactor addrFromBuf

Change-Id: I1b2deed483eb25034ca9b4717388119af3da1c8d
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/util.cpp b/src/util.cpp
index d69357d..8a39bb1 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -151,30 +151,17 @@
     throw std::invalid_argument("Invalid addr family");
 }
 
-InAddrAny addrFromBuf(int addressFamily, std::string_view buf)
+template <int family>
+typename FamilyTraits<family>::addr addrFromBuf(std::string_view buf)
 {
-    if (addressFamily == AF_INET)
-    {
-        struct in_addr ret;
-        if (buf.size() != sizeof(ret))
-        {
-            throw std::runtime_error("Buf not in_addr sized");
-        }
-        memcpy(&ret, buf.data(), sizeof(ret));
-        return ret;
-    }
-    else if (addressFamily == AF_INET6)
-    {
-        struct in6_addr ret;
-        if (buf.size() != sizeof(ret))
-        {
-            throw std::runtime_error("Buf not in6_addr sized");
-        }
-        memcpy(&ret, buf.data(), sizeof(ret));
-        return ret;
-    }
+    return stdplus::raw::copyFromStrict<typename FamilyTraits<family>::addr>(
+        buf);
+}
 
-    throw std::runtime_error("Unsupported address family");
+InAddrAny addrFromBuf(int family, std::string_view buf)
+{
+    return familyVisit(
+        [=]<int f>() -> InAddrAny { return addrFromBuf<f>(buf); }, family);
 }
 
 std::string toString(const struct in_addr& addr)
diff --git a/src/util.hpp b/src/util.hpp
index f98a7d5..023d375 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -91,10 +91,12 @@
 
 /* @brief converts a sockaddr for the specified address family into
  *        a type_safe InAddrAny.
- * @param[in] addressFamily - The address family of the buf
+ * @param[in] family - The address family of the buf
  * @param[in] buf - The network byte order address
  */
-InAddrAny addrFromBuf(int addressFamily, std::string_view buf);
+template <int family>
+typename FamilyTraits<family>::addr addrFromBuf(std::string_view buf);
+InAddrAny addrFromBuf(int family, std::string_view buf);
 
 /* @brief converts the ip bytes into a string representation
  * @param[in] addr - input ip address to convert.
diff --git a/test/test_util.cpp b/test/test_util.cpp
index 5d05ffd..712fe98 100644
--- a/test/test_util.cpp
+++ b/test/test_util.cpp
@@ -43,7 +43,7 @@
     EXPECT_EQ(0, memcmp(&ip1, &std::get<struct in_addr>(res1), sizeof(ip1)));
     EXPECT_THROW(addrFromBuf(AF_INET, tooSmall), std::runtime_error);
     EXPECT_THROW(addrFromBuf(AF_INET, tooLarge), std::runtime_error);
-    EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::runtime_error);
+    EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::invalid_argument);
 
     struct in6_addr ip2;
     EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2));
@@ -52,7 +52,7 @@
     EXPECT_EQ(0, memcmp(&ip2, &std::get<struct in6_addr>(res2), sizeof(ip2)));
     EXPECT_THROW(addrFromBuf(AF_INET6, tooSmall), std::runtime_error);
     EXPECT_THROW(addrFromBuf(AF_INET6, tooLarge), std::runtime_error);
-    EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::runtime_error);
+    EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::invalid_argument);
 }
 
 TEST_F(TestUtil, IpToString)