ruby-ulid 0.0.19 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 646d2a4b433ffbe28d4801483d3f1c43cfb5839bf5f80e759447304a1c8dad52
4
- data.tar.gz: 1e4ddc37266eb09f3635ba5509e66e6ff93e15fad3e6574fb3b50e8ad9322b10
3
+ metadata.gz: f0aff39d0f8044f373d8dcdea149f26501e0118dfc0876f060b1b757a4d2a49e
4
+ data.tar.gz: 02df0ea7a5fe5f8dabd1179988cfe4c2574debf3ad7200d11445eef932dd7443
5
5
  SHA512:
6
- metadata.gz: 9a564dbad8c3c88b729353826c599e618cd8963806759ce8a6bf041a95aef60044c8f75873560129bcef7550eec226c3bf04bcfec339c4b07fb72c3372342811
7
- data.tar.gz: 187c475f9332cb69827e2664193faa7f001cb14a5709b3c28600286ac9e6c1fb3176e14e3a7ae3a658d232af6157a3dea83ad992cee75db966ff80213c3a0e52
6
+ metadata.gz: ab036ed40e4f2740de9d37e44d2c6d4d233fa0071f95383accb2334c4d1f85b30b24eea902e0e29c34fefc8749b8caf5d1f9df6c52f93fe2e76c89aa0912d11e
7
+ data.tar.gz: d8ac11f63e5b301ed8b1eacd0d1211fd4b3a0bd79ccae8fe87050833cf305a7345da1dc136b95ecccfcafc6110cf9a281afb0f15db1fe2e01984bf320f82b7e5
data/README.md CHANGED
@@ -49,7 +49,7 @@ Should be installed!
49
49
  Add this line to your application/library's `Gemfile` is needed in basic use-case
50
50
 
51
51
  ```ruby
52
- gem 'ruby-ulid', '0.0.19'
52
+ gem 'ruby-ulid', '>= 0.1.0', '< 0.2.0'
53
53
  ```
54
54
 
55
55
  ### Generator and Parser
@@ -243,13 +243,15 @@ ULID.parse('01F4GNBXW1AM2KWW52PVT3ZY9X').patterns
243
243
 
244
244
  `ULID.min` and `ULID.max` return termination values for ULID spec.
245
245
 
246
+ It can take `Time` instance as an optional argument. Then returns min/max ID that has limit of randomness part in the time.
247
+
246
248
  ```ruby
247
249
  ULID.min #=> ULID(1970-01-01 00:00:00.000 UTC: 00000000000000000000000000)
248
250
  ULID.max #=> ULID(10889-08-02 05:31:50.655 UTC: 7ZZZZZZZZZZZZZZZZZZZZZZZZZ)
249
251
 
250
252
  time = Time.at(946684800, Rational('123456.789')).utc #=> 2000-01-01 00:00:00.123456789 UTC
251
- ULID.min(moment: time) #=> ULID(2000-01-01 00:00:00.123 UTC: 00VHNCZB3V0000000000000000)
252
- ULID.max(moment: time) #=> ULID(2000-01-01 00:00:00.123 UTC: 00VHNCZB3VZZZZZZZZZZZZZZZZ)
253
+ ULID.min(time) #=> ULID(2000-01-01 00:00:00.123 UTC: 00VHNCZB3V0000000000000000)
254
+ ULID.max(time) #=> ULID(2000-01-01 00:00:00.123 UTC: 00VHNCZB3VZZZZZZZZZZZZZZZZ)
253
255
  ```
254
256
 
255
257
  `ULID#next` and `ULID#succ` returns next(successor) ULID.
@@ -388,9 +390,9 @@ Major methods can be replaced as below.
388
390
  -ULID.time(string)
389
391
  +ULID.parse(string).to_time
390
392
  -ULID.min_ulid_at(time)
391
- +ULID.min(moment: time).to_s
393
+ +ULID.min(time).to_s
392
394
  -ULID.max_ulid_at(time)
393
- +ULID.max(moment: time).to_s
395
+ +ULID.max(time).to_s
394
396
  ```
395
397
 
396
398
  NOTE: It is still having precision issue similar as `ulid gem` in the both generator and parser. I sent PRs.
data/lib/ulid.rb CHANGED
@@ -51,7 +51,7 @@ class ULID
51
51
  # @param [Integer] entropy
52
52
  # @return [ULID]
53
53
  def self.generate(moment: current_milliseconds, entropy: reasonable_entropy)
54
- new milliseconds: milliseconds_from_moment(moment), entropy: entropy
54
+ from_milliseconds_and_entropy(milliseconds: milliseconds_from_moment(moment), entropy: entropy)
55
55
  end
56
56
 
57
57
  # Short hand of `ULID.generate(moment: time)`
@@ -59,18 +59,18 @@ class ULID
59
59
  # @return [ULID]
60
60
  def self.at(time)
61
61
  raise ArgumentError, 'ULID.at takes only `Time` instance' unless Time === time
62
- new milliseconds: milliseconds_from_time(time), entropy: reasonable_entropy
62
+ from_milliseconds_and_entropy(milliseconds: milliseconds_from_time(time), entropy: reasonable_entropy)
63
63
  end
64
64
 
65
- # @param [Integer, Time] moment
65
+ # @param [Time, Integer] moment
66
66
  # @return [ULID]
67
- def self.min(moment: 0)
67
+ def self.min(moment=0)
68
68
  0.equal?(moment) ? MIN : generate(moment: moment, entropy: 0)
69
69
  end
70
70
 
71
- # @param [Integer, Time] moment
71
+ # @param [Time, Integer] moment
72
72
  # @return [ULID]
73
- def self.max(moment: MAX_MILLISECONDS)
73
+ def self.max(moment=MAX_MILLISECONDS)
74
74
  MAX_MILLISECONDS.equal?(moment) ? MAX : generate(moment: moment, entropy: MAX_ENTROPY)
75
75
  end
76
76
 
@@ -112,11 +112,11 @@ class ULID
112
112
  raise ArgumentError, 'accepts no argument or integer only' unless Integer === number
113
113
 
114
114
  if number > MAX_INTEGER || number.negative?
115
- raise ArgumentError, "given number #{number} is larger than ULID limit #{MAX_INTEGER} or negative: #{number.inspect}"
115
+ raise ArgumentError, "given number `#{number}` is larger than ULID limit `#{MAX_INTEGER}` or negative"
116
116
  end
117
117
 
118
118
  if period && (number > possibilities)
119
- raise ArgumentError, "given number #{number} is larger than given possibilities #{possibilities}"
119
+ raise ArgumentError, "given number `#{number}` is larger than given possibilities `#{possibilities}`"
120
120
  end
121
121
 
122
122
  Array.new(number) { from_integer(int_generator.call) }
@@ -139,12 +139,12 @@ class ULID
139
139
  self
140
140
  end
141
141
 
142
- # @param [Integer, #to_int] integer
142
+ # @param [Integer] integer
143
143
  # @return [ULID]
144
144
  # @raise [OverflowError] if the given integer is larger than the ULID limit
145
145
  # @raise [ArgumentError] if the given integer is negative number
146
146
  def self.from_integer(integer)
147
- integer = integer.to_int
147
+ raise ArgumentError, 'ULID.from_integer takes only `Integer`' unless Integer === integer
148
148
  raise OverflowError, "integer overflow: given #{integer}, max: #{MAX_INTEGER}" unless integer <= MAX_INTEGER
149
149
  raise ArgumentError, "integer should not be negative: given: #{integer}" if integer.negative?
150
150
 
@@ -160,29 +160,29 @@ class ULID
160
160
 
161
161
  # @param [Range<Time>, Range<nil>, Range[ULID]] period
162
162
  # @return [Range<ULID>]
163
- # @raise [ArgumentError] if the given period is not a `Range[Time]` or `Range[nil]`
163
+ # @raise [ArgumentError] if the given period is not a `Range[Time]`, `Range[nil]` or `Range[ULID]`
164
164
  def self.range(period)
165
- raise ArgumentError, 'ULID.range takes only `Range[Time]` or `Range[nil]`' unless Range === period
165
+ raise ArgumentError, 'ULID.range takes only `Range[Time]`, `Range[nil]` or `Range[ULID]`' unless Range === period
166
166
  begin_element, end_element, exclude_end = period.begin, period.end, period.exclude_end?
167
167
  return period if self === begin_element && self === end_element
168
168
 
169
169
  case begin_element
170
170
  when Time
171
- begin_ulid = min(moment: begin_element)
171
+ begin_ulid = min(begin_element)
172
172
  when nil
173
173
  begin_ulid = MIN
174
174
  when self
175
175
  begin_ulid = begin_element
176
176
  else
177
- raise ArgumentError, "ULID.range takes only `Range[Time]` or `Range[nil]`, given: #{period.inspect}"
177
+ raise ArgumentError, "ULID.range takes only `Range[Time]`, `Range[nil]` or `Range[ULID]`, given: #{period.inspect}"
178
178
  end
179
179
 
180
180
  case end_element
181
181
  when Time
182
182
  if exclude_end
183
- end_ulid = min(moment: end_element)
183
+ end_ulid = min(end_element)
184
184
  else
185
- end_ulid = max(moment: end_element)
185
+ end_ulid = max(end_element)
186
186
  end
187
187
  when nil
188
188
  # The end should be max and include end, because nil end means to cover endless ULIDs until the limit
@@ -191,7 +191,7 @@ class ULID
191
191
  when self
192
192
  end_ulid = end_element
193
193
  else
194
- raise ArgumentError, "ULID.range takes only `Range[Time]` or `Range[nil]`, given: #{period.inspect}"
194
+ raise ArgumentError, "ULID.range takes only `Range[Time]`, `Range[nil]` or `Range[ULID]`, given: #{period.inspect}"
195
195
  end
196
196
 
197
197
  begin_ulid.freeze
@@ -218,6 +218,7 @@ class ULID
218
218
  milliseconds_from_time(Time.now)
219
219
  end
220
220
 
221
+ # @api private
221
222
  # @param [Time] time
222
223
  # @return [Integer]
223
224
  private_class_method def self.milliseconds_from_time(time)
@@ -266,11 +267,22 @@ class ULID
266
267
  end
267
268
 
268
269
  # @api private
269
- # @param [MonotonicGenerator] generator
270
+ # @param [Integer] milliseconds
271
+ # @param [Integer] entropy
270
272
  # @return [ULID]
271
- def self.from_monotonic_generator(generator)
272
- raise ArgumentError, 'this method provided only for MonotonicGenerator' unless MonotonicGenerator === generator
273
- new milliseconds: generator.latest_milliseconds, entropy: generator.latest_entropy
273
+ # @raise [OverflowError] if the given value is larger than the ULID limit
274
+ # @raise [ArgumentError] if the given milliseconds and/or entropy is negative number
275
+ def self.from_milliseconds_and_entropy(milliseconds:, entropy:)
276
+ raise ArgumentError, 'milliseconds and entropy should be an `Integer`' unless Integer === milliseconds && Integer === entropy
277
+ raise OverflowError, "timestamp overflow: given #{milliseconds}, max: #{MAX_MILLISECONDS}" unless milliseconds <= MAX_MILLISECONDS
278
+ raise OverflowError, "entropy overflow: given #{entropy}, max: #{MAX_ENTROPY}" unless entropy <= MAX_ENTROPY
279
+ raise ArgumentError, 'milliseconds and entropy should not be negative' if milliseconds.negative? || entropy.negative?
280
+
281
+ n32encoded_timestamp = milliseconds.to_s(32).rjust(TIMESTAMP_ENCODED_LENGTH, '0')
282
+ n32encoded_randomness = entropy.to_s(32).rjust(RANDOMNESS_ENCODED_LENGTH, '0')
283
+ integer = (n32encoded_timestamp + n32encoded_randomness).to_i(32)
284
+
285
+ new milliseconds: milliseconds, entropy: entropy, integer: integer
274
286
  end
275
287
 
276
288
  attr_reader :milliseconds, :entropy
@@ -280,42 +292,27 @@ class ULID
280
292
  # @param [Integer] entropy
281
293
  # @param [Integer] integer
282
294
  # @return [void]
283
- # @raise [OverflowError] if the given value is larger than the ULID limit
284
- # @raise [ArgumentError] if the given milliseconds and/or entropy is negative number
285
- def initialize(milliseconds:, entropy:, integer: nil)
286
- if integer
287
- @integer = integer
288
- else
289
- milliseconds = milliseconds.to_int
290
- entropy = entropy.to_int
291
-
292
- raise OverflowError, "timestamp overflow: given #{milliseconds}, max: #{MAX_MILLISECONDS}" unless milliseconds <= MAX_MILLISECONDS
293
- raise OverflowError, "entropy overflow: given #{entropy}, max: #{MAX_ENTROPY}" unless entropy <= MAX_ENTROPY
294
- raise ArgumentError, 'milliseconds and entropy should not be negative' if milliseconds.negative? || entropy.negative?
295
- end
296
-
295
+ def initialize(milliseconds:, entropy:, integer:)
296
+ # All arguments check should be done with each constructors, not here
297
+ @integer = integer
297
298
  @milliseconds = milliseconds
298
299
  @entropy = entropy
299
300
  end
300
301
 
301
302
  # @return [String]
302
303
  def to_s
303
- @string ||= CrockfordBase32.encode(to_i).freeze
304
+ @string ||= CrockfordBase32.encode(@integer).freeze
304
305
  end
305
306
 
306
307
  # @return [Integer]
307
308
  def to_i
308
- @integer ||= begin
309
- n32encoded_timestamp = milliseconds.to_s(32).rjust(TIMESTAMP_ENCODED_LENGTH, '0')
310
- n32encoded_randomness = entropy.to_s(32).rjust(RANDOMNESS_ENCODED_LENGTH, '0')
311
- (n32encoded_timestamp + n32encoded_randomness).to_i(32)
312
- end
309
+ @integer
313
310
  end
314
311
  alias_method :hash, :to_i
315
312
 
316
313
  # @return [Integer, nil]
317
314
  def <=>(other)
318
- (ULID === other) ? (to_i <=> other.to_i) : nil
315
+ (ULID === other) ? (@integer <=> other.to_i) : nil
319
316
  end
320
317
 
321
318
  # @return [String]
@@ -325,7 +322,7 @@ class ULID
325
322
 
326
323
  # @return [Boolean]
327
324
  def eql?(other)
328
- equal?(other) || (ULID === other && to_i == other.to_i)
325
+ equal?(other) || (ULID === other && @integer == other.to_i)
329
326
  end
330
327
  alias_method :==, :eql?
331
328
 
@@ -333,7 +330,7 @@ class ULID
333
330
  def ===(other)
334
331
  case other
335
332
  when ULID
336
- to_i == other.to_i
333
+ @integer == other.to_i
337
334
  when String
338
335
  to_s == other.upcase
339
336
  else
@@ -354,7 +351,7 @@ class ULID
354
351
 
355
352
  # @return [Array(Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer)]
356
353
  def octets
357
- digits = to_i.digits(256)
354
+ digits = @integer.digits(256)
358
355
  (OCTETS_LENGTH - digits.size).times do
359
356
  digits.push 0
360
357
  end
@@ -393,7 +390,7 @@ class ULID
393
390
 
394
391
  # @return [ULID, nil] when called on ULID as `7ZZZZZZZZZZZZZZZZZZZZZZZZZ`, returns `nil` instead of ULID
395
392
  def succ
396
- succ_int = to_i.succ
393
+ succ_int = @integer.succ
397
394
  if succ_int >= MAX_INTEGER
398
395
  if succ_int == MAX_INTEGER
399
396
  MAX
@@ -408,7 +405,7 @@ class ULID
408
405
 
409
406
  # @return [ULID, nil] when called on ULID as `00000000000000000000000000`, returns `nil` instead of ULID
410
407
  def pred
411
- pred_int = to_i.pred
408
+ pred_int = @integer.pred
412
409
  if pred_int <= 0
413
410
  if pred_int == 0
414
411
  MIN
@@ -427,6 +424,18 @@ class ULID
427
424
  super
428
425
  end
429
426
 
427
+ # @return [self]
428
+ def dup
429
+ self
430
+ end
431
+
432
+ # @return [self]
433
+ def clone(freeze: true)
434
+ self
435
+ end
436
+
437
+ undef_method :instance_variable_set
438
+
430
439
  private
431
440
 
432
441
  # @return [void]
@@ -27,7 +27,7 @@ class ULID
27
27
  else
28
28
  @latest_entropy += 1
29
29
  end
30
- ULID.from_monotonic_generator(self)
30
+ ULID.from_milliseconds_and_entropy(milliseconds: @latest_milliseconds, entropy: @latest_entropy)
31
31
  end
32
32
  end
33
33
 
data/lib/ulid/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  class ULID
5
- VERSION = '0.0.19'
5
+ VERSION = '0.1.0'
6
6
  end
data/sig/ulid.rbs CHANGED
@@ -63,33 +63,33 @@ class ULID
63
63
  @milliseconds: Integer
64
64
  @entropy: Integer
65
65
  @string: String?
66
- @integer: Integer?
66
+ @integer: Integer
67
67
  @timestamp: String?
68
68
  @randomness: String?
69
69
  @inspect: String?
70
70
  @time: Time?
71
71
 
72
- def self.generate: (?moment: moment, ?entropy: Integer) -> ULID
73
- def self.at: (Time time) -> ULID
72
+ def self.generate: (?moment: moment, ?entropy: Integer) -> self
73
+ def self.at: (Time time) -> self
74
74
  def self.current_milliseconds: -> Integer
75
75
  def self.milliseconds_from_moment: (moment moment) -> Integer
76
76
  def self.range: (period period) -> Range[ULID]
77
77
  def self.floor: (Time time) -> Time
78
78
  def self.reasonable_entropy: -> Integer
79
- def self.parse: (String string) -> ULID
79
+ def self.parse: (String string) -> self
80
80
  def self.from_uuidv4: (String uuid) -> ULID
81
- def self.from_integer: (Integer integer) -> ULID
82
- def self.min: (?moment: moment) -> ULID
83
- def self.max: (?moment: moment) -> ULID
84
- def self.sample: (?period: period) -> ULID
85
- | (Integer number, ?period: period) -> Array[ULID]
81
+ def self.from_integer: (Integer integer) -> self
82
+ def self.min: (?moment moment) -> ULID
83
+ def self.max: (?moment moment) -> ULID
84
+ def self.sample: (?period: period) -> self
85
+ | (Integer number, ?period: period) -> Array[self]
86
86
  def self.valid?: (untyped string) -> bool
87
- def self.scan: (String string) -> Enumerator[ULID, singleton(ULID)]
88
- | (String string) { (ULID ulid) -> void } -> singleton(ULID)
89
- def self.from_monotonic_generator: (MonotonicGenerator generator) -> ULID
87
+ def self.scan: (String string) -> Enumerator[self, singleton(ULID)]
88
+ | (String string) { (self ulid) -> void } -> singleton(ULID)
89
+ def self.from_milliseconds_and_entropy: (milliseconds: Integer, entropy: Integer) -> self
90
90
  attr_reader milliseconds: Integer
91
91
  attr_reader entropy: Integer
92
- def initialize: (milliseconds: Integer, entropy: Integer, ?integer: Integer) -> void
92
+ def initialize: (milliseconds: Integer, entropy: Integer, integer: Integer) -> void
93
93
  def to_s: -> String
94
94
  def to_i: -> Integer
95
95
  alias hash to_i
@@ -111,6 +111,9 @@ class ULID
111
111
  alias succ next
112
112
  def pred: -> ULID?
113
113
  def freeze: -> self
114
+ def dup: -> self
115
+ # Same as https://github.com/ruby/rbs/blob/4fb4c33b2325d1a73d79ff7aaeb49f21cec1e0e5/core/object.rbs#L79
116
+ def clone: (?freeze: bool) -> self
114
117
 
115
118
  private
116
119
  def self.milliseconds_from_time: (Time time) -> Integer
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.0.19
4
+ version: 0.1.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: 2021-05-08 00:00:00.000000000 Z
11
+ date: 2021-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs