ulid-transform 1.2.0__cp311-cp311-musllinux_1_2_aarch64.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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