util: Add a function for converting MAC addresses

We need to be able to convert a mac addresses from byte form into our
typical human readable string form.

Tested:
    Unit tests pass.

Change-Id: I6e68cfefd4d5962e1125c1b5229e61fce475729a
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/test/test_util.cpp b/test/test_util.cpp
index 6c647ed..f536bd7 100644
--- a/test/test_util.cpp
+++ b/test/test_util.cpp
@@ -2,6 +2,7 @@
 
 #include <netinet/in.h>
 
+#include <cstddef>
 #include <xyz/openbmc_project/Common/error.hpp>
 
 #include <gtest/gtest.h>
@@ -22,6 +23,27 @@
     }
 };
 
+TEST_F(TestUtil, ToHex)
+{
+    EXPECT_EQ('E', mac_address::internal::toHex(std::byte(0xfe)));
+    EXPECT_EQ('A', mac_address::internal::toHex(std::byte(10)));
+    EXPECT_EQ('4', mac_address::internal::toHex(std::byte(4)));
+}
+
+TEST_F(TestUtil, MacToString)
+{
+    MacAddr mac1{
+        std::byte(0x00), std::byte(0xDE), std::byte(0xAD),
+        std::byte(0x00), std::byte(0xBE), std::byte(0xEF),
+    };
+    EXPECT_EQ("00:DE:AD:00:BE:EF", mac_address::toString(mac1));
+    MacAddr mac2{
+        std::byte(0x70), std::byte(0xFF), std::byte(0x84),
+        std::byte(0x09), std::byte(0x35), std::byte(0x09),
+    };
+    EXPECT_EQ("70:FF:84:09:35:09", mac_address::toString(mac2));
+}
+
 TEST_F(TestUtil, IpValidation)
 {
     std::string ipaddress = "0.0.0.0";
diff --git a/util.cpp b/util.cpp
index 35a6ed7..7aa4e2a 100644
--- a/util.cpp
+++ b/util.cpp
@@ -547,6 +547,21 @@
     return sdbusplus::message::variant_ns::get<std::string>(value);
 }
 
+std::string toString(const MacAddr& mac)
+{
+    std::string str;
+    str.reserve(mac.size() * 3);
+    for (size_t i = 0; i < mac.size(); ++i)
+    {
+        str.push_back(internal::toHex(mac[i] >> 4));
+        str.push_back(internal::toHex(mac[i]));
+        str.push_back(':');
+    }
+    // Remove trailing semicolon
+    str.pop_back();
+    return str;
+}
+
 } // namespace mac_address
 } // namespace network
 } // namespace phosphor
diff --git a/util.hpp b/util.hpp
index 51c2e04..e01c744 100644
--- a/util.hpp
+++ b/util.hpp
@@ -8,6 +8,7 @@
 
 #include <regex>
 #include <sdbusplus/bus.hpp>
+#include <string>
 
 namespace phosphor
 {
@@ -47,6 +48,12 @@
  */
 std::string getfromInventory(sdbusplus::bus::bus& bus);
 
+/** @brief Converts the given mac address bytes into a string
+ *  @param[in] bytes - The mac address
+ *  @returns A valid mac address string
+ */
+std::string toString(const MacAddr& mac);
+
 namespace internal
 {
 /** @brief Converts the given mac address into unsigned 64 bit integer
@@ -66,6 +73,13 @@
            static_cast<uint64_t>(mac[4]) << 8 | static_cast<uint64_t>(mac[5]);
 }
 
+/** @brief Converts the lower nibble of a byte value to a hex digit
+ */
+inline char toHex(std::byte byte)
+{
+    uint8_t val = std::to_integer<uint8_t>(byte) & 0xf;
+    return val < 10 ? '0' + val : 'A' + (val - 10);
+}
 } // namespace internal
 } // namespace mac_address