Skip to content
This repository was archived by the owner on Apr 8, 2026. It is now read-only.

Commit a66d6d5

Browse files
committed
hex: Add from_hex<T> for user types
1 parent 3b05ee3 commit a66d6d5

2 files changed

Lines changed: 50 additions & 0 deletions

File tree

include/evmc/hex.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,24 @@ inline std::optional<bytes> from_hex(std::string_view hex)
113113
return {};
114114
return bs;
115115
}
116+
117+
/// Decodes hex-encoded string into custom type T with .bytes array of uint8_t.
118+
///
119+
/// The decoded bytes are right aligned in case the input is smaller than the result type.
120+
template <typename T>
121+
constexpr std::optional<T> from_hex(std::string_view s) noexcept
122+
{
123+
// Omit the optional 0x prefix.
124+
if (s.size() >= 2 && s[0] == '0' && s[1] == 'x')
125+
s.remove_prefix(2);
126+
127+
T r{}; // The T must have .bytes array. This may be lifted if std::bit_cast is available.
128+
constexpr auto num_out_bytes = std::size(r.bytes);
129+
const auto num_in_bytes = s.length() / 2;
130+
if (num_in_bytes > num_out_bytes)
131+
return {};
132+
if (!from_hex(s.begin(), s.end(), &r.bytes[num_out_bytes - num_in_bytes]))
133+
return {};
134+
return r;
135+
}
116136
} // namespace evmc

test/unittests/hex_test.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,33 @@ TEST(hex, validate_hex)
7373
EXPECT_FALSE(validate_hex("0"));
7474
EXPECT_FALSE(validate_hex("WXYZ"));
7575
}
76+
77+
TEST(hex, from_hex_to_custom_type)
78+
{
79+
struct X
80+
{
81+
uint8_t bytes[4];
82+
};
83+
constexpr auto test = [](std::string_view in) {
84+
return evmc::hex({evmc::from_hex<X>(in).value().bytes, sizeof(X)});
85+
};
86+
87+
static_assert(evmc::from_hex<X>("01").value().bytes[3] == 0x01); // Works in constexpr.
88+
89+
EXPECT_EQ(test("01020304"), "01020304");
90+
EXPECT_EQ(test("010203"), "00010203");
91+
EXPECT_EQ(test("0102"), "00000102");
92+
EXPECT_EQ(test("01"), "00000001");
93+
EXPECT_EQ(test(""), "00000000");
94+
95+
EXPECT_EQ(test("0x01020304"), "01020304");
96+
EXPECT_EQ(test("0x010203"), "00010203");
97+
EXPECT_EQ(test("0x0102"), "00000102");
98+
EXPECT_EQ(test("0x01"), "00000001");
99+
EXPECT_EQ(test("0x"), "00000000");
100+
101+
EXPECT_FALSE(evmc::from_hex<X>("0"));
102+
EXPECT_FALSE(evmc::from_hex<X>("0x "));
103+
EXPECT_FALSE(evmc::from_hex<X>("0xf"));
104+
EXPECT_FALSE(evmc::from_hex<X>("0x 00"));
105+
}

0 commit comments

Comments
 (0)