hyperuuid 0.0.1 → 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: d2b7cb6d510ac9faccd193dde27916dc8bd7384b6b9c1d387dfc47682eeb9274
4
- data.tar.gz: f4d3082562a32328b0519b6f2c0b461d8fb3303d731fca8b1b96422266f97e4c
3
+ metadata.gz: d36a27a93cdb9a4a6bffeb6a6b9ddb8da61bbc9d20b8fda29ad7c8b2238465c2
4
+ data.tar.gz: cbe47ffb022c0ccb23d98ff9543c56d515ecc6928dbf7df11533593c097247ae
5
5
  SHA512:
6
- metadata.gz: 1d80438fc78ff61048568c3ff70fff7bc6493ba639ac60299c21495b863419fc49f5e61f38bdfaf1b9be9910930da9124deaf98254bc119d9ec0d8f11b6cf1fc
7
- data.tar.gz: beed906a491217aef07a6d3ce2ac36f77410710c7379ae1cffa0733cdb3c33c2eb1deeecd24fac7d32f96160068b512b6d5984fbd5aa7508e6fa23590e950169
6
+ metadata.gz: eb071fda1c20cb7f44d0b64fbcf2833768bac66cfe7d71951d1ba2e4ef0fe3d3d166d6a545b347bba22b52dee932e979f8e7b0059719f92c6308fc70629dbd04
7
+ data.tar.gz: 8630e51665339db93b4a6c90230b08649f8b9bf2e86520b09a803bff435d0e977df6bdfc88601b412d33f8aa8b19104afd854329d409c0894d9bb3c98258c2ef
data/README.md CHANGED
@@ -23,6 +23,7 @@ id3 = HyperUuid.new_v6
23
23
  id4 = HyperUuid.new_v7
24
24
 
25
25
  id4.timestamp # recover the embedded UTC Time
26
+ id4.timestamp(raise_on_mismatch: false) # nil instead of raising if id4 isn't v6/v7
26
27
  id4.to_sql_order # byte order SQL Server's uniqueidentifier needs to sort by creation order
27
28
 
28
29
  # One native call, one random-bytes fetch, one counter reservation for the whole batch:
@@ -32,7 +33,9 @@ batch = HyperUuid.new_v7_batch(1000)
32
33
  Returns `HyperUuid::Uuid`, a minimal value object (`#bytes`, `#to_s`, `#version`, `#variant`,
33
34
  comparable/hashable) — this gem has no runtime dependency on the `uuid` gem.
34
35
  `HyperUuid::Namespaces::DNS`/`URL`/`OID`/`X500` are RFC 9562 Section 6.6's well-known
35
- namespaces. `#timestamp` recovers the embedded UTC `Time` from a version 6 or 7 UUID.
36
+ namespaces. `#timestamp` recovers the embedded UTC `Time` from a version 6 or 7 UUID; pass
37
+ `raise_on_mismatch: false` to get `nil` back for any other version instead of raising.
38
+ `.new_v6`/`.new_v7` also accept a `Time` directly in place of a raw millisecond count.
36
39
  `#to_sql_order`/`#from_sql_order` convert a version 6 or 7 UUID to and from the byte order SQL
37
40
  Server's `uniqueidentifier` needs on the wire to sort by creation order (`#to_sql_order`
38
41
  dispatches on the UUID's own version, matching `#timestamp`'s convention) — computed once in
@@ -90,10 +93,15 @@ The batch multiplier shrank from 11x to ~3.8x for the best reason available: the
90
93
 
91
94
  ## Install
92
95
 
93
- Not yet published to RubyGems.org under a registered `SkunkWerkx`/`buvinghausen` presence —
94
- for now this is proven by CI building and testing the native core plus this gem on real
95
- hardware for every platform leg. Consume via a direct
96
- `gem "hyperuuid", git: "https://github.com/SkunkWerkx/HyperUuid", glob: "ruby/*.gemspec"` in
97
- the meantime.
96
+ ```sh
97
+ gem install hyperuuid
98
+ ```
99
+
100
+ Published to [RubyGems.org](https://rubygems.org/gems/hyperuuid) as real precompiled
101
+ "platform gems" — `bundle`/`gem install` auto-selects the matching one for
102
+ linux-x64/arm64 or osx-x64/arm64 (the compiled Magnus native extension, `backend: :native`),
103
+ falling back automatically to the universal `ruby`-platform gem (pure Fiddle, zero compile,
104
+ bundles all 6 platforms' native libs) everywhere else — Windows included, since Magnus
105
+ doesn't target it. No extra configuration needed either way.
98
106
 
99
107
  See [the repo root README](../README.md) for the full RFC 9562 coverage table and the state of every other language binding.
@@ -52,12 +52,18 @@ module HyperUuid
52
52
  # when `version` is 6 or 7 — the RFC 9562 bit layout doesn't distinguish "not a time-based
53
53
  # UUID" from "time-based UUID with a very early timestamp", so the caller is responsible
54
54
  # for checking `version` first if that matters.
55
- def timestamp
55
+ #
56
+ # Raises by default for any other version; pass `raise_on_mismatch: false` to get `nil`
57
+ # back instead — for a caller that doesn't already know (or want to separately check)
58
+ # whether this UUID is time-based.
59
+ def timestamp(raise_on_mismatch: true)
56
60
  millis =
57
61
  case version
58
62
  when 6 then Runtime.v6_unix_millis(bytes)
59
63
  when 7 then Runtime.v7_unix_millis(bytes)
60
- else raise ArgumentError, "timestamp is only defined for version 6 or 7 UUIDs, got version #{version}"
64
+ else
65
+ raise ArgumentError, "timestamp is only defined for version 6 or 7 UUIDs, got version #{version}" if raise_on_mismatch
66
+ return nil
61
67
  end
62
68
  Time.at(millis / 1000, millis % 1000, :millisecond).utc
63
69
  end
data/lib/hyperuuid.rb CHANGED
@@ -33,38 +33,49 @@ module HyperUuid
33
33
  Uuid.new(Runtime.new_v5(namespace.bytes, name_bytes))
34
34
  end
35
35
 
36
+ # Converts +value+ to a Unix-epoch millisecond integer: +nil+ becomes the current time, a
37
+ # +Time+ is converted exactly (via its own Rational seconds, avoiding float rounding), and
38
+ # anything else (an Integer millisecond count) passes through unchanged. Shared by every
39
+ # `new_v6`/`new_v7`/batch door below so a caller can pass either a `Time` or a raw
40
+ # millisecond count interchangeably.
41
+ private_class_method def self.unix_millis_from(value)
42
+ case value
43
+ when nil then Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
44
+ when Time then (value.to_r * 1000).to_i
45
+ else value
46
+ end
47
+ end
48
+
36
49
  # Creates a time-sortable UUID version 6 (RFC 9562 §5.6), a field-compatible reordering of
37
50
  # version 1 for better sort/index locality. Defaults to the current time; pass an explicit
38
- # Unix-epoch millisecond timestamp to embed a specific time instead. `clock_seq` and `node`
39
- # are randomly generated on every call — unlike version 7, there is no monotonic counter, so
40
- # calls within the same millisecond are not guaranteed to sort in creation order.
51
+ # `Time` or Unix-epoch millisecond integer to embed a specific time instead. `clock_seq` and
52
+ # `node` are randomly generated on every call — unlike version 7, there is no monotonic
53
+ # counter, so calls within the same millisecond are not guaranteed to sort in creation order.
41
54
  def self.new_v6(unix_millis = nil)
42
- unix_millis ||= Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
43
- Uuid.new(Runtime.new_v6(unix_millis))
55
+ Uuid.new(Runtime.new_v6(unix_millis_from(unix_millis)))
44
56
  end
45
57
 
46
58
  # Creates `count` time-sortable version 6 UUIDs sharing one timestamp capture — one FFI call
47
- # and one random-bytes fetch instead of `count` of each. Defaults to the current time.
59
+ # and one random-bytes fetch instead of `count` of each. Defaults to the current time; pass
60
+ # an explicit `Time` or Unix-epoch millisecond integer to embed a specific time instead.
48
61
  def self.new_v6_batch(count, unix_millis = nil)
49
- unix_millis ||= Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
50
- bytes = Runtime.new_v6_batch(count, unix_millis)
62
+ bytes = Runtime.new_v6_batch(count, unix_millis_from(unix_millis))
51
63
  Array.new(count) { |i| Uuid.new(bytes[i * 16, 16]) }
52
64
  end
53
65
 
54
66
  # Creates a time-sortable UUID version 7 (RFC 9562 §6.2). Defaults to the current time; pass
55
- # an explicit Unix-epoch millisecond timestamp (non-negative, fitting in 48 bits) to embed a
56
- # specific time instead.
67
+ # an explicit `Time` or Unix-epoch millisecond integer (non-negative, fitting in 48 bits) to
68
+ # embed a specific time instead.
57
69
  def self.new_v7(unix_millis = nil)
58
- unix_millis ||= Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
59
- Uuid.new(Runtime.new_v7(unix_millis))
70
+ Uuid.new(Runtime.new_v7(unix_millis_from(unix_millis)))
60
71
  end
61
72
 
62
73
  # Creates `count` time-sortable version 7 UUIDs sharing one timestamp capture and one
63
74
  # contiguous block of the monotonic counter — one FFI call and one random-bytes fetch
64
- # instead of `count` of each. Defaults to the current time.
75
+ # instead of `count` of each. Defaults to the current time; pass an explicit `Time` or
76
+ # Unix-epoch millisecond integer to embed a specific time instead.
65
77
  def self.new_v7_batch(count, unix_millis = nil)
66
- unix_millis ||= Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond)
67
- bytes = Runtime.new_v7_batch(count, unix_millis)
78
+ bytes = Runtime.new_v7_batch(count, unix_millis_from(unix_millis))
68
79
  Array.new(count) { |i| Uuid.new(bytes[i * 16, 16]) }
69
80
  end
70
81
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hyperuuid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Buvinghausen