ulid-transform 1.0.1__cp313-cp313-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,716 @@
1
+ #ifndef ULID_STRUCT_HH
2
+ #define ULID_STRUCT_HH
3
+
4
+ #include <chrono>
5
+ #include <cstdlib>
6
+ #include <ctime>
7
+ #include <functional>
8
+ #include <random>
9
+ #include <vector>
10
+
11
+ #if _MSC_VER > 0
12
+ typedef uint32_t rand_t;
13
+ # else
14
+ typedef uint8_t rand_t;
15
+ #endif
16
+
17
+ namespace ulid {
18
+
19
+ /**
20
+ * ULID is a 16 byte Universally Unique Lexicographically Sortable Identifier
21
+ * */
22
+ struct ULID {
23
+ uint8_t data[16];
24
+
25
+ ULID() {
26
+ // for (int i = 0 ; i < 16 ; i++) {
27
+ // data[i] = 0;
28
+ // }
29
+
30
+ // unrolled loop
31
+ data[0] = 0;
32
+ data[1] = 0;
33
+ data[2] = 0;
34
+ data[3] = 0;
35
+ data[4] = 0;
36
+ data[5] = 0;
37
+ data[6] = 0;
38
+ data[7] = 0;
39
+ data[8] = 0;
40
+ data[9] = 0;
41
+ data[10] = 0;
42
+ data[11] = 0;
43
+ data[12] = 0;
44
+ data[13] = 0;
45
+ data[14] = 0;
46
+ data[15] = 0;
47
+ }
48
+
49
+ ULID(uint64_t val) {
50
+ // for (int i = 0 ; i < 16 ; i++) {
51
+ // data[15 - i] = static_cast<uint8_t>(val);
52
+ // val >>= 8;
53
+ // }
54
+
55
+ // unrolled loop
56
+ data[15] = static_cast<uint8_t>(val);
57
+
58
+ val >>= 8;
59
+ data[14] = static_cast<uint8_t>(val);
60
+
61
+ val >>= 8;
62
+ data[13] = static_cast<uint8_t>(val);
63
+
64
+ val >>= 8;
65
+ data[12] = static_cast<uint8_t>(val);
66
+
67
+ val >>= 8;
68
+ data[11] = static_cast<uint8_t>(val);
69
+
70
+ val >>= 8;
71
+ data[10] = static_cast<uint8_t>(val);
72
+
73
+ val >>= 8;
74
+ data[9] = static_cast<uint8_t>(val);
75
+
76
+ val >>= 8;
77
+ data[8] = static_cast<uint8_t>(val);
78
+
79
+ data[7] = 0;
80
+ data[6] = 0;
81
+ data[5] = 0;
82
+ data[4] = 0;
83
+ data[3] = 0;
84
+ data[2] = 0;
85
+ data[1] = 0;
86
+ data[0] = 0;
87
+ }
88
+
89
+ ULID(const ULID& other) {
90
+ // for (int i = 0 ; i < 16 ; i++) {
91
+ // data[i] = other.data[i];
92
+ // }
93
+
94
+ // unrolled loop
95
+ data[0] = other.data[0];
96
+ data[1] = other.data[1];
97
+ data[2] = other.data[2];
98
+ data[3] = other.data[3];
99
+ data[4] = other.data[4];
100
+ data[5] = other.data[5];
101
+ data[6] = other.data[6];
102
+ data[7] = other.data[7];
103
+ data[8] = other.data[8];
104
+ data[9] = other.data[9];
105
+ data[10] = other.data[10];
106
+ data[11] = other.data[11];
107
+ data[12] = other.data[12];
108
+ data[13] = other.data[13];
109
+ data[14] = other.data[14];
110
+ data[15] = other.data[15];
111
+ }
112
+
113
+ ULID& operator=(const ULID& other) {
114
+ // for (int i = 0 ; i < 16 ; i++) {
115
+ // data[i] = other.data[i];
116
+ // }
117
+
118
+ // unrolled loop
119
+ data[0] = other.data[0];
120
+ data[1] = other.data[1];
121
+ data[2] = other.data[2];
122
+ data[3] = other.data[3];
123
+ data[4] = other.data[4];
124
+ data[5] = other.data[5];
125
+ data[6] = other.data[6];
126
+ data[7] = other.data[7];
127
+ data[8] = other.data[8];
128
+ data[9] = other.data[9];
129
+ data[10] = other.data[10];
130
+ data[11] = other.data[11];
131
+ data[12] = other.data[12];
132
+ data[13] = other.data[13];
133
+ data[14] = other.data[14];
134
+ data[15] = other.data[15];
135
+
136
+ return *this;
137
+ }
138
+
139
+ ULID(ULID&& other) {
140
+ // for (int i = 0 ; i < 16 ; i++) {
141
+ // data[i] = other.data[i];
142
+ // other.data[i] = 0;
143
+ // }
144
+
145
+ // unrolled loop
146
+ data[0] = other.data[0];
147
+ other.data[0] = 0;
148
+
149
+ data[1] = other.data[1];
150
+ other.data[1] = 0;
151
+
152
+ data[2] = other.data[2];
153
+ other.data[2] = 0;
154
+
155
+ data[3] = other.data[3];
156
+ other.data[3] = 0;
157
+
158
+ data[4] = other.data[4];
159
+ other.data[4] = 0;
160
+
161
+ data[5] = other.data[5];
162
+ other.data[5] = 0;
163
+
164
+ data[6] = other.data[6];
165
+ other.data[6] = 0;
166
+
167
+ data[7] = other.data[7];
168
+ other.data[7] = 0;
169
+
170
+ data[8] = other.data[8];
171
+ other.data[8] = 0;
172
+
173
+ data[9] = other.data[9];
174
+ other.data[9] = 0;
175
+
176
+ data[10] = other.data[10];
177
+ other.data[10] = 0;
178
+
179
+ data[11] = other.data[11];
180
+ other.data[11] = 0;
181
+
182
+ data[12] = other.data[12];
183
+ other.data[12] = 0;
184
+
185
+ data[13] = other.data[13];
186
+ other.data[13] = 0;
187
+
188
+ data[14] = other.data[14];
189
+ other.data[14] = 0;
190
+
191
+ data[15] = other.data[15];
192
+ other.data[15] = 0;
193
+ }
194
+
195
+ ULID& operator=(ULID&& other) {
196
+ // for (int i = 0 ; i < 16 ; i++) {
197
+ // data[i] = other.data[i];
198
+ // other.data[i] = 0;
199
+ // }
200
+
201
+ // unrolled loop
202
+ data[0] = other.data[0];
203
+ other.data[0] = 0;
204
+
205
+ data[1] = other.data[1];
206
+ other.data[1] = 0;
207
+
208
+ data[2] = other.data[2];
209
+ other.data[2] = 0;
210
+
211
+ data[3] = other.data[3];
212
+ other.data[3] = 0;
213
+
214
+ data[4] = other.data[4];
215
+ other.data[4] = 0;
216
+
217
+ data[5] = other.data[5];
218
+ other.data[5] = 0;
219
+
220
+ data[6] = other.data[6];
221
+ other.data[6] = 0;
222
+
223
+ data[7] = other.data[7];
224
+ other.data[7] = 0;
225
+
226
+ data[8] = other.data[8];
227
+ other.data[8] = 0;
228
+
229
+ data[9] = other.data[9];
230
+ other.data[9] = 0;
231
+
232
+ data[10] = other.data[10];
233
+ other.data[10] = 0;
234
+
235
+ data[11] = other.data[11];
236
+ other.data[11] = 0;
237
+
238
+ data[12] = other.data[12];
239
+ other.data[12] = 0;
240
+
241
+ data[13] = other.data[13];
242
+ other.data[13] = 0;
243
+
244
+ data[14] = other.data[14];
245
+ other.data[14] = 0;
246
+
247
+ data[15] = other.data[15];
248
+ other.data[15] = 0;
249
+
250
+ return *this;
251
+ }
252
+ };
253
+
254
+ /**
255
+ * EncodeTimestamp will encode the int64_t timestamp to the passed ulid
256
+ * */
257
+ inline void EncodeTimestamp(int64_t timestamp, ULID& ulid) {
258
+ ulid.data[0] = static_cast<uint8_t>(timestamp >> 40);
259
+ ulid.data[1] = static_cast<uint8_t>(timestamp >> 32);
260
+ ulid.data[2] = static_cast<uint8_t>(timestamp >> 24);
261
+ ulid.data[3] = static_cast<uint8_t>(timestamp >> 16);
262
+ ulid.data[4] = static_cast<uint8_t>(timestamp >> 8);
263
+ ulid.data[5] = static_cast<uint8_t>(timestamp);
264
+ }
265
+
266
+ /**
267
+ * EncodeTime will encode the time point to the passed ulid
268
+ * */
269
+ inline void EncodeTime(std::chrono::time_point<std::chrono::system_clock> time_point, ULID& ulid) {
270
+ auto time_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(time_point);
271
+ int64_t timestamp = time_ms.time_since_epoch().count();
272
+ EncodeTimestamp(timestamp, ulid);
273
+ }
274
+
275
+ /**
276
+ * EncodeTimeNow will encode a ULID using the time obtained using std::time(nullptr)
277
+ * */
278
+ inline void EncodeTimeNow(ULID& ulid) {
279
+ auto time_now = std::chrono::system_clock::from_time_t(time(nullptr));
280
+ EncodeTime(time_now, ulid);
281
+ }
282
+
283
+ /**
284
+ * EncodeTimeSystemClockNow will encode a ULID using the time obtained using
285
+ * std::chrono::system_clock::now() by taking the timestamp in milliseconds.
286
+ * */
287
+ inline void EncodeTimeSystemClockNow(ULID& ulid) {
288
+ EncodeTime(std::chrono::system_clock::now(), ulid);
289
+ }
290
+
291
+ /**
292
+ * EncodeEntropy will encode the last 10 bytes of the passed uint8_t array with
293
+ * the values generated using the passed random number generator.
294
+ * */
295
+ inline void EncodeEntropy(const std::function<uint8_t()>& rng, ULID& ulid) {
296
+ ulid.data[6] = rng();
297
+ ulid.data[7] = rng();
298
+ ulid.data[8] = rng();
299
+ ulid.data[9] = rng();
300
+ ulid.data[10] = rng();
301
+ ulid.data[11] = rng();
302
+ ulid.data[12] = rng();
303
+ ulid.data[13] = rng();
304
+ ulid.data[14] = rng();
305
+ ulid.data[15] = rng();
306
+ }
307
+
308
+ /**
309
+ * EncodeEntropyRand will encode a ulid using std::rand
310
+ *
311
+ * std::rand returns values in [0, RAND_MAX]
312
+ * */
313
+ inline void EncodeEntropyRand(ULID& ulid) {
314
+ ulid.data[6] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
315
+ ulid.data[7] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
316
+ ulid.data[8] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
317
+ ulid.data[9] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
318
+ ulid.data[10] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
319
+ ulid.data[11] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
320
+ ulid.data[12] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
321
+ ulid.data[13] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
322
+ ulid.data[14] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
323
+ ulid.data[15] = static_cast<uint8_t>((std::rand() * 255ull) / RAND_MAX);
324
+ }
325
+
326
+ static std::uniform_int_distribution<rand_t> Distribution_0_255(0, 255);
327
+
328
+ /**
329
+ * EncodeEntropyMt19937 will encode a ulid using std::mt19937
330
+ *
331
+ * It also creates a std::uniform_int_distribution to generate values in [0, 255]
332
+ * */
333
+ inline void EncodeEntropyMt19937(std::mt19937& generator, ULID& ulid) {
334
+ ulid.data[6] = Distribution_0_255(generator);
335
+ ulid.data[7] = Distribution_0_255(generator);
336
+ ulid.data[8] = Distribution_0_255(generator);
337
+ ulid.data[9] = Distribution_0_255(generator);
338
+ ulid.data[10] = Distribution_0_255(generator);
339
+ ulid.data[11] = Distribution_0_255(generator);
340
+ ulid.data[12] = Distribution_0_255(generator);
341
+ ulid.data[13] = Distribution_0_255(generator);
342
+ ulid.data[14] = Distribution_0_255(generator);
343
+ ulid.data[15] = Distribution_0_255(generator);
344
+ }
345
+
346
+ /**
347
+ * Encode will create an encoded ULID with a timestamp and a generator.
348
+ * */
349
+ inline void Encode(std::chrono::time_point<std::chrono::system_clock> timestamp, const std::function<uint8_t()>& rng, ULID& ulid) {
350
+ EncodeTime(timestamp, ulid);
351
+ EncodeEntropy(rng, ulid);
352
+ }
353
+
354
+ /**
355
+ * EncodeNowRand = EncodeTimeNow + EncodeEntropyRand.
356
+ * */
357
+ inline void EncodeNowRand(ULID& ulid) {
358
+ EncodeTimeNow(ulid);
359
+ EncodeEntropyRand(ulid);
360
+ }
361
+
362
+ /**
363
+ * Create will create a ULID with a timestamp and a generator.
364
+ * */
365
+ inline ULID Create(std::chrono::time_point<std::chrono::system_clock> timestamp, const std::function<uint8_t()>& rng) {
366
+ ULID ulid;
367
+ Encode(timestamp, rng, ulid);
368
+ return ulid;
369
+ }
370
+
371
+
372
+ /**
373
+ * CreateNowRand:EncodeNowRand = Create:Encode.
374
+ * */
375
+ inline ULID CreateNowRand() {
376
+ ULID ulid;
377
+ EncodeNowRand(ulid);
378
+ return ulid;
379
+ }
380
+
381
+ /**
382
+ * Crockford's Base32
383
+ * */
384
+ static const char Encoding[33] = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
385
+
386
+ /**
387
+ * MarshalTo will marshal a ULID to the passed character array.
388
+ *
389
+ * Implementation taken directly from oklog/ulid
390
+ * (https://sourcegraph.com/github.com/oklog/ulid@0774f81f6e44af5ce5e91c8d7d76cf710e889ebb/-/blob/ulid.go#L162-190)
391
+ *
392
+ * timestamp:<br>
393
+ * dst[0]: first 3 bits of data[0]<br>
394
+ * dst[1]: last 5 bits of data[0]<br>
395
+ * dst[2]: first 5 bits of data[1]<br>
396
+ * dst[3]: last 3 bits of data[1] + first 2 bits of data[2]<br>
397
+ * dst[4]: bits 3-7 of data[2]<br>
398
+ * dst[5]: last bit of data[2] + first 4 bits of data[3]<br>
399
+ * dst[6]: last 4 bits of data[3] + first bit of data[4]<br>
400
+ * dst[7]: bits 2-6 of data[4]<br>
401
+ * dst[8]: last 2 bits of data[4] + first 3 bits of data[5]<br>
402
+ * dst[9]: last 5 bits of data[5]<br>
403
+ *
404
+ * entropy:
405
+ * follows similarly, except now all components are set to 5 bits.
406
+ * */
407
+ inline void MarshalTo(const ULID& ulid, char dst[26]) {
408
+ // 10 byte timestamp
409
+ dst[0] = Encoding[(ulid.data[0] & 224) >> 5];
410
+ dst[1] = Encoding[ulid.data[0] & 31];
411
+ dst[2] = Encoding[(ulid.data[1] & 248) >> 3];
412
+ dst[3] = Encoding[((ulid.data[1] & 7) << 2) | ((ulid.data[2] & 192) >> 6)];
413
+ dst[4] = Encoding[(ulid.data[2] & 62) >> 1];
414
+ dst[5] = Encoding[((ulid.data[2] & 1) << 4) | ((ulid.data[3] & 240) >> 4)];
415
+ dst[6] = Encoding[((ulid.data[3] & 15) << 1) | ((ulid.data[4] & 128) >> 7)];
416
+ dst[7] = Encoding[(ulid.data[4] & 124) >> 2];
417
+ dst[8] = Encoding[((ulid.data[4] & 3) << 3) | ((ulid.data[5] & 224) >> 5)];
418
+ dst[9] = Encoding[ulid.data[5] & 31];
419
+
420
+ // 16 bytes of entropy
421
+ dst[10] = Encoding[(ulid.data[6] & 248) >> 3];
422
+ dst[11] = Encoding[((ulid.data[6] & 7) << 2) | ((ulid.data[7] & 192) >> 6)];
423
+ dst[12] = Encoding[(ulid.data[7] & 62) >> 1];
424
+ dst[13] = Encoding[((ulid.data[7] & 1) << 4) | ((ulid.data[8] & 240) >> 4)];
425
+ dst[14] = Encoding[((ulid.data[8] & 15) << 1) | ((ulid.data[9] & 128) >> 7)];
426
+ dst[15] = Encoding[(ulid.data[9] & 124) >> 2];
427
+ dst[16] = Encoding[((ulid.data[9] & 3) << 3) | ((ulid.data[10] & 224) >> 5)];
428
+ dst[17] = Encoding[ulid.data[10] & 31];
429
+ dst[18] = Encoding[(ulid.data[11] & 248) >> 3];
430
+ dst[19] = Encoding[((ulid.data[11] & 7) << 2) | ((ulid.data[12] & 192) >> 6)];
431
+ dst[20] = Encoding[(ulid.data[12] & 62) >> 1];
432
+ dst[21] = Encoding[((ulid.data[12] & 1) << 4) | ((ulid.data[13] & 240) >> 4)];
433
+ dst[22] = Encoding[((ulid.data[13] & 15) << 1) | ((ulid.data[14] & 128) >> 7)];
434
+ dst[23] = Encoding[(ulid.data[14] & 124) >> 2];
435
+ dst[24] = Encoding[((ulid.data[14] & 3) << 3) | ((ulid.data[15] & 224) >> 5)];
436
+ dst[25] = Encoding[ulid.data[15] & 31];
437
+ }
438
+
439
+ /**
440
+ * Marshal will marshal a ULID to a std::string.
441
+ * */
442
+ inline std::string Marshal(const ULID& ulid) {
443
+ char data[27];
444
+ data[26] = '\0';
445
+ MarshalTo(ulid, data);
446
+ return std::string(data);
447
+ }
448
+
449
+ /**
450
+ * MarshalBinaryTo will Marshal a ULID to the passed byte array
451
+ * */
452
+ inline void MarshalBinaryTo(const ULID& ulid, uint8_t dst[16]) {
453
+ // timestamp
454
+ dst[0] = ulid.data[0];
455
+ dst[1] = ulid.data[1];
456
+ dst[2] = ulid.data[2];
457
+ dst[3] = ulid.data[3];
458
+ dst[4] = ulid.data[4];
459
+ dst[5] = ulid.data[5];
460
+
461
+ // entropy
462
+ dst[6] = ulid.data[6];
463
+ dst[7] = ulid.data[7];
464
+ dst[8] = ulid.data[8];
465
+ dst[9] = ulid.data[9];
466
+ dst[10] = ulid.data[10];
467
+ dst[11] = ulid.data[11];
468
+ dst[12] = ulid.data[12];
469
+ dst[13] = ulid.data[13];
470
+ dst[14] = ulid.data[14];
471
+ dst[15] = ulid.data[15];
472
+ }
473
+
474
+ /**
475
+ * MarshalBinary will Marshal a ULID to a byte vector.
476
+ * */
477
+ inline std::vector<uint8_t> MarshalBinary(const ULID& ulid) {
478
+ std::vector<uint8_t> dst(16);
479
+ MarshalBinaryTo(ulid, dst.data());
480
+ return dst;
481
+ }
482
+
483
+ /**
484
+ * dec storesdecimal encodings for characters.
485
+ * 0xFF indicates invalid character.
486
+ * 48-57 are digits.
487
+ * 65-90 are capital alphabets.
488
+ * */
489
+ static const uint8_t dec[256] = {
490
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
491
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
492
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
493
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
494
+
495
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
496
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
497
+ /* 0 1 2 3 4 5 6 7 */
498
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
499
+ /* 8 9 */
500
+ 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
501
+
502
+ /* 10(A) 11(B) 12(C) 13(D) 14(E) 15(F) 16(G) */
503
+ 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
504
+ /*17(H) 18(J) 19(K) 20(M) 21(N) */
505
+ 0x11, 0xFF, 0x12, 0x13, 0xFF, 0x14, 0x15, 0xFF,
506
+ /*22(P)23(Q)24(R) 25(S) 26(T) 27(V) 28(W) */
507
+ 0x16, 0x17, 0x18, 0x19, 0x1A, 0xFF, 0x1B, 0x1C,
508
+ /*29(X)30(Y)31(Z) */
509
+ 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
510
+
511
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
512
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
513
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
514
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
515
+
516
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
517
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
518
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
519
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
520
+
521
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
522
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
523
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
524
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
525
+
526
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
527
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
528
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
529
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
530
+
531
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
532
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
533
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
534
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
535
+ };
536
+
537
+ /**
538
+ * UnmarshalFrom will unmarshal a ULID from the passed character array.
539
+ * */
540
+ inline void UnmarshalFrom(const char str[26], ULID& ulid) {
541
+ // timestamp
542
+ ulid.data[0] = (dec[int(str[0])] << 5) | dec[int(str[1])];
543
+ ulid.data[1] = (dec[int(str[2])] << 3) | (dec[int(str[3])] >> 2);
544
+ ulid.data[2] = (dec[int(str[3])] << 6) | (dec[int(str[4])] << 1) | (dec[int(str[5])] >> 4);
545
+ ulid.data[3] = (dec[int(str[5])] << 4) | (dec[int(str[6])] >> 1);
546
+ ulid.data[4] = (dec[int(str[6])] << 7) | (dec[int(str[7])] << 2) | (dec[int(str[8])] >> 3);
547
+ ulid.data[5] = (dec[int(str[8])] << 5) | dec[int(str[9])];
548
+
549
+ // entropy
550
+ ulid.data[6] = (dec[int(str[10])] << 3) | (dec[int(str[11])] >> 2);
551
+ ulid.data[7] = (dec[int(str[11])] << 6) | (dec[int(str[12])] << 1) | (dec[int(str[13])] >> 4);
552
+ ulid.data[8] = (dec[int(str[13])] << 4) | (dec[int(str[14])] >> 1);
553
+ ulid.data[9] = (dec[int(str[14])] << 7) | (dec[int(str[15])] << 2) | (dec[int(str[16])] >> 3);
554
+ ulid.data[10] = (dec[int(str[16])] << 5) | dec[int(str[17])];
555
+ ulid.data[11] = (dec[int(str[18])] << 3) | (dec[int(str[19])] >> 2);
556
+ ulid.data[12] = (dec[int(str[19])] << 6) | (dec[int(str[20])] << 1) | (dec[int(str[21])] >> 4);
557
+ ulid.data[13] = (dec[int(str[21])] << 4) | (dec[int(str[22])] >> 1);
558
+ ulid.data[14] = (dec[int(str[22])] << 7) | (dec[int(str[23])] << 2) | (dec[int(str[24])] >> 3);
559
+ ulid.data[15] = (dec[int(str[24])] << 5) | dec[int(str[25])];
560
+ }
561
+
562
+ /**
563
+ * Unmarshal will create a new ULID by unmarshaling the passed string.
564
+ * */
565
+ inline ULID Unmarshal(const std::string& str) {
566
+ ULID ulid;
567
+ UnmarshalFrom(str.c_str(), ulid);
568
+ return ulid;
569
+ }
570
+
571
+ /**
572
+ * UnmarshalBinaryFrom will unmarshal a ULID from the passed byte array.
573
+ * */
574
+ inline void UnmarshalBinaryFrom(const uint8_t b[16], ULID& ulid) {
575
+ // timestamp
576
+ ulid.data[0] = b[0];
577
+ ulid.data[1] = b[1];
578
+ ulid.data[2] = b[2];
579
+ ulid.data[3] = b[3];
580
+ ulid.data[4] = b[4];
581
+ ulid.data[5] = b[5];
582
+
583
+ // entropy
584
+ ulid.data[6] = b[6];
585
+ ulid.data[7] = b[7];
586
+ ulid.data[8] = b[8];
587
+ ulid.data[9] = b[9];
588
+ ulid.data[10] = b[10];
589
+ ulid.data[11] = b[11];
590
+ ulid.data[12] = b[12];
591
+ ulid.data[13] = b[13];
592
+ ulid.data[14] = b[14];
593
+ ulid.data[15] = b[15];
594
+ }
595
+
596
+ /**
597
+ * Unmarshal will create a new ULID by unmarshaling the passed byte vector.
598
+ * */
599
+ inline ULID UnmarshalBinary(const std::vector<uint8_t>& b) {
600
+ ULID ulid;
601
+ UnmarshalBinaryFrom(b.data(), ulid);
602
+ return ulid;
603
+ }
604
+
605
+ /**
606
+ * CompareULIDs will compare two ULIDs.
607
+ * returns:
608
+ * -1 if ulid1 is Lexicographically before ulid2
609
+ * 1 if ulid1 is Lexicographically after ulid2
610
+ * 0 if ulid1 is same as ulid2
611
+ * */
612
+ inline int CompareULIDs(const ULID& ulid1, const ULID& ulid2) {
613
+ // for (int i = 0 ; i < 16 ; i++) {
614
+ // if (ulid1.data[i] != ulid2.data[i]) {
615
+ // return (ulid1.data[i] < ulid2.data[i]) * -2 + 1;
616
+ // }
617
+ // }
618
+
619
+ // unrolled loop
620
+
621
+ if (ulid1.data[0] != ulid2.data[0]) {
622
+ return (ulid1.data[0] < ulid2.data[0]) * -2 + 1;
623
+ }
624
+
625
+ if (ulid1.data[1] != ulid2.data[1]) {
626
+ return (ulid1.data[1] < ulid2.data[1]) * -2 + 1;
627
+ }
628
+
629
+ if (ulid1.data[2] != ulid2.data[2]) {
630
+ return (ulid1.data[2] < ulid2.data[2]) * -2 + 1;
631
+ }
632
+
633
+ if (ulid1.data[3] != ulid2.data[3]) {
634
+ return (ulid1.data[3] < ulid2.data[3]) * -2 + 1;
635
+ }
636
+
637
+ if (ulid1.data[4] != ulid2.data[4]) {
638
+ return (ulid1.data[4] < ulid2.data[4]) * -2 + 1;
639
+ }
640
+
641
+ if (ulid1.data[5] != ulid2.data[5]) {
642
+ return (ulid1.data[5] < ulid2.data[5]) * -2 + 1;
643
+ }
644
+
645
+ if (ulid1.data[6] != ulid2.data[6]) {
646
+ return (ulid1.data[6] < ulid2.data[6]) * -2 + 1;
647
+ }
648
+
649
+ if (ulid1.data[7] != ulid2.data[7]) {
650
+ return (ulid1.data[7] < ulid2.data[7]) * -2 + 1;
651
+ }
652
+
653
+ if (ulid1.data[8] != ulid2.data[8]) {
654
+ return (ulid1.data[8] < ulid2.data[8]) * -2 + 1;
655
+ }
656
+
657
+ if (ulid1.data[9] != ulid2.data[9]) {
658
+ return (ulid1.data[9] < ulid2.data[9]) * -2 + 1;
659
+ }
660
+
661
+ if (ulid1.data[10] != ulid2.data[10]) {
662
+ return (ulid1.data[10] < ulid2.data[10]) * -2 + 1;
663
+ }
664
+
665
+ if (ulid1.data[11] != ulid2.data[11]) {
666
+ return (ulid1.data[11] < ulid2.data[11]) * -2 + 1;
667
+ }
668
+
669
+ if (ulid1.data[12] != ulid2.data[12]) {
670
+ return (ulid1.data[12] < ulid2.data[12]) * -2 + 1;
671
+ }
672
+
673
+ if (ulid1.data[13] != ulid2.data[13]) {
674
+ return (ulid1.data[13] < ulid2.data[13]) * -2 + 1;
675
+ }
676
+
677
+ if (ulid1.data[14] != ulid2.data[14]) {
678
+ return (ulid1.data[14] < ulid2.data[14]) * -2 + 1;
679
+ }
680
+
681
+ if (ulid1.data[15] != ulid2.data[15]) {
682
+ return (ulid1.data[15] < ulid2.data[15]) * -2 + 1;
683
+ }
684
+
685
+ return 0;
686
+ }
687
+
688
+ /**
689
+ * Time will extract the timestamp used to generate a ULID
690
+ * */
691
+ inline std::chrono::time_point<std::chrono::system_clock> Time(const ULID& ulid) {
692
+ int64_t ans = 0;
693
+
694
+ ans |= ulid.data[0];
695
+
696
+ ans <<= 8;
697
+ ans |= ulid.data[1];
698
+
699
+ ans <<= 8;
700
+ ans |= ulid.data[2];
701
+
702
+ ans <<= 8;
703
+ ans |= ulid.data[3];
704
+
705
+ ans <<= 8;
706
+ ans |= ulid.data[4];
707
+
708
+ ans <<= 8;
709
+ ans |= ulid.data[5];
710
+
711
+ return std::chrono::time_point<std::chrono::system_clock>(std::chrono::milliseconds{ans});
712
+ }
713
+
714
+ }; // namespace ulid
715
+
716
+ #endif // ULID_STRUCT_HH