Skip to content

Commit

Permalink
hex: Add from_hex<T> for user types
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed May 25, 2022
1 parent 4acbda7 commit a573243
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
17 changes: 17 additions & 0 deletions include/evmc/hex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,21 @@ inline std::optional<bytes> from_hex(std::string_view hex)
return {};
return bs;
}

template <typename T>
constexpr std::optional<T> from_hex(std::string_view s) noexcept
{
// Omit the optional 0x prefix.
if (s.size() >= 2 && s[0] == '0' && s[1] == 'x')
s.remove_prefix(2);

T r{}; // The T must have .bytes array. This may be lifted if std::bit_cast is available.
constexpr auto num_out_bytes = std::size(r.bytes);
const auto num_in_bytes = s.length() / 2;
if (num_in_bytes > num_out_bytes)
return {};
if (!from_hex(s.begin(), s.end(), &r.bytes[num_out_bytes - num_in_bytes]))
return {};
return r;
}
} // namespace evmc
30 changes: 30 additions & 0 deletions test/unittests/hex_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,33 @@ TEST(hex, validate_hex)
EXPECT_FALSE(validate_hex("0"));
EXPECT_FALSE(validate_hex("WXYZ"));
}

TEST(hex, from_hex_to_custom_type)
{
struct X
{
uint8_t bytes[4];
};
constexpr auto test = [](std::string_view in) {
return evmc::hex({evmc::from_hex<X>(in).value().bytes, sizeof(X)});
};

static_assert(evmc::from_hex<X>("01").value().bytes[3] == 0x01); // Works in constexpr.

EXPECT_EQ(test("01020304"), "01020304");
EXPECT_EQ(test("010203"), "00010203");
EXPECT_EQ(test("0102"), "00000102");
EXPECT_EQ(test("01"), "00000001");
EXPECT_EQ(test(""), "00000000");

EXPECT_EQ(test("0x01020304"), "01020304");
EXPECT_EQ(test("0x010203"), "00010203");
EXPECT_EQ(test("0x0102"), "00000102");
EXPECT_EQ(test("0x01"), "00000001");
EXPECT_EQ(test("0x"), "00000000");

EXPECT_FALSE(evmc::from_hex<X>("0"));
EXPECT_FALSE(evmc::from_hex<X>("0x "));
EXPECT_FALSE(evmc::from_hex<X>("0xf"));
EXPECT_FALSE(evmc::from_hex<X>("0x 00"));
}

0 comments on commit a573243

Please sign in to comment.