ruby-ulid 0.0.19 → 0.1.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 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