ulid_fast 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 675e2d1ea39c7608d9bb84a96efeab8acdf7eef82c1dd294c300577db946f72e
4
+ data.tar.gz: a58b60f8ff7177465adb801d194d80e456cbcaa4f7b90ea9efdb7cda2d0666bb
5
+ SHA512:
6
+ metadata.gz: 2aa59ba886b3f1d00ade9e4f3aa5595d41ebf15ccc2ad0a841d4d88dc1e58b5c8954032a3a3403e3dba9f691e8bbdf2b79a130d3b454aec5f1ec34ec9154027e
7
+ data.tar.gz: 6805293e8c88cf1464cdebb3f157c5fc97749b85e53068bf29f4b22b3a370fc4f1bd1ebc92a08e7454f3e771b62acda7bed04b36d0d62ee6c37e96fffd46202c
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('ulid_fast')
@@ -0,0 +1,88 @@
1
+ #include <stdlib.h>
2
+ #include <ruby.h>
3
+ #include <ruby/encoding.h>
4
+ #include "ulid.h"
5
+
6
+
7
+ static VALUE m_ULID;
8
+
9
+
10
+ void
11
+ rb_ulid_generator_mark (void *_self)
12
+ {
13
+ /*
14
+ * This function is not needed becaue there is no malloc() or
15
+ * pointers to other VALUE objects.
16
+ * However, to help others understand how Ruby C extensions
17
+ * work I've left it here.
18
+ *
19
+ struct ulid_generator *ug;
20
+
21
+ TypedData_Get_Struct(self, struct ulid_generator, &UlidGeneratorType, ug);
22
+
23
+ rb_gc_mark(ug->thing);
24
+ rb_gc_mark(ug->other_thing);
25
+ */
26
+ }
27
+
28
+ void
29
+ rb_ulid_generator_free (void *_self)
30
+ {
31
+ // Not needed. We do not malloc() here or in the ulid lib
32
+ // free(_self);
33
+ }
34
+
35
+ static const rb_data_type_t UlidGeneratorType = {
36
+ "UlidGenerator",
37
+ { rb_ulid_generator_mark, rb_ulid_generator_free, NULL }
38
+ };
39
+
40
+ static VALUE
41
+ rb_ulid_generate(VALUE self)
42
+ {
43
+ struct ulid_generator *ug;
44
+
45
+ TypedData_Get_Struct(self, struct ulid_generator, &UlidGeneratorType, ug);
46
+ char ulid[27];
47
+
48
+ ulid_generate(ug, ulid);
49
+
50
+ return rb_utf8_str_new(ulid, 26);
51
+ }
52
+
53
+ static VALUE
54
+ rb_ulid_alloc(VALUE self)
55
+ {
56
+ struct ulid_generator *ug;
57
+ VALUE obj;
58
+ obj = TypedData_Make_Struct(self, struct ulid_generator, &UlidGeneratorType, ug);
59
+
60
+ int ret = ulid_generator_init(ug, ULID_SECURE);
61
+
62
+ if (ret != 0)
63
+ rb_raise(rb_eRuntimeError, "ulid_generator_init failure");
64
+
65
+ return obj;
66
+ }
67
+
68
+ // TODO ..
69
+ /*
70
+ static VALUE
71
+ rb_ulid_each(int argc, VALUE* argv, VALUE self)
72
+ {
73
+ // return rb_funcall(self, rb_intern("to_enum"), 2, rb_intern("generate"), self,);
74
+
75
+ return Qnil;
76
+ }
77
+ */
78
+
79
+ void
80
+ Init_ulid_fast() {
81
+ m_ULID = rb_define_module("ULID");
82
+
83
+ VALUE cls = rb_define_class_under(m_ULID, "Generator", rb_cObject);
84
+ // rb_include_module(m_ULID, rb_mEnumerable);
85
+ rb_define_alloc_func(cls, rb_ulid_alloc);
86
+ rb_define_method(cls, "generate", rb_ulid_generate, 0);
87
+ //rb_define_method(cls, "each", rb_ulid_each, -1);
88
+ }
@@ -0,0 +1,294 @@
1
+ /* ULID generation and parsing library (implementation)
2
+ *
3
+ * This is free and unencumbered software released into the public domain.
4
+ */
5
+ #ifdef _WIN32
6
+ # define WIN32_LEAN_AND_MEAN
7
+ # include <windows.h>
8
+ # pragma comment(lib, "advapi32.lib")
9
+ #elif __linux__
10
+ # define _GNU_SOURCE
11
+ # include <unistd.h>
12
+ # include <sys/time.h>
13
+ # include <sys/syscall.h>
14
+ #else
15
+ # define _POSIX_C_SOURCE 200112L
16
+ # include <sys/time.h>
17
+ #endif
18
+ #include <time.h>
19
+ #include <stdio.h>
20
+ #include <string.h>
21
+ #include "ulid.h"
22
+
23
+ /* Returns unix epoch microseconds.
24
+ */
25
+ static unsigned long long
26
+ platform_utime(int coarse)
27
+ {
28
+ #ifdef _WIN32
29
+ FILETIME ft;
30
+ (void)coarse;
31
+ GetSystemTimeAsFileTime(&ft);
32
+ return ((unsigned long long)ft.dwHighDateTime << 32 |
33
+ (unsigned long long)ft.dwLowDateTime << 0)
34
+ / 10 - 11644473600000000ULL;
35
+ #elif __linux__
36
+ /* CLOCK_REALTIME_COARSE has a resolution of 1ms, which is
37
+ * sufficient for this purpose. It's also _much_ faster.
38
+ */
39
+ struct timespec tv[1];
40
+ clock_gettime(coarse ? CLOCK_REALTIME_COARSE : CLOCK_REALTIME, tv);
41
+ return tv->tv_sec * 1000000ULL + tv->tv_nsec / 1000ULL;
42
+ #else
43
+ struct timespec tv[1];
44
+ (void)coarse;
45
+ clock_gettime(CLOCK_REALTIME, tv);
46
+ return tv->tv_sec * 1000000ULL + tv->tv_nsec / 1000ULL;
47
+ #endif
48
+ }
49
+
50
+ /* Gather entropy from the operating system.
51
+ * Returns 0 on success.
52
+ */
53
+ static int
54
+ platform_entropy(void *buf, int len)
55
+ {
56
+ #if _WIN32
57
+ BOOLEAN NTAPI SystemFunction036(PVOID, ULONG);
58
+ return !SystemFunction036(buf, len);
59
+ #elif __linux__
60
+ return syscall(SYS_getrandom, buf, len, 0) != len;
61
+ #else
62
+ int r = 0;
63
+ FILE *f = fopen("/dev/urandom", "rb");
64
+ if (f) {
65
+ r = fread(buf, len, 1, f);
66
+ fclose(f);
67
+ }
68
+ return !r;
69
+ #endif
70
+ }
71
+
72
+ int
73
+ ulid_generator_init(struct ulid_generator *g, int flags)
74
+ {
75
+ g->last_ts = 0;
76
+ g->flags = flags;
77
+ g->i = g->j = 0;
78
+ for (int i = 0; i < 256; i++)
79
+ g->s[i] = i;
80
+
81
+ /* RC4 is used to fill the random segment of ULIDs. It's tiny,
82
+ * simple, perfectly sufficient for the task (assuming it's seeded
83
+ * properly), and doesn't require fixed-width integers. It's not the
84
+ * fastest option, but it's plenty fast for the task.
85
+ *
86
+ * Besides, when we're in a serious hurry in normal operation (not
87
+ * in "relaxed" mode), we're incrementing the random field much more
88
+ * often than generating fresh random bytes.
89
+ */
90
+
91
+ int initstyle = 1;
92
+ unsigned char key[256] = {0};
93
+ if (!platform_entropy(key, 256)) {
94
+ /* Mix entropy into the RC4 state. */
95
+ for (int i = 0, j = 0; i < 256; i++) {
96
+ j = (j + g->s[i] + key[i]) & 0xff;
97
+ int tmp = g->s[i];
98
+ g->s[i] = g->s[j];
99
+ g->s[j] = tmp;
100
+ }
101
+ initstyle = 0;
102
+ } else if (!(flags & ULID_SECURE)) {
103
+ /* Failed to read entropy from OS, so generate some. */
104
+ unsigned long n = 0;
105
+ unsigned long long now;
106
+ unsigned long long start = platform_utime(0);
107
+ do {
108
+ struct {
109
+ clock_t clk;
110
+ unsigned long long ts;
111
+ long n;
112
+ void *stackgap;
113
+ } noise;
114
+ noise.ts = now = platform_utime(0);
115
+ noise.clk = clock();
116
+ noise.stackgap = &noise;
117
+ noise.n = n;
118
+ unsigned char *k = (unsigned char *)&noise;
119
+ for (int i = 0, j = 0; i < 256; i++) {
120
+ j = (j + g->s[i] + k[i % sizeof(noise)]) & 0xff;
121
+ int tmp = g->s[i];
122
+ g->s[i] = g->s[j];
123
+ g->s[j] = tmp;
124
+ }
125
+ } while (n++ < 1UL << 16 || now - start < 500000ULL);
126
+ }
127
+ return initstyle;
128
+ }
129
+
130
+ void
131
+ ulid_encode(char str[27], const unsigned char ulid[16])
132
+ {
133
+ static const char set[256] = {
134
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
135
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
136
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
137
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a,
138
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
139
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
140
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
141
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a,
142
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
143
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
144
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
145
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a,
146
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
147
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
148
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
149
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a,
150
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
151
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
152
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
153
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a,
154
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
155
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
156
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
157
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a,
158
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
159
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
160
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
161
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a,
162
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
163
+ 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
164
+ 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e, 0x50, 0x51,
165
+ 0x52, 0x53, 0x54, 0x56, 0x57, 0x58, 0x59, 0x5a
166
+ };
167
+ str[ 0] = set[ ulid[ 0] >> 5];
168
+ str[ 1] = set[ ulid[ 0] >> 0];
169
+ str[ 2] = set[ ulid[ 1] >> 3];
170
+ str[ 3] = set[(ulid[ 1] << 2 | ulid[ 2] >> 6) & 0x1f];
171
+ str[ 4] = set[ ulid[ 2] >> 1];
172
+ str[ 5] = set[(ulid[ 2] << 4 | ulid[ 3] >> 4) & 0x1f];
173
+ str[ 6] = set[(ulid[ 3] << 1 | ulid[ 4] >> 7) & 0x1f];
174
+ str[ 7] = set[ ulid[ 4] >> 2];
175
+ str[ 8] = set[(ulid[ 4] << 3 | ulid[ 5] >> 5) & 0x1f];
176
+ str[ 9] = set[ ulid[ 5] >> 0];
177
+ str[10] = set[ ulid[ 6] >> 3];
178
+ str[11] = set[(ulid[ 6] << 2 | ulid[ 7] >> 6) & 0x1f];
179
+ str[12] = set[ ulid[ 7] >> 1];
180
+ str[13] = set[(ulid[ 7] << 4 | ulid[ 8] >> 4) & 0x1f];
181
+ str[14] = set[(ulid[ 8] << 1 | ulid[ 9] >> 7) & 0x1f];
182
+ str[15] = set[ ulid[ 9] >> 2];
183
+ str[16] = set[(ulid[ 9] << 3 | ulid[10] >> 5) & 0x1f];
184
+ str[17] = set[ ulid[10] >> 0];
185
+ str[18] = set[ ulid[11] >> 3];
186
+ str[19] = set[(ulid[11] << 2 | ulid[12] >> 6) & 0x1f];
187
+ str[20] = set[ ulid[12] >> 1];
188
+ str[21] = set[(ulid[12] << 4 | ulid[13] >> 4) & 0x1f];
189
+ str[22] = set[(ulid[13] << 1 | ulid[14] >> 7) & 0x1f];
190
+ str[23] = set[ ulid[14] >> 2];
191
+ str[24] = set[(ulid[14] << 3 | ulid[15] >> 5) & 0x1f];
192
+ str[25] = set[ ulid[15] >> 0];
193
+ str[26] = 0;
194
+ }
195
+
196
+ int
197
+ ulid_decode(unsigned char ulid[16], const char *s)
198
+ {
199
+ static const signed char v[] = {
200
+ -1, -1, -1, -1, -1, -1, -1, -1,
201
+ -1, -1, -1, -1, -1, -1, -1, -1,
202
+ -1, -1, -1, -1, -1, -1, -1, -1,
203
+ -1, -1, -1, -1, -1, -1, -1, -1,
204
+ -1, -1, -1, -1, -1, -1, -1, -1,
205
+ -1, -1, -1, -1, -1, -1, -1, -1,
206
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
207
+ 0x08, 0x09, -1, -1, -1, -1, -1, -1,
208
+ -1, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
209
+ 0x11, 0x01, 0x12, 0x13, 0x01, 0x14, 0x15, 0x00,
210
+ 0x16, 0x17, 0x18, 0x19, 0x1a, -1, 0x1b, 0x1c,
211
+ 0x1d, 0x1e, 0x1f, -1, -1, -1, -1, -1,
212
+ -1, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
213
+ 0x11, 0x01, 0x12, 0x13, 0x01, 0x14, 0x15, 0x00,
214
+ 0x16, 0x17, 0x18, 0x19, 0x1a, -1, 0x1b, 0x1c,
215
+ 0x1d, 0x1e, 0x1f, -1, -1, -1, -1, -1,
216
+ -1, -1, -1, -1, -1, -1, -1, -1,
217
+ -1, -1, -1, -1, -1, -1, -1, -1,
218
+ -1, -1, -1, -1, -1, -1, -1, -1,
219
+ -1, -1, -1, -1, -1, -1, -1, -1,
220
+ -1, -1, -1, -1, -1, -1, -1, -1,
221
+ -1, -1, -1, -1, -1, -1, -1, -1,
222
+ -1, -1, -1, -1, -1, -1, -1, -1,
223
+ -1, -1, -1, -1, -1, -1, -1, -1,
224
+ -1, -1, -1, -1, -1, -1, -1, -1,
225
+ -1, -1, -1, -1, -1, -1, -1, -1,
226
+ -1, -1, -1, -1, -1, -1, -1, -1,
227
+ -1, -1, -1, -1, -1, -1, -1, -1,
228
+ -1, -1, -1, -1, -1, -1, -1, -1,
229
+ -1, -1, -1, -1, -1, -1, -1, -1,
230
+ -1, -1, -1, -1, -1, -1, -1, -1,
231
+ -1, -1, -1, -1, -1, -1, -1, -1
232
+ };
233
+ if (v[(int)s[0]] > 7)
234
+ return 1;
235
+ for (int i = 0; i < 26; i++)
236
+ if (v[(int)s[i]] == -1)
237
+ return 2;
238
+ ulid[ 0] = v[(int)s[ 0]] << 5 | v[(int)s[ 1]] >> 0;
239
+ ulid[ 1] = v[(int)s[ 2]] << 3 | v[(int)s[ 3]] >> 2;
240
+ ulid[ 2] = v[(int)s[ 3]] << 6 | v[(int)s[ 4]] << 1 | v[(int)s[ 5]] >> 4;
241
+ ulid[ 3] = v[(int)s[ 5]] << 4 | v[(int)s[ 6]] >> 1;
242
+ ulid[ 4] = v[(int)s[ 6]] << 7 | v[(int)s[ 7]] << 2 | v[(int)s[ 8]] >> 3;
243
+ ulid[ 5] = v[(int)s[ 8]] << 5 | v[(int)s[ 9]] >> 0;
244
+ ulid[ 6] = v[(int)s[10]] << 3 | v[(int)s[11]] >> 2;
245
+ ulid[ 7] = v[(int)s[11]] << 6 | v[(int)s[12]] << 1 | v[(int)s[13]] >> 4;
246
+ ulid[ 8] = v[(int)s[13]] << 4 | v[(int)s[14]] >> 1;
247
+ ulid[ 9] = v[(int)s[14]] << 7 | v[(int)s[15]] << 2 | v[(int)s[16]] >> 3;
248
+ ulid[10] = v[(int)s[16]] << 5 | v[(int)s[17]] >> 0;
249
+ ulid[11] = v[(int)s[18]] << 3 | v[(int)s[19]] >> 2;
250
+ ulid[12] = v[(int)s[19]] << 6 | v[(int)s[20]] << 1 | v[(int)s[21]] >> 4;
251
+ ulid[13] = v[(int)s[21]] << 4 | v[(int)s[22]] >> 1;
252
+ ulid[14] = v[(int)s[22]] << 7 | v[(int)s[23]] << 2 | v[(int)s[24]] >> 3;
253
+ ulid[15] = v[(int)s[24]] << 5 | v[(int)s[25]] >> 0;
254
+ return 0;
255
+ }
256
+
257
+ void
258
+ ulid_generate(struct ulid_generator *g, char str[27])
259
+ {
260
+ unsigned long long ts = platform_utime(1) / 1000;
261
+
262
+ if (!(g->flags & ULID_RELAXED) && g->last_ts == ts) {
263
+ /* Chance of 80-bit overflow is so small that it's not considered. */
264
+ for (int i = 15; i > 5; i--)
265
+ if (++g->last[i])
266
+ break;
267
+ ulid_encode(str, g->last);
268
+ return;
269
+ }
270
+
271
+ /* Fill out timestamp */
272
+ g->last_ts = ts;
273
+ g->last[0] = ts >> 40;
274
+ g->last[1] = ts >> 32;
275
+ g->last[2] = ts >> 24;
276
+ g->last[3] = ts >> 16;
277
+ g->last[4] = ts >> 8;
278
+ g->last[5] = ts >> 0;
279
+
280
+ /* Fill out random section */
281
+ for (int k = 0; k < 10; k++) {
282
+ g->i = (g->i + 1) & 0xff;
283
+ g->j = (g->j + g->s[g->i]) & 0xff;
284
+ int tmp = g->s[g->i];
285
+ g->s[g->i] = g->s[g->j];
286
+ g->s[g->j] = tmp;
287
+ g->last[6 + k] = g->s[(g->s[g->i] + g->s[g->j]) & 0xff];
288
+ }
289
+ if (g->flags & ULID_PARANOID)
290
+ g->last[6] &= 0x7f;
291
+
292
+ ulid_encode(str, g->last);
293
+ }
294
+
@@ -0,0 +1,59 @@
1
+ /* ULID generation and parsing library (API)
2
+ *
3
+ * This is free and unencumbered software released into the public domain.
4
+ */
5
+ #ifndef ULID_H
6
+ #define ULID_H
7
+
8
+ /* Generator configuration flags */
9
+ #define ULID_RELAXED (1 << 0)
10
+ #define ULID_PARANOID (1 << 1)
11
+ #define ULID_SECURE (1 << 2)
12
+
13
+ struct ulid_generator {
14
+ unsigned char last[16];
15
+ unsigned long long last_ts;
16
+ int flags;
17
+ unsigned char i, j;
18
+ unsigned char s[256];
19
+ };
20
+
21
+ /* Initialize a new ULID generator instance.
22
+ *
23
+ * The ULID_RELAXED flag allows ULIDs generated within the same
24
+ * millisecond to be non-monotonic, e.g. the random section is generated
25
+ * fresh each time.
26
+ *
27
+ * The ULID_PARANOID flag causes the generator to clear the highest bit
28
+ * of the random field, which guarantees that overflow cannot occur.
29
+ * Normally the chance of overflow is non-zero, but negligible. This
30
+ * makes it zero. It doesn't make sense to use this flag in conjunction
31
+ * with ULID_RELAX.
32
+ *
33
+ * The ULID_SECURE flag doesn't fall back on userspace initialization if
34
+ * system entropy could not be gathered. You _must_ check the return
35
+ * value if you use this flag, since it now indicates a hard error.
36
+ *
37
+ * Returns 0 if the generator was successfully initialized from secure
38
+ * system entropy. Returns 1 if this failed and instead derived entropy
39
+ * in userspace (or is uninitialized in the case of ULID_SECURE).
40
+ */
41
+ int ulid_generator_init(struct ulid_generator *, int flags);
42
+
43
+ /* Generate a new ULID.
44
+ * A zero terminating byte is written to the output buffer.
45
+ */
46
+ void ulid_generate(struct ulid_generator *, char [27]);
47
+
48
+ /* Encode a 128-bit binary ULID to its text format.
49
+ * A zero terminating byte is written to the output buffer.
50
+ */
51
+ void ulid_encode(char [27], const unsigned char [16]);
52
+
53
+ /* Decode a text ULID to a 128-bit binary ULID.
54
+ * Returns non-zero if input was invalid.
55
+ */
56
+ int ulid_decode(unsigned char [16], const char *);
57
+
58
+ #endif
59
+
@@ -0,0 +1,3 @@
1
+ module ULID
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ulid_fast
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Cook
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
41
+ description:
42
+ email:
43
+ executables: []
44
+ extensions:
45
+ - ext/ulid_fast/extconf.rb
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ext/ulid_fast/extconf.rb
49
+ - ext/ulid_fast/ulid-fast.c
50
+ - ext/ulid_fast/ulid.c
51
+ - ext/ulid_fast/ulid.h
52
+ - lib/ulid_fast/version.rb
53
+ homepage: https://github.com/jamescook/ulid_fast
54
+ licenses:
55
+ - MIT
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">"
64
+ - !ruby/object:Gem::Version
65
+ version: '2.1'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubygems_version: 3.1.2
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: ULID Ruby C Extension
76
+ test_files: []