1717 * under the License.
1818 */
1919
20- #include " iceberg/util/uuid_util .h"
20+ #include " iceberg/util/uuid .h"
2121
2222#include < chrono>
2323#include < cstdint>
3232
3333namespace iceberg {
3434
35- std::array<uint8_t , 16 > UUIDUtils::GenerateUuidV4 () {
35+ Uuid::Uuid (std::array<uint8_t , kUuidSize > data) : data_(std::move(data)) {}
36+
37+ Uuid Uuid::GenerateV4 () {
3638 static std::random_device rd;
3739 static std::mt19937 gen (rd ());
3840 static std::uniform_int_distribution<uint64_t > distrib (
@@ -55,20 +57,20 @@ std::array<uint8_t, 16> UUIDUtils::GenerateUuidV4() {
5557 // Set variant field, top two bits are 1, 0
5658 uuid[8 ] = (uuid[8 ] & 0x3F ) | 0x80 ;
5759
58- return uuid;
60+ return Uuid ( std::move ( uuid)) ;
5961}
6062
61- std::array< uint8_t , 16 > UUIDUtils::GenerateUuidV7 () {
63+ Uuid Uuid::GenerateV7 () {
6264 // Get the current time in milliseconds since the Unix epoch
6365 auto now = std::chrono::system_clock::now ();
6466 auto duration_since_epoch = now.time_since_epoch ();
6567 auto unix_ts_ms =
6668 std::chrono::duration_cast<std::chrono::milliseconds>(duration_since_epoch).count ();
6769
68- return GenerateUuidV7 (static_cast <uint64_t >(unix_ts_ms));
70+ return GenerateV7 (static_cast <uint64_t >(unix_ts_ms));
6971}
7072
71- std::array< uint8_t , 16 > UUIDUtils::GenerateUuidV7 (uint64_t unix_ts_ms) {
73+ Uuid Uuid::GenerateV7 (uint64_t unix_ts_ms) {
7274 std::array<uint8_t , 16 > uuid = {};
7375
7476 // Set the timestamp (in milliseconds since Unix epoch)
@@ -98,14 +100,14 @@ std::array<uint8_t, 16> UUIDUtils::GenerateUuidV7(uint64_t unix_ts_ms) {
98100 // set variant field, top two bits are 1, 0
99101 uuid[8 ] = (uuid[8 ] & 0x3F ) | 0x80 ;
100102
101- return uuid;
103+ return Uuid ( std::move ( uuid)) ;
102104}
103105
104106namespace {
105107
106108constexpr std::array<uint8_t , 256 > BuildHexTable () {
107109 std::array<uint8_t , 256 > buf{};
108- for (int i = 0 ; i < 256 ; i++) {
110+ for (int32_t i = 0 ; i < 256 ; i++) {
109111 if (i >= ' 0' && i <= ' 9' ) {
110112 buf[i] = static_cast <uint8_t >(i - ' 0' );
111113 } else if (i >= ' a' && i <= ' f' ) {
@@ -121,35 +123,35 @@ constexpr std::array<uint8_t, 256> BuildHexTable() {
121123
122124constexpr std::array<uint8_t , 256 > BuildShl4Table () {
123125 std::array<uint8_t , 256 > buf{};
124- for (int i = 0 ; i < 256 ; i++) {
126+ for (int32_t i = 0 ; i < 256 ; i++) {
125127 buf[i] = static_cast <uint8_t >(i << 4 );
126128 }
127129 return buf;
128130}
129131
130- constexpr auto HEX_TABLE = BuildHexTable();
131- constexpr auto SHL4_TABLE = BuildShl4Table();
132+ constexpr auto kHexTable = BuildHexTable();
133+ constexpr auto kShl4Table = BuildShl4Table();
132134
133135// Parse a UUID string without dashes, e.g. "67e5504410b1426f9247bb680e5fe0c8"
134- inline Result<std::array< uint8_t , 16 > > ParseSimple (std::string_view s) {
136+ inline Result<Uuid > ParseSimple (std::string_view s) {
135137 ICEBERG_DCHECK (s.size () == 32 , " s must be 32 characters long" );
136138
137- std::array<uint8_t , 16 > buf {};
139+ std::array<uint8_t , 16 > uuid {};
138140 for (size_t i = 0 ; i < 16 ; i++) {
139- uint8_t h1 = HEX_TABLE [static_cast <uint8_t >(s[i * 2 ])];
140- uint8_t h2 = HEX_TABLE [static_cast <uint8_t >(s[i * 2 + 1 ])];
141+ uint8_t h1 = kHexTable [static_cast <uint8_t >(s[i * 2 ])];
142+ uint8_t h2 = kHexTable [static_cast <uint8_t >(s[i * 2 + 1 ])];
141143
142- if ((h1 | h2) == 0xff ) {
144+ if ((h1 | h2) == 0xFF ) {
143145 return InvalidArgument (" Invalid UUID string: {}" , s);
144146 }
145147
146- buf [i] = static_cast <uint8_t >(SHL4_TABLE [h1] | h2);
148+ uuid [i] = static_cast <uint8_t >(kShl4Table [h1] | h2);
147149 }
148- return buf ;
150+ return Uuid ( std::move (uuid)) ;
149151}
150152
151153// Parse a UUID string with dashes, e.g. "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
152- inline Result<std::array< uint8_t , 16 > > ParseHyphenated (std::string_view s) {
154+ inline Result<Uuid > ParseHyphenated (std::string_view s) {
153155 ICEBERG_DCHECK (s.size () == 36 , " s must be 36 characters long" );
154156
155157 // Check that dashes are in the right places
@@ -158,29 +160,29 @@ inline Result<std::array<uint8_t, 16>> ParseHyphenated(std::string_view s) {
158160 }
159161
160162 constexpr std::array<size_t , 8 > positions = {0 , 4 , 9 , 14 , 19 , 24 , 28 , 32 };
161- std::array<uint8_t , 16 > buf {};
163+ std::array<uint8_t , 16 > uuid {};
162164
163165 for (size_t j = 0 ; j < 8 ; j++) {
164166 size_t i = positions[j];
165- uint8_t h1 = HEX_TABLE [static_cast <uint8_t >(s[i])];
166- uint8_t h2 = HEX_TABLE [static_cast <uint8_t >(s[i + 1 ])];
167- uint8_t h3 = HEX_TABLE [static_cast <uint8_t >(s[i + 2 ])];
168- uint8_t h4 = HEX_TABLE [static_cast <uint8_t >(s[i + 3 ])];
167+ uint8_t h1 = kHexTable [static_cast <uint8_t >(s[i])];
168+ uint8_t h2 = kHexTable [static_cast <uint8_t >(s[i + 1 ])];
169+ uint8_t h3 = kHexTable [static_cast <uint8_t >(s[i + 2 ])];
170+ uint8_t h4 = kHexTable [static_cast <uint8_t >(s[i + 3 ])];
169171
170- if ((h1 | h2 | h3 | h4) == 0xff ) {
172+ if ((h1 | h2 | h3 | h4) == 0xFF ) {
171173 return InvalidArgument (" Invalid UUID string: {}" , s);
172174 }
173175
174- buf [j * 2 ] = static_cast <uint8_t >(SHL4_TABLE [h1] | h2);
175- buf [j * 2 + 1 ] = static_cast <uint8_t >(SHL4_TABLE [h3] | h4);
176+ uuid [j * 2 ] = static_cast <uint8_t >(kShl4Table [h1] | h2);
177+ uuid [j * 2 + 1 ] = static_cast <uint8_t >(kShl4Table [h3] | h4);
176178 }
177179
178- return buf ;
180+ return Uuid ( std::move (uuid)) ;
179181}
180182
181183} // namespace
182184
183- Result<std::array< uint8_t , 16 >> UUIDUtils ::FromString (std::string_view str) {
185+ Result<Uuid> Uuid ::FromString (std::string_view str) {
184186 if (str.size () == 32 ) {
185187 return ParseSimple (str);
186188 } else if (str.size () == 36 ) {
@@ -190,15 +192,30 @@ Result<std::array<uint8_t, 16>> UUIDUtils::FromString(std::string_view str) {
190192 }
191193}
192194
193- std::string UUIDUtils::ToString (std::span<uint8_t > uuid) {
195+ Result<Uuid> Uuid::FromBytes (std::span<const uint8_t > bytes) {
196+ if (bytes.size () != kUuidSize ) [[unlikely]] {
197+ return InvalidArgument (" UUID byte array must be exactly {} bytes, was {}" , kUuidSize ,
198+ bytes.size ());
199+ }
200+ std::array<uint8_t , kUuidSize > data;
201+ std::memcpy (data.data (), bytes.data (), kUuidSize );
202+ return Uuid (std::move (data));
203+ }
204+
205+ uint8_t Uuid::operator [](size_t index) const {
206+ ICEBERG_CHECK (index < kUuidSize , " UUID index out of range: {}" , index);
207+ return data_[index];
208+ }
209+
210+ std::string Uuid::ToString () const {
194211 static const char * hex_chars = " 0123456789abcdef" ;
195- ICEBERG_CHECK (uuid.size () == 16 , " uuid must be 16 bytes long" );
196212
197213 return std::format (
198214 " {:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}"
199215 " {:02x}{:02x}{:02x}" ,
200- uuid[0 ], uuid[1 ], uuid[2 ], uuid[3 ], uuid[4 ], uuid[5 ], uuid[6 ], uuid[7 ], uuid[8 ],
201- uuid[9 ], uuid[10 ], uuid[11 ], uuid[12 ], uuid[13 ], uuid[14 ], uuid[15 ]);
216+ data_[0 ], data_[1 ], data_[2 ], data_[3 ], data_[4 ], data_[5 ], data_[6 ], data_[7 ],
217+ data_[8 ], data_[9 ], data_[10 ], data_[11 ], data_[12 ], data_[13 ], data_[14 ],
218+ data_[15 ]);
202219}
203220
204221} // namespace iceberg
0 commit comments