ruby-ulid 0.6.1 → 0.7.0
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.
- checksums.yaml +4 -4
- data/README.md +28 -28
- data/lib/ulid/crockford_base32.rb +13 -12
- data/lib/ulid/monotonic_generator.rb +12 -5
- data/lib/ulid/utils.rb +117 -0
- data/lib/ulid/uuid.rb +3 -1
- data/lib/ulid/version.rb +1 -1
- data/lib/ulid.rb +65 -130
- data/sig/ulid.rbs +33 -37
- metadata +3 -3
- data/lib/ulid/ractor_unshareable_constants.rb +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 637c2b95fc9d18a59e1bc6d23a3791bc80362b146c52ff962c407894c29c782e
|
|
4
|
+
data.tar.gz: 74a9e3ea4be5d9a541d4cb6dd012997406ef3cb68a08f7a1a42959f40f7ab4e5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c39c42f8da0aac22356cb26fefb7d23855d118f68148be90c1e253577847b91135f8a04ef1fdca1af59075bd673e61cf2f492f046f30616f7c6b493e28332174
|
|
7
|
+
data.tar.gz: 623f7f9b4d46e46c2a47a143330b3d1c2cf83a033e83c8e68ab3af13e56f1ff5a082b3a15f57efcf4a3180fcc5786e18e94a0221fd03c44343322d641b69e31a
|
data/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# ruby-ulid
|
|
2
2
|
|
|
3
|
-
[](https://github.com/kachick/ruby-ulid/actions/workflows/ci.yml?query=branch%3Amain)
|
|
4
4
|
[](http://badge.fury.io/rb/ruby-ulid)
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
|
-
[ulid/spec](https://github.com/ulid/spec)
|
|
9
|
-
Especially possess all `uniqueness`, `randomness`, `extractable timestamps` and `
|
|
10
|
-
This gem aims to provide the generator, optional monotonicity, parser and other manipulation
|
|
8
|
+
[ulid/spec](https://github.com/ulid/spec) has some useful features.\
|
|
9
|
+
Especially possess all `uniqueness`, `randomness`, `extractable timestamps` and `sortability`.\
|
|
10
|
+
This gem aims to provide the generator, optional monotonicity, parser and other manipulation ways around ULID with included [RBS](https://github.com/ruby/rbs).
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
@@ -49,7 +49,7 @@ Should be installed!
|
|
|
49
49
|
Add this line in your Gemfile.
|
|
50
50
|
|
|
51
51
|
```ruby
|
|
52
|
-
gem('ruby-ulid', '~> 0.
|
|
52
|
+
gem('ruby-ulid', '~> 0.7.0')
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
### How to use
|
|
@@ -58,10 +58,10 @@ gem('ruby-ulid', '~> 0.6.1')
|
|
|
58
58
|
require 'ulid'
|
|
59
59
|
|
|
60
60
|
ULID::VERSION
|
|
61
|
-
# => "0.
|
|
61
|
+
# => "0.7.0"
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
NOTE: This README includes info about development version. If you would see released version's one. [Look at the ref](https://github.com/kachick/ruby-ulid/tree/v0.
|
|
64
|
+
NOTE: This README includes info about development version. If you would see released version's one. [Look at the ref](https://github.com/kachick/ruby-ulid/tree/v0.7.0).
|
|
65
65
|
|
|
66
66
|
### Generator and Parser
|
|
67
67
|
|
|
@@ -99,9 +99,9 @@ ULID.generate(moment: time) #=> ULID(2000-01-01 00:00:00.000 UTC: 00VHNCZB006WQT
|
|
|
99
99
|
ULID.at(time) #=> ULID(2000-01-01 00:00:00.000 UTC: 00VHNCZB002W5BGWWKN76N22H6)
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
Also `ULID.encode` and `ULID.decode_time` can be used to get primitive values for most usecases.
|
|
102
|
+
Also `ULID.encode` and `ULID.decode_time` can be used to get primitive values for most usecases.
|
|
103
103
|
|
|
104
|
-
`ULID.encode` returns [normalized](#variants-of-format) String without ULID object creation
|
|
104
|
+
`ULID.encode` returns [normalized](#variants-of-format) String without ULID object creation.\
|
|
105
105
|
It can take same arguments as `ULID.generate`.
|
|
106
106
|
|
|
107
107
|
```ruby
|
|
@@ -116,13 +116,13 @@ ULID.decode_time('00VHNCZB00SYG7RCEXZC9DA4E1') #=> 2000-01-01 00:00:00 UTC
|
|
|
116
116
|
ULID.decode_time('00VHNCZB00SYG7RCEXZC9DA4E1', in: '+09:00') #=> 2000-01-01 09:00:00 +0900
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
This project does not prioritize the speed. However it actually works faster than others! :zap:
|
|
119
|
+
This project does not prioritize on the speed. However it actually works faster than others! :zap:
|
|
120
120
|
|
|
121
|
-
Snapshot on 0.
|
|
121
|
+
Snapshot on 0.7.0 is below
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
- Generator is 1.6x faster than - [ulid gem](https://github.com/rafaelsales/ulid)
|
|
124
|
+
- Generator is 1.9x faster than - [ulid-ruby gem](https://github.com/abachman/ulid-ruby)
|
|
125
|
+
- Parser is 2.6x faster than - [ulid-ruby gem](https://github.com/abachman/ulid-ruby)
|
|
126
126
|
|
|
127
127
|
You can see further detail at [Benchmark](https://github.com/kachick/ruby-ulid/wiki/Benchmark).
|
|
128
128
|
|
|
@@ -151,7 +151,7 @@ ulids.sort == ulids #=> false
|
|
|
151
151
|
|
|
152
152
|
### How to keep `Sortable` even if in same timestamp
|
|
153
153
|
|
|
154
|
-
If you want to prefer `sortable`, Use `MonotonicGenerator` instead. It is called as [Monotonicity](https://github.com/ulid/spec/tree/d0c7170df4517939e70129b4d6462cc162f2d5bf#monotonicity) on the spec
|
|
154
|
+
If you want to prefer `sortable`, Use `MonotonicGenerator` instead. It is called as [Monotonicity](https://github.com/ulid/spec/tree/d0c7170df4517939e70129b4d6462cc162f2d5bf#monotonicity) on the spec.\
|
|
155
155
|
(Though it starts with new random value when changed the timestamp)
|
|
156
156
|
|
|
157
157
|
```ruby
|
|
@@ -195,7 +195,7 @@ ulids.grep(one_of_the_above)
|
|
|
195
195
|
ulids.grep_v(one_of_the_above)
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
-
When want to filter ULIDs with `Time`, we should consider to handle the precision
|
|
198
|
+
When want to filter ULIDs with `Time`, we should consider to handle the precision.\
|
|
199
199
|
So this gem provides `ULID.range` to generate reasonable `Range[ULID]` from `Range[Time]`
|
|
200
200
|
|
|
201
201
|
```ruby
|
|
@@ -294,7 +294,7 @@ ULID.max(time) #=> ULID(2000-01-01 00:00:00.123 UTC: 00VHNCZB3VZZZZZZZZZZZZZZZZ)
|
|
|
294
294
|
|
|
295
295
|
#### As element in Enumerable
|
|
296
296
|
|
|
297
|
-
`ULID#next` and `ULID#succ` returns next(successor) ULID
|
|
297
|
+
`ULID#next` and `ULID#succ` returns next(successor) ULID.\
|
|
298
298
|
Especially `ULID#succ` makes it possible `Range[ULID]#each`.
|
|
299
299
|
|
|
300
300
|
NOTE: However basically `Range[ULID]#each` should not be used. Incrementing 128 bits IDs are not reasonable operation in most cases.
|
|
@@ -360,15 +360,15 @@ ULID.sample(5, period: ulid1.to_time..ulid2.to_time)
|
|
|
360
360
|
|
|
361
361
|
I'm afraid so, we should consider [Current ULID spec](https://github.com/ulid/spec/tree/d0c7170df4517939e70129b4d6462cc162f2d5bf#universally-unique-lexicographically-sortable-identifier) has `orthographical variants of the format` possibilities.
|
|
362
362
|
|
|
363
|
-
>Case insensitive
|
|
363
|
+
> Case insensitive
|
|
364
364
|
|
|
365
|
-
I can understand it might be considered in actual use-case. So `ULID.parse` accepts upcase and downcase
|
|
365
|
+
I can understand it might be considered in actual use-case. So `ULID.parse` accepts upcase and downcase.\
|
|
366
366
|
However it is a controversial point, discussing in [ulid/spec#3](https://github.com/ulid/spec/issues/3).
|
|
367
367
|
|
|
368
|
-
>Uses Crockford's base32 for better efficiency and readability (5 bits per character)
|
|
368
|
+
> Uses Crockford's base32 for better efficiency and readability (5 bits per character)
|
|
369
369
|
|
|
370
|
-
The original `Crockford's base32` maps `I`, `L` to `1`, `O` to `0
|
|
371
|
-
And accepts freestyle inserting `Hyphens (-)
|
|
370
|
+
The original `Crockford's base32` maps `I`, `L` to `1`, `O` to `0`.\
|
|
371
|
+
And accepts freestyle inserting `Hyphens (-)`.\
|
|
372
372
|
To consider this patterns or not is different in each implementations.
|
|
373
373
|
|
|
374
374
|
I have suggested to clarify `subset of Crockford's base32` in [ulid/spec#57](https://github.com/ulid/spec/pull/57).
|
|
@@ -387,7 +387,7 @@ ULID.parse_variant_format('01G70Y0Y7G-ZLXWDIREXERGSDoD') #=> ULID(2022-07-03 02:
|
|
|
387
387
|
|
|
388
388
|
#### UUIDv4 converter (experimental)
|
|
389
389
|
|
|
390
|
-
`ULID.from_uuidv4` and `ULID#to_uuidv4` is the converter
|
|
390
|
+
`ULID.from_uuidv4` and `ULID#to_uuidv4` is the converter.\
|
|
391
391
|
The imported timestamp is meaningless. So ULID's benefit will lost.
|
|
392
392
|
|
|
393
393
|
```ruby
|
|
@@ -426,11 +426,11 @@ See [wiki page for gem migration](https://github.com/kachick/ruby-ulid/wiki/Gem-
|
|
|
426
426
|
|
|
427
427
|
Try at [examples/rbs_sandbox](https://github.com/kachick/ruby-ulid/tree/main/examples/rbs_sandbox).
|
|
428
428
|
|
|
429
|
-
I have checked the behavior with [ruby/rbs@2.6.0](https://github.com/ruby/rbs) + [soutaro/steep@1.0.1](https://github.com/soutaro/steep) +
|
|
429
|
+
I have checked the behavior with [ruby/rbs@2.6.0](https://github.com/ruby/rbs) + [soutaro/steep@1.0.1](https://github.com/soutaro/steep) + [soutaro/steep-vscode](https://github.com/soutaro/steep-vscode).
|
|
430
430
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
431
|
+
- 
|
|
432
|
+
- 
|
|
433
|
+
- 
|
|
434
434
|
|
|
435
435
|
## References
|
|
436
436
|
|
|
@@ -440,5 +440,5 @@ I have checked the behavior with [ruby/rbs@2.6.0](https://github.com/ruby/rbs) +
|
|
|
440
440
|
|
|
441
441
|
## Note
|
|
442
442
|
|
|
443
|
-
- [UUIDv6, UUIDv7, UUIDv8](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-01.html) is another choice for sortable and randomness ID
|
|
443
|
+
- [UUIDv6, UUIDv7, UUIDv8](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-01.html) is another choice for sortable and randomness ID.\
|
|
444
444
|
However they are stayed in draft state. ref: [ruby-ulid#37](https://github.com/kachick/ruby-ulid/issues/37)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# coding: us-ascii
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
# shareable_constant_value: literal
|
|
4
3
|
|
|
5
4
|
# Copyright (C) 2021 Kenichi Kamiya
|
|
6
5
|
|
|
6
|
+
require_relative('utils')
|
|
7
|
+
|
|
7
8
|
class ULID
|
|
8
9
|
# @see https://www.crockford.com/base32.html
|
|
9
10
|
#
|
|
@@ -68,36 +69,36 @@ class ULID
|
|
|
68
69
|
VARIANT_TR_PATTERN = variant_to_normarized.keys.join.freeze
|
|
69
70
|
NORMALIZED_TR_PATTERN = variant_to_normarized.values.join.freeze
|
|
70
71
|
|
|
72
|
+
Utils.make_sharable_constantans(self)
|
|
73
|
+
|
|
71
74
|
# @note Avoid to depend regex as possible. `tr(string, string)` is almost 2x Faster than `gsub(regex, hash)` in Ruby 3.1
|
|
72
75
|
|
|
73
|
-
# @api private
|
|
74
76
|
# @param [String] string
|
|
75
77
|
# @return [Integer]
|
|
76
78
|
def self.decode(string)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
base32encoded = string.upcase.tr(CROCKFORD_TR_PATTERN, BASE32_TR_PATTERN)
|
|
80
|
+
Integer(base32encoded, 32, exception: true)
|
|
79
81
|
end
|
|
80
82
|
|
|
81
|
-
# @api private
|
|
82
83
|
# @param [Integer] integer
|
|
83
84
|
# @return [String]
|
|
84
85
|
def self.encode(integer)
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
base32encoded = integer.to_s(32)
|
|
87
|
+
from_base32(base32encoded).rjust(ENCODED_LENGTH, '0')
|
|
87
88
|
end
|
|
88
89
|
|
|
89
|
-
# @api private
|
|
90
90
|
# @param [String] string
|
|
91
91
|
# @return [String]
|
|
92
92
|
def self.normalize(string)
|
|
93
93
|
string.delete('-').tr(VARIANT_TR_PATTERN, NORMALIZED_TR_PATTERN)
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
# @
|
|
97
|
-
# @param [String] n32encoded
|
|
96
|
+
# @param [String] base32encoded
|
|
98
97
|
# @return [String]
|
|
99
|
-
def self.
|
|
100
|
-
|
|
98
|
+
def self.from_base32(base32encoded)
|
|
99
|
+
base32encoded.upcase.tr(BASE32_TR_PATTERN, CROCKFORD_TR_PATTERN)
|
|
101
100
|
end
|
|
102
101
|
end
|
|
102
|
+
|
|
103
|
+
private_constant(:CrockfordBase32)
|
|
103
104
|
end
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
# Copyright (C) 2021 Kenichi Kamiya
|
|
6
6
|
|
|
7
|
+
require_relative('errors')
|
|
8
|
+
require_relative('utils')
|
|
9
|
+
|
|
7
10
|
class ULID
|
|
8
11
|
class MonotonicGenerator
|
|
9
12
|
# @note When use https://github.com/ko1/ractor-tvar might realize Ractor based thread safe monotonic generator.
|
|
@@ -11,7 +14,8 @@ class ULID
|
|
|
11
14
|
include(MonitorMixin)
|
|
12
15
|
|
|
13
16
|
# @return [ULID, nil]
|
|
14
|
-
|
|
17
|
+
attr_accessor(:prev)
|
|
18
|
+
private(:prev=)
|
|
15
19
|
|
|
16
20
|
undef_method(:instance_variable_set)
|
|
17
21
|
|
|
@@ -31,7 +35,7 @@ class ULID
|
|
|
31
35
|
# @raise [OverflowError] if the entropy part is larger than the ULID limit in same milliseconds
|
|
32
36
|
# @raise [UnexpectedError] if the generated ULID is an invalid value in monotonicity spec.
|
|
33
37
|
# Basically will not happen. Just means this feature prefers error rather than invalid value.
|
|
34
|
-
def generate(moment:
|
|
38
|
+
def generate(moment: Utils.current_milliseconds)
|
|
35
39
|
synchronize do
|
|
36
40
|
prev_ulid = @prev
|
|
37
41
|
unless prev_ulid
|
|
@@ -40,13 +44,13 @@ class ULID
|
|
|
40
44
|
return ret
|
|
41
45
|
end
|
|
42
46
|
|
|
43
|
-
milliseconds =
|
|
47
|
+
milliseconds = Utils.milliseconds_from_moment(moment)
|
|
44
48
|
|
|
45
49
|
ulid = (
|
|
46
50
|
if prev_ulid.milliseconds < milliseconds
|
|
47
51
|
ULID.generate(moment: milliseconds)
|
|
48
52
|
else
|
|
49
|
-
ULID.
|
|
53
|
+
ULID.generate(moment: prev_ulid.milliseconds, entropy: prev_ulid.entropy.succ)
|
|
50
54
|
end
|
|
51
55
|
)
|
|
52
56
|
|
|
@@ -68,9 +72,12 @@ class ULID
|
|
|
68
72
|
end
|
|
69
73
|
end
|
|
70
74
|
|
|
75
|
+
# Just providing similar api as `ULID.generate` and `ULID.encode` relation. No performance benefit exists in monotonic generator's one.
|
|
76
|
+
#
|
|
77
|
+
# @see https://github.com/kachick/ruby-ulid/pull/220
|
|
71
78
|
# @param [Time, Integer] moment
|
|
72
79
|
# @return [String]
|
|
73
|
-
def encode(moment:
|
|
80
|
+
def encode(moment: Utils.current_milliseconds)
|
|
74
81
|
generate(moment: moment).encode
|
|
75
82
|
end
|
|
76
83
|
|
data/lib/ulid/utils.rb
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# coding: us-ascii
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
# shareable_constant_value: literal
|
|
4
|
+
|
|
5
|
+
# Copyright (C) 2021 Kenichi Kamiya
|
|
6
|
+
|
|
7
|
+
require('securerandom')
|
|
8
|
+
|
|
9
|
+
class ULID
|
|
10
|
+
# @note I don't have confidence for the naming of `Utils`. However some standard libraries have same name.
|
|
11
|
+
# https://github.com/ruby/webrick/blob/14612a7540fdd7373344461851c4bfff64985b3e/lib/webrick/utils.rb#L17
|
|
12
|
+
# https://docs.ruby-lang.org/ja/latest/class/ERB=3a=3aUtil.html
|
|
13
|
+
# https://github.com/ruby/rss/blob/af1c3c9c9630ec0a48abec48ed1ef348ba82aa13/lib/rss/utils.rb#L9
|
|
14
|
+
module Utils
|
|
15
|
+
# @return [Integer]
|
|
16
|
+
def self.current_milliseconds
|
|
17
|
+
milliseconds_from_time(Time.now)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @param [Time] time
|
|
21
|
+
# @return [Integer]
|
|
22
|
+
def self.milliseconds_from_time(time)
|
|
23
|
+
(time.to_r * 1000).to_i
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @param [Time, Integer] moment
|
|
27
|
+
# @return [Integer]
|
|
28
|
+
def self.milliseconds_from_moment(moment)
|
|
29
|
+
case moment
|
|
30
|
+
when Integer
|
|
31
|
+
moment
|
|
32
|
+
when Time
|
|
33
|
+
milliseconds_from_time(moment)
|
|
34
|
+
else
|
|
35
|
+
raise(ArgumentError, '`moment` should be a `Time` or `Integer as milliseconds`')
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @return [Integer]
|
|
40
|
+
def self.reasonable_entropy
|
|
41
|
+
SecureRandom.random_number(MAX_ENTROPY)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @param [Integer] milliseconds
|
|
45
|
+
# @param [Integer] entropy
|
|
46
|
+
# @return [String]
|
|
47
|
+
# @raise [OverflowError] if the given value is larger than the ULID limit
|
|
48
|
+
# @raise [ArgumentError] if the given milliseconds and/or entropy is negative number
|
|
49
|
+
def self.encode_base32(milliseconds:, entropy:)
|
|
50
|
+
raise(ArgumentError, 'milliseconds and entropy should be an `Integer`') unless Integer === milliseconds && Integer === entropy
|
|
51
|
+
raise(OverflowError, "timestamp overflow: given #{milliseconds}, max: #{MAX_MILLISECONDS}") unless milliseconds <= MAX_MILLISECONDS
|
|
52
|
+
raise(OverflowError, "entropy overflow: given #{entropy}, max: #{MAX_ENTROPY}") unless entropy <= MAX_ENTROPY
|
|
53
|
+
raise(ArgumentError, 'milliseconds and entropy should not be negative') if milliseconds.negative? || entropy.negative?
|
|
54
|
+
|
|
55
|
+
base32encoded_timestamp = milliseconds.to_s(32).rjust(TIMESTAMP_ENCODED_LENGTH, '0')
|
|
56
|
+
base32encoded_randomness = entropy.to_s(32).rjust(RANDOMNESS_ENCODED_LENGTH, '0')
|
|
57
|
+
"#{base32encoded_timestamp}#{base32encoded_randomness}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @param [BasicObject] object
|
|
61
|
+
# @return [String]
|
|
62
|
+
def self.safe_get_class_name(object)
|
|
63
|
+
fallback = 'UnknownObject'
|
|
64
|
+
|
|
65
|
+
# This class getter implementation used https://github.com/rspec/rspec-support/blob/4ad8392d0787a66f9c351d9cf6c7618e18b3d0f2/lib/rspec/support.rb#L83-L89 as a reference, thank you!
|
|
66
|
+
# ref: https://twitter.com/_kachick/status/1400064896759304196
|
|
67
|
+
klass = (
|
|
68
|
+
begin
|
|
69
|
+
object.class
|
|
70
|
+
rescue NoMethodError
|
|
71
|
+
# steep can't correctly handle singleton class assign. See https://github.com/soutaro/steep/pull/586 for further detail
|
|
72
|
+
# So this annotation is hack for the type infer.
|
|
73
|
+
# @type var object: BasicObject
|
|
74
|
+
# @type var singleton_class: untyped
|
|
75
|
+
singleton_class = class << object; self; end
|
|
76
|
+
(Class === singleton_class) ? singleton_class.ancestors.detect { |ancestor| !ancestor.equal?(singleton_class) } : fallback
|
|
77
|
+
end
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
begin
|
|
81
|
+
name = String.try_convert(klass.name)
|
|
82
|
+
rescue Exception
|
|
83
|
+
fallback
|
|
84
|
+
else
|
|
85
|
+
name || fallback
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.make_sharable_value(value)
|
|
90
|
+
value.freeze
|
|
91
|
+
if defined?(Ractor)
|
|
92
|
+
case value
|
|
93
|
+
when ULID, Time
|
|
94
|
+
if ractor_can_make_shareable_time?
|
|
95
|
+
Ractor.make_shareable(value)
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
Ractor.make_shareable(value)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @note Call before Module#private_constant
|
|
104
|
+
def self.make_sharable_constantans(mod)
|
|
105
|
+
mod.constants.each do |const_name|
|
|
106
|
+
value = mod.const_get(const_name)
|
|
107
|
+
make_sharable_value(value)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.ractor_can_make_shareable_time?
|
|
112
|
+
RUBY_VERSION >= '3.1'
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
private_constant(:Utils)
|
|
117
|
+
end
|
data/lib/ulid/uuid.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# coding: us-ascii
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
# shareable_constant_value: literal
|
|
4
3
|
|
|
5
4
|
# Copyright (C) 2021 Kenichi Kamiya
|
|
6
5
|
|
|
6
|
+
require_relative('errors')
|
|
7
|
+
|
|
7
8
|
# Extracted features around UUID from some reasons
|
|
8
9
|
# ref:
|
|
9
10
|
# * https://github.com/kachick/ruby-ulid/issues/105
|
|
@@ -11,6 +12,7 @@
|
|
|
11
12
|
class ULID
|
|
12
13
|
# Imported from https://stackoverflow.com/a/38191104/1212807, thank you!
|
|
13
14
|
UUIDV4_PATTERN = /\A[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}\z/i.freeze
|
|
15
|
+
Utils.make_sharable_value(UUIDV4_PATTERN)
|
|
14
16
|
private_constant(:UUIDV4_PATTERN)
|
|
15
17
|
|
|
16
18
|
# @param [String, #to_str] uuid
|
data/lib/ulid/version.rb
CHANGED
data/lib/ulid.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# coding: us-ascii
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
# shareable_constant_value: experimental_everything
|
|
4
3
|
|
|
5
4
|
# Copyright (C) 2021 Kenichi Kamiya
|
|
6
5
|
|
|
@@ -9,6 +8,7 @@ require('securerandom')
|
|
|
9
8
|
require_relative('ulid/version')
|
|
10
9
|
require_relative('ulid/errors')
|
|
11
10
|
require_relative('ulid/crockford_base32')
|
|
11
|
+
require_relative('ulid/utils')
|
|
12
12
|
require_relative('ulid/monotonic_generator')
|
|
13
13
|
|
|
14
14
|
# @see https://github.com/ulid/spec
|
|
@@ -46,13 +46,36 @@ class ULID
|
|
|
46
46
|
# @see https://github.com/ruby/ruby/blob/744d17ff6c33b09334508e8110007ea2a82252f5/time.c#L4026-L4078
|
|
47
47
|
TIME_FORMAT_IN_INSPECT = '%Y-%m-%d %H:%M:%S.%3N %Z'
|
|
48
48
|
|
|
49
|
+
RANDOM_INTEGER_GENERATOR = -> {
|
|
50
|
+
SecureRandom.random_number(MAX_INTEGER)
|
|
51
|
+
}.freeze
|
|
52
|
+
|
|
53
|
+
Utils.make_sharable_constantans(self)
|
|
54
|
+
|
|
55
|
+
private_constant(
|
|
56
|
+
:PATTERN_WITH_CROCKFORD_BASE32_SUBSET,
|
|
57
|
+
:STRICT_PATTERN_WITH_CROCKFORD_BASE32_SUBSET,
|
|
58
|
+
:SCANNING_PATTERN,
|
|
59
|
+
:TIME_FORMAT_IN_INSPECT,
|
|
60
|
+
:RANDOM_INTEGER_GENERATOR
|
|
61
|
+
)
|
|
62
|
+
|
|
49
63
|
private_class_method(:new)
|
|
50
64
|
|
|
51
65
|
# @param [Integer, Time] moment
|
|
52
66
|
# @param [Integer] entropy
|
|
53
67
|
# @return [ULID]
|
|
54
|
-
|
|
55
|
-
|
|
68
|
+
# @raise [OverflowError] if the given value is larger than the ULID limit
|
|
69
|
+
# @raise [ArgumentError] if the given milliseconds and/or entropy is negative number
|
|
70
|
+
def self.generate(moment: Utils.current_milliseconds, entropy: Utils.reasonable_entropy)
|
|
71
|
+
milliseconds = Utils.milliseconds_from_moment(moment)
|
|
72
|
+
base32_encoded = Utils.encode_base32(milliseconds: milliseconds, entropy: entropy)
|
|
73
|
+
new(
|
|
74
|
+
milliseconds: milliseconds,
|
|
75
|
+
entropy: entropy,
|
|
76
|
+
integer: base32_encoded.to_i(32),
|
|
77
|
+
encoded: CrockfordBase32.from_base32(base32_encoded).freeze
|
|
78
|
+
)
|
|
56
79
|
end
|
|
57
80
|
|
|
58
81
|
# Almost same as [.generate] except directly returning String without needless object creation
|
|
@@ -60,9 +83,9 @@ class ULID
|
|
|
60
83
|
# @param [Integer, Time] moment
|
|
61
84
|
# @param [Integer] entropy
|
|
62
85
|
# @return [String]
|
|
63
|
-
def self.encode(moment: current_milliseconds, entropy: reasonable_entropy)
|
|
64
|
-
|
|
65
|
-
CrockfordBase32.
|
|
86
|
+
def self.encode(moment: Utils.current_milliseconds, entropy: Utils.reasonable_entropy)
|
|
87
|
+
base32_encoded = Utils.encode_base32(milliseconds: Utils.milliseconds_from_moment(moment), entropy: entropy)
|
|
88
|
+
CrockfordBase32.from_base32(base32_encoded)
|
|
66
89
|
end
|
|
67
90
|
|
|
68
91
|
# Short hand of `ULID.generate(moment: time)`
|
|
@@ -71,7 +94,7 @@ class ULID
|
|
|
71
94
|
def self.at(time)
|
|
72
95
|
raise(ArgumentError, 'ULID.at takes only `Time` instance') unless Time === time
|
|
73
96
|
|
|
74
|
-
|
|
97
|
+
generate(moment: time)
|
|
75
98
|
end
|
|
76
99
|
|
|
77
100
|
# @param [Time, Integer] moment
|
|
@@ -86,10 +109,6 @@ class ULID
|
|
|
86
109
|
MAX_MILLISECONDS.equal?(moment) ? MAX : generate(moment: moment, entropy: MAX_ENTROPY)
|
|
87
110
|
end
|
|
88
111
|
|
|
89
|
-
RANDOM_INTEGER_GENERATOR = -> {
|
|
90
|
-
SecureRandom.random_number(MAX_INTEGER)
|
|
91
|
-
}.freeze
|
|
92
|
-
|
|
93
112
|
# @param [Range<Time>, Range<nil>, Range[ULID], nil] period
|
|
94
113
|
# @overload sample(number, period: nil)
|
|
95
114
|
# @param [Integer] number
|
|
@@ -162,20 +181,20 @@ class ULID
|
|
|
162
181
|
raise(OverflowError, "integer overflow: given #{integer}, max: #{MAX_INTEGER}") unless integer <= MAX_INTEGER
|
|
163
182
|
raise(ArgumentError, "integer should not be negative: given: #{integer}") if integer.negative?
|
|
164
183
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
184
|
+
base32encoded = integer.to_s(32).rjust(ENCODED_LENGTH, '0')
|
|
185
|
+
base32encoded_timestamp = base32encoded.slice(0, TIMESTAMP_ENCODED_LENGTH)
|
|
186
|
+
base32encoded_randomness = base32encoded.slice(TIMESTAMP_ENCODED_LENGTH, RANDOMNESS_ENCODED_LENGTH)
|
|
168
187
|
|
|
169
|
-
raise(UnexpectedError) unless
|
|
188
|
+
raise(UnexpectedError) unless base32encoded_timestamp && base32encoded_randomness
|
|
170
189
|
|
|
171
|
-
milliseconds =
|
|
172
|
-
entropy =
|
|
190
|
+
milliseconds = base32encoded_timestamp.to_i(32)
|
|
191
|
+
entropy = base32encoded_randomness.to_i(32)
|
|
173
192
|
|
|
174
193
|
new(
|
|
175
194
|
milliseconds: milliseconds,
|
|
176
195
|
entropy: entropy,
|
|
177
196
|
integer: integer,
|
|
178
|
-
encoded: CrockfordBase32.
|
|
197
|
+
encoded: CrockfordBase32.from_base32(base32encoded).freeze
|
|
179
198
|
)
|
|
180
199
|
end
|
|
181
200
|
|
|
@@ -232,49 +251,6 @@ class ULID
|
|
|
232
251
|
time.floor(3)
|
|
233
252
|
end
|
|
234
253
|
|
|
235
|
-
# @api private
|
|
236
|
-
# @return [Integer]
|
|
237
|
-
def self.current_milliseconds
|
|
238
|
-
milliseconds_from_time(Time.now)
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
# @api private
|
|
242
|
-
# @param [Time] time
|
|
243
|
-
# @return [Integer]
|
|
244
|
-
private_class_method def self.milliseconds_from_time(time)
|
|
245
|
-
(time.to_r * 1000).to_i
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
# @api private
|
|
249
|
-
# @param [Time, Integer] moment
|
|
250
|
-
# @return [Integer]
|
|
251
|
-
def self.milliseconds_from_moment(moment)
|
|
252
|
-
case moment
|
|
253
|
-
when Integer
|
|
254
|
-
moment
|
|
255
|
-
when Time
|
|
256
|
-
milliseconds_from_time(moment)
|
|
257
|
-
else
|
|
258
|
-
raise(ArgumentError, '`moment` should be a `Time` or `Integer as milliseconds`')
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
|
|
262
|
-
# @return [Integer]
|
|
263
|
-
private_class_method def self.reasonable_entropy
|
|
264
|
-
SecureRandom.random_number(MAX_ENTROPY)
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
private_class_method def self.encode_n32(milliseconds:, entropy:)
|
|
268
|
-
raise(ArgumentError, 'milliseconds and entropy should be an `Integer`') unless Integer === milliseconds && Integer === entropy
|
|
269
|
-
raise(OverflowError, "timestamp overflow: given #{milliseconds}, max: #{MAX_MILLISECONDS}") unless milliseconds <= MAX_MILLISECONDS
|
|
270
|
-
raise(OverflowError, "entropy overflow: given #{entropy}, max: #{MAX_ENTROPY}") unless entropy <= MAX_ENTROPY
|
|
271
|
-
raise(ArgumentError, 'milliseconds and entropy should not be negative') if milliseconds.negative? || entropy.negative?
|
|
272
|
-
|
|
273
|
-
n32encoded_timestamp = milliseconds.to_s(32).rjust(TIMESTAMP_ENCODED_LENGTH, '0')
|
|
274
|
-
n32encoded_randomness = entropy.to_s(32).rjust(RANDOMNESS_ENCODED_LENGTH, '0')
|
|
275
|
-
"#{n32encoded_timestamp}#{n32encoded_randomness}"
|
|
276
|
-
end
|
|
277
|
-
|
|
278
254
|
# @param [String, #to_str] string
|
|
279
255
|
# @return [ULID]
|
|
280
256
|
# @raise [ParserError] if the given format is not correct for ULID specs
|
|
@@ -303,6 +279,7 @@ class ULID
|
|
|
303
279
|
# Almost same as `ULID.parse(string).to_time` except directly returning Time instance without needless object creation
|
|
304
280
|
#
|
|
305
281
|
# @param [String, #to_str] string
|
|
282
|
+
# @param [String, Integer, nil] in
|
|
306
283
|
# @return [Time]
|
|
307
284
|
# @raise [ParserError] if the given format is not correct for ULID specs
|
|
308
285
|
def self.decode_time(string, in: 'UTC')
|
|
@@ -375,74 +352,15 @@ class ULID
|
|
|
375
352
|
if ULID === converted
|
|
376
353
|
converted
|
|
377
354
|
else
|
|
378
|
-
object_class_name = safe_get_class_name(object)
|
|
379
|
-
converted_class_name = safe_get_class_name(converted)
|
|
355
|
+
object_class_name = Utils.safe_get_class_name(object)
|
|
356
|
+
converted_class_name = Utils.safe_get_class_name(converted)
|
|
380
357
|
raise(TypeError, "can't convert #{object_class_name} to ULID (#{object_class_name}#to_ulid gives #{converted_class_name})")
|
|
381
358
|
end
|
|
382
359
|
end
|
|
383
360
|
end
|
|
384
361
|
|
|
385
|
-
# @param [BasicObject] object
|
|
386
|
-
# @return [String]
|
|
387
|
-
private_class_method def self.safe_get_class_name(object)
|
|
388
|
-
fallback = 'UnknownObject'
|
|
389
|
-
|
|
390
|
-
# This class getter implementation used https://github.com/rspec/rspec-support/blob/4ad8392d0787a66f9c351d9cf6c7618e18b3d0f2/lib/rspec/support.rb#L83-L89 as a reference, thank you!
|
|
391
|
-
# ref: https://twitter.com/_kachick/status/1400064896759304196
|
|
392
|
-
klass = (
|
|
393
|
-
begin
|
|
394
|
-
object.class
|
|
395
|
-
rescue NoMethodError
|
|
396
|
-
# steep can't correctly handle singleton class assign. See https://github.com/soutaro/steep/pull/586 for further detail
|
|
397
|
-
# So this annotation is hack for the type infer.
|
|
398
|
-
# @type var object: BasicObject
|
|
399
|
-
# @type var singleton_class: untyped
|
|
400
|
-
singleton_class = class << object; self; end
|
|
401
|
-
(Class === singleton_class) ? singleton_class.ancestors.detect { |ancestor| !ancestor.equal?(singleton_class) } : fallback
|
|
402
|
-
end
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
begin
|
|
406
|
-
name = String.try_convert(klass.name)
|
|
407
|
-
rescue Exception
|
|
408
|
-
fallback
|
|
409
|
-
else
|
|
410
|
-
name || fallback
|
|
411
|
-
end
|
|
412
|
-
end
|
|
413
|
-
|
|
414
|
-
# @api private
|
|
415
|
-
# @param [Integer] milliseconds
|
|
416
|
-
# @param [Integer] entropy
|
|
417
|
-
# @return [ULID]
|
|
418
|
-
# @raise [OverflowError] if the given value is larger than the ULID limit
|
|
419
|
-
# @raise [ArgumentError] if the given milliseconds and/or entropy is negative number
|
|
420
|
-
def self.from_milliseconds_and_entropy(milliseconds:, entropy:)
|
|
421
|
-
n32_encoded = encode_n32(milliseconds: milliseconds, entropy: entropy)
|
|
422
|
-
new(
|
|
423
|
-
milliseconds: milliseconds,
|
|
424
|
-
entropy: entropy,
|
|
425
|
-
integer: n32_encoded.to_i(32),
|
|
426
|
-
encoded: CrockfordBase32.from_n32(n32_encoded).upcase.freeze
|
|
427
|
-
)
|
|
428
|
-
end
|
|
429
|
-
|
|
430
362
|
attr_reader(:milliseconds, :entropy)
|
|
431
363
|
|
|
432
|
-
# @api private
|
|
433
|
-
# @param [Integer] milliseconds
|
|
434
|
-
# @param [Integer] entropy
|
|
435
|
-
# @param [Integer] integer
|
|
436
|
-
# @param [String] encoded
|
|
437
|
-
# @return [void]
|
|
438
|
-
def initialize(milliseconds:, entropy:, integer:, encoded:)
|
|
439
|
-
# All arguments check should be done with each constructors, not here
|
|
440
|
-
@integer = integer
|
|
441
|
-
@encoded = encoded
|
|
442
|
-
@milliseconds = milliseconds
|
|
443
|
-
@entropy = entropy
|
|
444
|
-
end
|
|
445
|
-
|
|
446
364
|
# @return [String]
|
|
447
365
|
def encode
|
|
448
366
|
@encoded
|
|
@@ -578,18 +496,21 @@ class ULID
|
|
|
578
496
|
super
|
|
579
497
|
end
|
|
580
498
|
|
|
581
|
-
# @api private
|
|
582
499
|
# @return [Integer]
|
|
583
500
|
def marshal_dump
|
|
584
501
|
@integer
|
|
585
502
|
end
|
|
586
503
|
|
|
587
|
-
# @api private
|
|
588
504
|
# @param [Integer] integer
|
|
589
505
|
# @return [void]
|
|
590
506
|
def marshal_load(integer)
|
|
591
507
|
unmarshaled = ULID.from_integer(integer)
|
|
592
|
-
initialize(
|
|
508
|
+
initialize(
|
|
509
|
+
integer: unmarshaled.to_i,
|
|
510
|
+
milliseconds: unmarshaled.milliseconds,
|
|
511
|
+
entropy: unmarshaled.entropy,
|
|
512
|
+
encoded: unmarshaled.to_s
|
|
513
|
+
)
|
|
593
514
|
end
|
|
594
515
|
|
|
595
516
|
# @return [self]
|
|
@@ -611,17 +532,31 @@ class ULID
|
|
|
611
532
|
|
|
612
533
|
private
|
|
613
534
|
|
|
535
|
+
# @param [Integer] milliseconds
|
|
536
|
+
# @param [Integer] entropy
|
|
537
|
+
# @param [Integer] integer
|
|
538
|
+
# @param [String] encoded
|
|
539
|
+
# @return [void]
|
|
540
|
+
def initialize(milliseconds:, entropy:, integer:, encoded:)
|
|
541
|
+
# All arguments check should be done with each constructors, not here
|
|
542
|
+
@integer = integer
|
|
543
|
+
@encoded = encoded
|
|
544
|
+
@milliseconds = milliseconds
|
|
545
|
+
@entropy = entropy
|
|
546
|
+
end
|
|
547
|
+
|
|
614
548
|
# @return [void]
|
|
615
549
|
def cache_all_instance_variables
|
|
616
550
|
inspect
|
|
617
551
|
timestamp
|
|
618
552
|
randomness
|
|
619
553
|
end
|
|
620
|
-
end
|
|
621
554
|
|
|
622
|
-
|
|
555
|
+
MIN = parse('00000000000000000000000000').freeze
|
|
556
|
+
MAX = parse('7ZZZZZZZZZZZZZZZZZZZZZZZZZ').freeze
|
|
623
557
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
558
|
+
Utils.make_sharable_value(MIN)
|
|
559
|
+
Utils.make_sharable_value(MAX)
|
|
560
|
+
|
|
561
|
+
private_constant(:MIN, :MAX)
|
|
627
562
|
end
|
data/sig/ulid.rbs
CHANGED
|
@@ -19,8 +19,8 @@ class ULID < Object
|
|
|
19
19
|
MAX: ULID
|
|
20
20
|
include Comparable
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
type moment = Time |
|
|
22
|
+
type milliseconds = Integer
|
|
23
|
+
type moment = Time | milliseconds
|
|
24
24
|
|
|
25
25
|
class Error < StandardError
|
|
26
26
|
end
|
|
@@ -34,27 +34,42 @@ class ULID < Object
|
|
|
34
34
|
class UnexpectedError < Error
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
module
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
# Private module
|
|
38
|
+
module Utils
|
|
39
|
+
def self.encode_base32: (milliseconds: milliseconds, entropy: Integer) -> String
|
|
40
|
+
|
|
41
|
+
def self.current_milliseconds: -> milliseconds
|
|
42
|
+
|
|
43
|
+
def self.milliseconds_from_moment: (moment moment) -> milliseconds
|
|
44
|
+
|
|
45
|
+
def self.reasonable_entropy: -> Integer
|
|
46
|
+
|
|
47
|
+
def self.milliseconds_from_time: (Time time) -> milliseconds
|
|
48
|
+
|
|
49
|
+
def self.safe_get_class_name: (untyped object) -> String
|
|
40
50
|
|
|
51
|
+
def self.make_sharable_value: (untyped object) -> void
|
|
52
|
+
|
|
53
|
+
def self.make_sharable_constantans: (Module) -> void
|
|
54
|
+
|
|
55
|
+
def self.ractor_can_make_shareable_time?: -> bool
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Private module
|
|
59
|
+
module CrockfordBase32
|
|
41
60
|
ENCODING_STRING: String
|
|
42
61
|
CROCKFORD_TR_PATTERN: String
|
|
43
62
|
BASE32_TR_PATTERN: String
|
|
44
63
|
VARIANT_TR_PATTERN: String
|
|
45
64
|
NORMALIZED_TR_PATTERN: String
|
|
46
65
|
|
|
47
|
-
# A private API. Should not be used in your code.
|
|
48
66
|
def self.encode: (Integer integer) -> String
|
|
49
67
|
|
|
50
|
-
# A private API. Should not be used in your code.
|
|
51
68
|
def self.decode: (String string) -> Integer
|
|
52
69
|
|
|
53
|
-
# A private API. Should not be used in your code.
|
|
54
70
|
def self.normalize: (String string) -> String
|
|
55
71
|
|
|
56
|
-
|
|
57
|
-
def self.from_n32: (String n32encoded) -> String
|
|
72
|
+
def self.from_base32: (String base32encoded) -> String
|
|
58
73
|
end
|
|
59
74
|
|
|
60
75
|
class MonotonicGenerator
|
|
@@ -72,9 +87,6 @@ class ULID < Object
|
|
|
72
87
|
# ```
|
|
73
88
|
attr_reader prev: ULID | nil
|
|
74
89
|
|
|
75
|
-
# A private API. Should not be used in your code.
|
|
76
|
-
def initialize: -> void
|
|
77
|
-
|
|
78
90
|
# See [How to keep `Sortable` even if in same timestamp](https://github.com/kachick/ruby-ulid#how-to-keep-sortable-even-if-in-same-timestamp)
|
|
79
91
|
# The `Thread-safety` is implemented with [Monitor](https://bugs.ruby-lang.org/issues/16255)
|
|
80
92
|
def generate: (?moment: moment) -> ULID
|
|
@@ -95,6 +107,12 @@ class ULID < Object
|
|
|
95
107
|
def inspect: -> String
|
|
96
108
|
alias to_s inspect
|
|
97
109
|
def freeze: -> void
|
|
110
|
+
|
|
111
|
+
private
|
|
112
|
+
|
|
113
|
+
def initialize: -> void
|
|
114
|
+
|
|
115
|
+
def prev=: (ULID?) -> void
|
|
98
116
|
end
|
|
99
117
|
|
|
100
118
|
interface _ToULID
|
|
@@ -156,9 +174,6 @@ class ULID < Object
|
|
|
156
174
|
#
|
|
157
175
|
def self.encode: (?moment: moment, ?entropy: Integer) -> String
|
|
158
176
|
|
|
159
|
-
# A private API. Should not be used in your code.
|
|
160
|
-
def self.encode_n32: (milliseconds: Integer, entropy: Integer) -> String
|
|
161
|
-
|
|
162
177
|
# Shorthand of `ULID.generate(moment: Time)`
|
|
163
178
|
# See also [ULID.generate](https://kachick.github.io/ruby-ulid/ULID.html#generate-class_method)
|
|
164
179
|
#
|
|
@@ -173,12 +188,6 @@ class ULID < Object
|
|
|
173
188
|
# ```
|
|
174
189
|
def self.at: (Time time) -> ULID
|
|
175
190
|
|
|
176
|
-
# A private API. Should not be used in your code.
|
|
177
|
-
def self.current_milliseconds: -> Integer
|
|
178
|
-
|
|
179
|
-
# A private API. Should not be used in your code.
|
|
180
|
-
def self.milliseconds_from_moment: (moment moment) -> Integer
|
|
181
|
-
|
|
182
191
|
# `ULID` can be element of the `Range`. If you generated the IDs in monotonic generator, ID based filtering is easy and reliable
|
|
183
192
|
#
|
|
184
193
|
# ```ruby
|
|
@@ -440,7 +449,7 @@ class ULID < Object
|
|
|
440
449
|
# ```
|
|
441
450
|
def self.scan: (_ToStr string) -> Enumerator[self, singleton(ULID)]
|
|
442
451
|
| (_ToStr string) { (ULID ulid) -> void } -> singleton(ULID)
|
|
443
|
-
|
|
452
|
+
|
|
444
453
|
def self.try_convert: (_ToULID) -> ULID
|
|
445
454
|
| (untyped) -> nil
|
|
446
455
|
|
|
@@ -591,10 +600,8 @@ class ULID < Object
|
|
|
591
600
|
def pred: -> ULID?
|
|
592
601
|
def freeze: -> self
|
|
593
602
|
|
|
594
|
-
# A private API. Should not be used in your code.
|
|
595
603
|
def marshal_dump: -> Integer
|
|
596
604
|
|
|
597
|
-
# A private API. Should not be used in your code.
|
|
598
605
|
def marshal_load: (Integer integer) -> void
|
|
599
606
|
|
|
600
607
|
# Returns `self`
|
|
@@ -609,18 +616,7 @@ class ULID < Object
|
|
|
609
616
|
|
|
610
617
|
private
|
|
611
618
|
|
|
612
|
-
|
|
613
|
-
def self.reasonable_entropy: -> Integer
|
|
614
|
-
|
|
615
|
-
# A private API. Should not be used in your code.
|
|
616
|
-
def self.milliseconds_from_time: (Time time) -> Integer
|
|
617
|
-
|
|
618
|
-
# A private API. Should not be used in your code.
|
|
619
|
-
def self.safe_get_class_name: (untyped object) -> String
|
|
620
|
-
|
|
621
|
-
# A private API. Should not be used in your code.
|
|
622
|
-
def initialize: (milliseconds: Integer, entropy: Integer, integer: Integer, encoded: String) -> void
|
|
619
|
+
def initialize: (milliseconds: milliseconds, entropy: Integer, integer: Integer, encoded: String) -> void
|
|
623
620
|
|
|
624
|
-
# A private API. Should not be used in your code.
|
|
625
621
|
def cache_all_instance_variables: -> void
|
|
626
622
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-ulid
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kenichi Kamiya
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-08-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: " generator, optional monotonicity, parser and tools for ULID (RBS
|
|
14
14
|
included)\n"
|
|
@@ -25,7 +25,7 @@ files:
|
|
|
25
25
|
- lib/ulid/crockford_base32.rb
|
|
26
26
|
- lib/ulid/errors.rb
|
|
27
27
|
- lib/ulid/monotonic_generator.rb
|
|
28
|
-
- lib/ulid/
|
|
28
|
+
- lib/ulid/utils.rb
|
|
29
29
|
- lib/ulid/uuid.rb
|
|
30
30
|
- lib/ulid/version.rb
|
|
31
31
|
- sig/ulid.rbs
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# coding: us-ascii
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
class ULID
|
|
5
|
-
min = parse('00000000000000000000000000').freeze
|
|
6
|
-
max = parse('7ZZZZZZZZZZZZZZZZZZZZZZZZZ').freeze
|
|
7
|
-
|
|
8
|
-
ractor_can_make_shareable_time = RUBY_VERSION >= '3.1'
|
|
9
|
-
|
|
10
|
-
MIN = ractor_can_make_shareable_time ? Ractor.make_shareable(min) : min
|
|
11
|
-
MAX = ractor_can_make_shareable_time ? Ractor.make_shareable(max) : max
|
|
12
|
-
end
|