3232
3333namespace iceberg {
3434
35- Uuid::Uuid (std::array<uint8_t , kUuidSize > data) : data_(std::move(data)) {}
36-
37- Uuid Uuid::GenerateV4 () {
38- static std::random_device rd;
39- static std::mt19937 gen (rd ());
40- static std::uniform_int_distribution<uint64_t > distrib (
41- std::numeric_limits<uint64_t >::min (), std::numeric_limits<uint64_t >::max ());
42- std::array<uint8_t , 16 > uuid;
43-
44- // Generate two random 64-bit integers
45- uint64_t high_bits = distrib (gen);
46- uint64_t low_bits = distrib (gen);
47-
48- // Combine them into a uint128_t
49- uint128_t random_128_bit_number = (static_cast <uint128_t >(high_bits) << 64 ) | low_bits;
50-
51- // Copy the bytes into the uuid array
52- std::memcpy (uuid.data (), &random_128_bit_number, 16 );
53-
54- // Set magic numbers for a "version 4" (pseudorandom) UUID and variant,
55- // see https://datatracker.ietf.org/doc/html/rfc9562#name-uuid-version-4
56- uuid[6 ] = (uuid[6 ] & 0x0F ) | 0x40 ;
57- // Set variant field, top two bits are 1, 0
58- uuid[8 ] = (uuid[8 ] & 0x3F ) | 0x80 ;
59-
60- return Uuid (std::move (uuid));
61- }
62-
63- Uuid Uuid::GenerateV7 () {
64- // Get the current time in milliseconds since the Unix epoch
65- auto now = std::chrono::system_clock::now ();
66- auto duration_since_epoch = now.time_since_epoch ();
67- auto unix_ts_ms =
68- std::chrono::duration_cast<std::chrono::milliseconds>(duration_since_epoch).count ();
69-
70- return GenerateV7 (static_cast <uint64_t >(unix_ts_ms));
71- }
72-
73- Uuid Uuid::GenerateV7 (uint64_t unix_ts_ms) {
74- std::array<uint8_t , 16 > uuid = {};
75-
76- // Set the timestamp (in milliseconds since Unix epoch)
77- uuid[0 ] = (unix_ts_ms >> 40 ) & 0xFF ;
78- uuid[1 ] = (unix_ts_ms >> 32 ) & 0xFF ;
79- uuid[2 ] = (unix_ts_ms >> 24 ) & 0xFF ;
80- uuid[3 ] = (unix_ts_ms >> 16 ) & 0xFF ;
81- uuid[4 ] = (unix_ts_ms >> 8 ) & 0xFF ;
82- uuid[5 ] = unix_ts_ms & 0xFF ;
83-
84- // Generate random bytes for the remaining fields
85- static std::random_device rd;
86- static std::mt19937 gen (rd ());
87- static std::uniform_int_distribution<uint16_t > distrib (
88- std::numeric_limits<uint16_t >::min (), std::numeric_limits<uint16_t >::max ());
89-
90- // Note: uint8_t is invalid for uniform_int_distribution on Windows
91- for (size_t i = 6 ; i < 16 ; i += 2 ) {
92- auto rand = static_cast <uint16_t >(distrib (gen));
93- uuid[i] = (rand >> 8 ) & 0xFF ;
94- uuid[i + 1 ] = rand & 0xFF ;
95- }
96-
97- // Set magic numbers for a "version 7" (pseudorandom) UUID and variant,
98- // see https://www.rfc-editor.org/rfc/rfc9562#name-version-field
99- uuid[6 ] = (uuid[6 ] & 0x0F ) | 0x70 ;
100- // set variant field, top two bits are 1, 0
101- uuid[8 ] = (uuid[8 ] & 0x3F ) | 0x80 ;
102-
103- return Uuid (std::move (uuid));
104- }
105-
10635namespace {
10736
10837constexpr std::array<uint8_t , 256 > BuildHexTable () {
@@ -182,6 +111,77 @@ inline Result<Uuid> ParseHyphenated(std::string_view s) {
182111
183112} // namespace
184113
114+ Uuid::Uuid (std::array<uint8_t , kLength > data) : data_(std::move(data)) {}
115+
116+ Uuid Uuid::GenerateV4 () {
117+ static std::random_device rd;
118+ static std::mt19937 gen (rd ());
119+ static std::uniform_int_distribution<uint64_t > distrib (
120+ std::numeric_limits<uint64_t >::min (), std::numeric_limits<uint64_t >::max ());
121+ std::array<uint8_t , 16 > uuid;
122+
123+ // Generate two random 64-bit integers
124+ uint64_t high_bits = distrib (gen);
125+ uint64_t low_bits = distrib (gen);
126+
127+ // Combine them into a uint128_t
128+ uint128_t random_128_bit_number = (static_cast <uint128_t >(high_bits) << 64 ) | low_bits;
129+
130+ // Copy the bytes into the uuid array
131+ std::memcpy (uuid.data (), &random_128_bit_number, 16 );
132+
133+ // Set magic numbers for a "version 4" (pseudorandom) UUID and variant,
134+ // see https://datatracker.ietf.org/doc/html/rfc9562#name-uuid-version-4
135+ uuid[6 ] = (uuid[6 ] & 0x0F ) | 0x40 ;
136+ // Set variant field, top two bits are 1, 0
137+ uuid[8 ] = (uuid[8 ] & 0x3F ) | 0x80 ;
138+
139+ return Uuid (std::move (uuid));
140+ }
141+
142+ Uuid Uuid::GenerateV7 () {
143+ // Get the current time in milliseconds since the Unix epoch
144+ auto now = std::chrono::system_clock::now ();
145+ auto duration_since_epoch = now.time_since_epoch ();
146+ auto unix_ts_ms =
147+ std::chrono::duration_cast<std::chrono::milliseconds>(duration_since_epoch).count ();
148+
149+ return GenerateV7 (static_cast <uint64_t >(unix_ts_ms));
150+ }
151+
152+ Uuid Uuid::GenerateV7 (uint64_t unix_ts_ms) {
153+ std::array<uint8_t , 16 > uuid = {};
154+
155+ // Set the timestamp (in milliseconds since Unix epoch)
156+ uuid[0 ] = (unix_ts_ms >> 40 ) & 0xFF ;
157+ uuid[1 ] = (unix_ts_ms >> 32 ) & 0xFF ;
158+ uuid[2 ] = (unix_ts_ms >> 24 ) & 0xFF ;
159+ uuid[3 ] = (unix_ts_ms >> 16 ) & 0xFF ;
160+ uuid[4 ] = (unix_ts_ms >> 8 ) & 0xFF ;
161+ uuid[5 ] = unix_ts_ms & 0xFF ;
162+
163+ // Generate random bytes for the remaining fields
164+ static std::random_device rd;
165+ static std::mt19937 gen (rd ());
166+ static std::uniform_int_distribution<uint16_t > distrib (
167+ std::numeric_limits<uint16_t >::min (), std::numeric_limits<uint16_t >::max ());
168+
169+ // Note: uint8_t is invalid for uniform_int_distribution on Windows
170+ for (size_t i = 6 ; i < 16 ; i += 2 ) {
171+ auto rand = static_cast <uint16_t >(distrib (gen));
172+ uuid[i] = (rand >> 8 ) & 0xFF ;
173+ uuid[i + 1 ] = rand & 0xFF ;
174+ }
175+
176+ // Set magic numbers for a "version 7" (pseudorandom) UUID and variant,
177+ // see https://www.rfc-editor.org/rfc/rfc9562#name-version-field
178+ uuid[6 ] = (uuid[6 ] & 0x0F ) | 0x70 ;
179+ // set variant field, top two bits are 1, 0
180+ uuid[8 ] = (uuid[8 ] & 0x3F ) | 0x80 ;
181+
182+ return Uuid (std::move (uuid));
183+ }
184+
185185Result<Uuid> Uuid::FromString (std::string_view str) {
186186 if (str.size () == 32 ) {
187187 return ParseSimple (str);
@@ -193,23 +193,23 @@ Result<Uuid> Uuid::FromString(std::string_view str) {
193193}
194194
195195Result<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 ,
196+ if (bytes.size () != kLength ) [[unlikely]] {
197+ return InvalidArgument (" UUID byte array must be exactly {} bytes, was {}" , kLength ,
198198 bytes.size ());
199199 }
200- std::array<uint8_t , kUuidSize > data;
201- std::memcpy (data.data (), bytes.data (), kUuidSize );
200+ std::array<uint8_t , kLength > data;
201+ std::memcpy (data.data (), bytes.data (), kLength );
202202 return Uuid (std::move (data));
203203}
204204
205205uint8_t Uuid::operator [](size_t index) const {
206- ICEBERG_CHECK (index < kUuidSize , " UUID index out of range: {}" , index);
206+ ICEBERG_CHECK (index < kLength , " UUID index out of range: {}" , index);
207207 return data_[index];
208208}
209209
210- std::string Uuid::ToString () const {
211- static const char * hex_chars = " 0123456789abcdef" ;
210+ std::array<uint8_t , Uuid::kLength > Uuid::ToBigEndianBytes () const { return data_; }
212211
212+ std::string Uuid::ToString () const {
213213 return std::format (
214214 " {:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}"
215215 " {:02x}{:02x}{:02x}" ,
0 commit comments