block-uuidv7 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ae447bd13b7cd778a06726790f667823627a9b3bac0adbce6d309b3e367b2e3d
4
+ data.tar.gz: b526111fb89415d3efff2bc315af518c43f9dfb7a432a6363b582bbdd746dc1f
5
+ SHA512:
6
+ metadata.gz: b4b93d3b5a7aaf4007cf70ada05fc001561d4a9a24df2594a6011fcce0644f74f2a7eae9466323e52ef7bdf302bfb1b8ce8a4aaeaaf34e75454f9e8407006ec6
7
+ data.tar.gz: 71d36f1e1395312cf3348cc00cb6b254792c3c9836a9e590990f12e7d760325a3161976857b497f6c322fdaa515eeaead9e14e3da0d91aea8e6d5f189bd28189
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,23 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.0
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+
6
+ Style/Documentation:
7
+ Enabled: false
8
+
9
+ Metrics/BlockLength:
10
+ Exclude:
11
+ - 'spec/**/*'
12
+
13
+ Metrics/MethodLength:
14
+ Max: 25
15
+
16
+ Metrics/AbcSize:
17
+ Max: 30
18
+
19
+ Style/FormatStringToken:
20
+ Enabled: false
21
+
22
+ Layout/LineLength:
23
+ Max: 120
data/AGENTS.md ADDED
@@ -0,0 +1,88 @@
1
+ # Agent Guide - Ruby Implementation
2
+
3
+ For the multi-language overview, see [root AGENTS.md](../AGENTS.md).
4
+
5
+ ## Quick Commands
6
+
7
+ ```bash
8
+ cd ruby
9
+ bundle install # Install dependencies
10
+ bundle exec rake spec # Run tests
11
+ bundle exec rake rubocop # Run linter
12
+ bundle exec rake # Run both tests and linter
13
+ ```
14
+
15
+ ## Prerequisites
16
+
17
+ - Ruby 3.0 or later
18
+ - Bundler
19
+
20
+ ## Project Structure
21
+
22
+ ```
23
+ ruby/
24
+ ├── lib/
25
+ │ ├── uuidv7.rb # Main entry point
26
+ │ └── uuidv7/
27
+ │ ├── version.rb # Version constant
28
+ │ ├── generator.rb # High-performance UUID v7 (no ordering guarantees)
29
+ │ ├── monotonic_generator.rb # Monotonic UUID v7 (strict ordering)
30
+ │ └── base62.rb # Base62 encoding/decoding
31
+ ├── spec/
32
+ │ ├── spec_helper.rb
33
+ │ ├── uuidv7_spec.rb
34
+ │ ├── monotonic_uuidv7_spec.rb
35
+ │ └── base62_spec.rb
36
+ ├── uuidv7.gemspec
37
+ ├── Gemfile
38
+ ├── Rakefile
39
+ ├── README.md
40
+ └── AGENTS.md # This file
41
+ ```
42
+
43
+ ## Key Implementation Details
44
+
45
+ ### Random Number Generation Strategy
46
+
47
+ - Uses `SecureRandom` from Ruby stdlib for all random bits
48
+ - Ruby's `rand()` is not thread-safe, so `SecureRandom` is preferred
49
+ - Performance is still excellent for typical use cases
50
+
51
+ ### Monotonic Counter Behavior
52
+
53
+ - Counter occupies 12 bits (rand_a field): 0-4095
54
+ - Counter increments with each generation in same millisecond
55
+ - Counter resets to **random value** when timestamp advances (not zero!)
56
+ - If counter overflows (4096 in same ms), waits for next millisecond
57
+ - Uses `Mutex` for thread safety
58
+
59
+ ### Thread Safety
60
+
61
+ - `UUIDv7.generate`: Thread-safe (no shared mutable state)
62
+ - `MonotonicUUIDv7.generate`: Thread-safe via Mutex synchronization
63
+
64
+ ### Clock Injection
65
+
66
+ Uses block-based clock injection for testability:
67
+
68
+ ```ruby
69
+ UUIDv7.generate { 1700000000000 }
70
+ MonotonicUUIDv7.generate { Time.now.to_i * 1000 }
71
+ ```
72
+
73
+ ### Testing Notes
74
+
75
+ - `MonotonicGenerator.reset_state!` is available for test isolation
76
+ - Always reset state before monotonic tests to ensure deterministic behavior
77
+
78
+ ## Gem Publishing
79
+
80
+ ```bash
81
+ gem build uuidv7.gemspec
82
+ gem push uuidv7-x.x.x.gem
83
+ ```
84
+
85
+ ## Further Reading
86
+
87
+ - [README.md](README.md) - API documentation and usage examples
88
+ - [Root AGENTS.md](../AGENTS.md) - Shared algorithm and design principles
data/README.md ADDED
@@ -0,0 +1,163 @@
1
+ # UUIDv7 - Ruby
2
+
3
+ A minimal, high-performance UUID v7 implementation for Ruby.
4
+
5
+ ## Introduction
6
+
7
+ [UUID v7](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7) is a time-ordered UUID format that encodes a Unix timestamp in the most significant 48 bits, making UUIDs naturally sortable by creation time. This is useful for:
8
+
9
+ - Database indexed fields that benefit from sequential ordering
10
+ - Distributed systems where time-based ordering is valuable
11
+ - Event logs and audit trails where chronological sorting is important
12
+
13
+ ### Compact Base62 Format
14
+
15
+ **Recommended for APIs, databases, and anywhere IDs are stored or transmitted as text.**
16
+
17
+ #### Why Compact Strings?
18
+
19
+ UUIDs are 128-bit values. When you need to store or transmit them, you have two choices:
20
+
21
+ 1. **Binary (16 bytes)**: Most efficient, but not human-readable and requires binary-safe storage
22
+ 2. **String**: Human-readable and universally supported, but takes more space
23
+
24
+ If you must use strings (APIs, URLs, text database columns, JSON, logs), the standard UUID format (`01936c0a-5e0c-7b3a-8f9d-2e1c4a6b8d0f`) uses 36 characters. The compact format reduces this to **22 characters** while preserving all the benefits of UUID v7.
25
+
26
+ #### How It Works
27
+
28
+ The compact format uses **Base62 encoding** (digits `0-9`, uppercase `A-Z`, lowercase `a-z`) to represent the 128-bit UUID value. This is similar to how Base64 works, but without special characters like `+`, `/`, or `=`.
29
+
30
+ ```
31
+ Standard: 01936c0a-5e0c-7b3a-8f9d-2e1c4a6b8d0f (36 chars)
32
+ Compact: 01JDQYZ9M6K7TCJK2F3W8N (22 chars)
33
+
34
+ Same UUID, different encoding
35
+ ```
36
+
37
+ The encoding preserves **lexicographic ordering**: if UUID A was generated before UUID B, then `compact(A) < compact(B)` in string comparison. This means database indexes on compact strings maintain time-ordering, and APIs can sort by ID to get chronological order.
38
+
39
+ #### When to Use Compact Strings
40
+
41
+ | Use Case | Recommended Format |
42
+ |----------|-------------------|
43
+ | Database binary column (BINARY(16), BLOB) | Binary (16 bytes) |
44
+ | Database text/VARCHAR column | **Compact (22 chars)** |
45
+ | REST API responses | **Compact (22 chars)** |
46
+ | URLs and query parameters | **Compact (22 chars)** |
47
+ | Logs and debugging | Standard (36 chars) for readability |
48
+ | Interop with systems expecting standard UUIDs | Standard (36 chars) |
49
+
50
+ #### Benefits Summary
51
+
52
+ - **39% shorter** than standard UUID strings (22 vs 36 characters)
53
+ - **Lexicographically sortable** - preserves time-based ordering in databases and APIs
54
+ - **URL-safe** - no special characters, hyphens, or encoding needed
55
+ - **Database-friendly** - smaller indexes, faster queries, less storage
56
+
57
+ ## Installation
58
+
59
+ Add this line to your application's Gemfile:
60
+
61
+ ```ruby
62
+ gem 'uuidv7'
63
+ ```
64
+
65
+ And then execute:
66
+
67
+ ```bash
68
+ bundle install
69
+ ```
70
+
71
+ Or install it yourself as:
72
+
73
+ ```bash
74
+ gem install uuidv7
75
+ ```
76
+
77
+ ## Usage
78
+
79
+ ```ruby
80
+ require 'uuidv7'
81
+
82
+ # Generate a UUID v7 (high performance, no ordering guarantees within same millisecond)
83
+ uuid = UUIDv7.generate
84
+ # => "01936c0a-5e0c-7b3a-8f9d-2e1c4a6b8d0f"
85
+
86
+ # Generate with monotonic ordering (for database primary keys)
87
+ uuid = MonotonicUUIDv7.generate
88
+ # => "01936c0a-5e0c-7b3a-8f9d-2e1c4a6b8d0f"
89
+
90
+ # Extract the timestamp (milliseconds since Unix epoch)
91
+ timestamp = UUIDv7.timestamp(uuid)
92
+ # => 1700000000000
93
+
94
+ # Generate a compact string directly (22 characters, Base62)
95
+ compact_id = UUIDv7.generate_compact
96
+ # => "01JDQYZ9M6K7TCJK2F3W8N"
97
+
98
+ # Convert UUID to compact string (preserves sort order)
99
+ compact = UUIDv7.to_compact(uuid)
100
+
101
+ # Convert compact string back to UUID
102
+ uuid = UUIDv7.from_compact(compact)
103
+
104
+ # Custom clock for testing
105
+ uuid = UUIDv7.generate { 1700000000000 }
106
+
107
+ # Monotonic with custom clock
108
+ uuid = MonotonicUUIDv7.generate { 1700000000000 }
109
+ ```
110
+
111
+ ## Design Principles
112
+
113
+ **Minimal API Surface**: Simple module methods that return standard UUID strings. No custom UUID class - maximum compatibility with existing code.
114
+
115
+ **Separate Modules for Different Use Cases**: Two distinct implementations for different performance/ordering trade-offs:
116
+ - **`UUIDv7`**: Maximum performance with no synchronization overhead. UUIDs generated in the same millisecond may not be strictly ordered, but uniqueness is maintained through random bits. Ideal for high-throughput scenarios and distributed systems.
117
+ - **`MonotonicUUIDv7`**: Uses a mutex-protected counter to ensure strict ordering within the same millisecond, following RFC 9562 recommendations. Best for database primary keys and scenarios requiring guaranteed sequential ordering.
118
+
119
+ **Timestamp Extraction**: UUIDs contain timing information, and this library makes it easy to extract this for debugging, observability, and time-based queries.
120
+
121
+ **Flexible Generation**: Block-based clock injection for testing or custom time sources.
122
+
123
+ ## API Reference
124
+
125
+ ### UUIDv7 (High Performance, No Ordering Guarantees)
126
+
127
+ | Method | Description |
128
+ |--------|-------------|
129
+ | `UUIDv7.generate(&clock)` | Generate a new UUID v7 string. Optional block for custom clock. |
130
+ | `UUIDv7.generate_compact(&clock)` | Generate a new UUID v7 as 22-character compact string. |
131
+ | `UUIDv7.timestamp(uuid)` | Extract millisecond timestamp from UUID v7 string. |
132
+ | `UUIDv7.to_compact(uuid)` | Convert UUID string to 22-character compact string. |
133
+ | `UUIDv7.from_compact(compact)` | Convert compact string back to UUID string. |
134
+
135
+ ### MonotonicUUIDv7 (Sequential Ordering Guaranteed)
136
+
137
+ | Method | Description |
138
+ |--------|-------------|
139
+ | `MonotonicUUIDv7.generate(&clock)` | Generate a new UUID v7 with strict ordering. Optional block for custom clock. |
140
+ | `MonotonicUUIDv7.generate_compact(&clock)` | Generate with strict ordering as compact string. |
141
+
142
+ ## Implementation Details
143
+
144
+ ### Format
145
+
146
+ UUID v7 follows RFC 9562:
147
+ - **Bits 0-47**: Unix timestamp in milliseconds (48 bits)
148
+ - **Bits 48-51**: Version field (0111 for v7)
149
+ - **Bits 52-63**: Counter or random bits (12 bits, called `rand_a`)
150
+ - **Bits 64-65**: Variant field (10 for RFC 4122)
151
+ - **Bits 66-127**: Random bits (62 bits, called `rand_b`)
152
+
153
+ ### Monotonic Counter Behavior
154
+
155
+ - Counter occupies 12 bits (rand_a field): 0-4095
156
+ - Counter increments with each generation in same millisecond
157
+ - Counter resets to **random value** when timestamp advances
158
+ - If counter overflows (4096 in same ms), waits for next millisecond
159
+ - Thread-safe via Mutex synchronization
160
+
161
+ ## License
162
+
163
+ Apache-2.0
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[spec rubocop]
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/uuidv7/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'block-uuidv7'
7
+ spec.version = UUIDv7::VERSION
8
+ spec.authors = ['Block, Inc.']
9
+ spec.email = ['opensource@block.xyz']
10
+
11
+ spec.summary = 'A minimal, high-performance UUID v7 implementation for Ruby'
12
+ spec.description = 'UUID v7 is a time-ordered UUID format that encodes a Unix timestamp in the most significant ' \
13
+ '48 bits, making UUIDs naturally sortable by creation time. This library provides both ' \
14
+ 'high-performance and monotonic (strictly ordered) variants.'
15
+ spec.homepage = 'https://github.com/block/uuidv7'
16
+ spec.license = 'Apache-2.0'
17
+ spec.required_ruby_version = '>= 3.0.0'
18
+
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = 'https://github.com/block/uuidv7/tree/main/ruby'
21
+ spec.metadata['rubygems_mfa_required'] = 'true'
22
+
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (File.expand_path(f) == __FILE__) ||
26
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
27
+ end
28
+ end
29
+ spec.bindir = 'exe'
30
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
+ spec.require_paths = ['lib']
32
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UUIDv7
4
+ module Base62
5
+ ALPHABET = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
6
+ BASE = 62
7
+ COMPACT_LENGTH = 22
8
+
9
+ class << self
10
+ def encode(uuid)
11
+ raise InvalidUUIDError, 'UUID cannot be nil' if uuid.nil?
12
+
13
+ hex = uuid.delete('-')
14
+ raise InvalidUUIDError, 'Invalid UUID format' unless hex.match?(/\A[0-9a-f]{32}\z/i)
15
+
16
+ value = hex.to_i(16)
17
+ result = []
18
+
19
+ while value.positive?
20
+ value, remainder = value.divmod(BASE)
21
+ result << ALPHABET[remainder]
22
+ end
23
+
24
+ result << '0' while result.length < COMPACT_LENGTH
25
+
26
+ result.reverse.join
27
+ end
28
+
29
+ def decode(compact_string)
30
+ raise InvalidCompactStringError, 'Compact string cannot be nil' if compact_string.nil?
31
+
32
+ unless compact_string.length == COMPACT_LENGTH
33
+ raise InvalidCompactStringError,
34
+ "Compact string must be exactly #{COMPACT_LENGTH} characters (got #{compact_string.length})"
35
+ end
36
+
37
+ value = 0
38
+ compact_string.each_char do |char|
39
+ digit = ALPHABET.index(char)
40
+ raise InvalidCompactStringError, "Invalid compact string character: #{char}" if digit.nil?
41
+
42
+ value = (value * BASE) + digit
43
+ end
44
+
45
+ msb = (value >> 64) & 0xFFFFFFFFFFFFFFFF
46
+ lsb = value & 0xFFFFFFFFFFFFFFFF
47
+
48
+ hex = format('%016x%016x', msb, lsb)
49
+ "#{hex[0, 8]}-#{hex[8, 4]}-#{hex[12, 4]}-#{hex[16, 4]}-#{hex[20, 12]}"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module UUIDv7
6
+ module Generator
7
+ class << self
8
+ def generate(&clock)
9
+ timestamp = clock ? clock.call : (Time.now.to_f * 1000).to_i
10
+ rand_a = rand(4096)
11
+ rand_b = SecureRandom.random_number(2**62)
12
+
13
+ build(timestamp, rand_a, rand_b)
14
+ end
15
+
16
+ def generate_compact(&clock)
17
+ Base62.encode(generate(&clock))
18
+ end
19
+
20
+ def timestamp(uuid)
21
+ raise InvalidUUIDError, 'UUID cannot be nil' if uuid.nil?
22
+
23
+ hex = uuid.delete('-')
24
+ raise InvalidUUIDError, 'Invalid UUID format' unless hex.match?(/\A[0-9a-f]{32}\z/i)
25
+
26
+ msb = hex[0, 16].to_i(16)
27
+ version = (msb >> 12) & 0xF
28
+
29
+ raise InvalidUUIDError, "UUID is not version 7 (got version #{version})" unless version == 7
30
+
31
+ msb >> 16
32
+ end
33
+
34
+ def build(timestamp, rand_a, rand_b)
35
+ rand_a &= 0xFFF
36
+
37
+ msb = (timestamp << 16) | rand_a
38
+ lsb = rand_b
39
+
40
+ msb = (msb & 0xFFFFFFFFFFFF0FFF) | 0x0000000000007000
41
+ lsb = (lsb & 0x3FFFFFFFFFFFFFFF) | 0x8000000000000000
42
+
43
+ format_uuid(msb, lsb)
44
+ end
45
+
46
+ private
47
+
48
+ def format_uuid(msb, lsb)
49
+ hex = format('%016x%016x', msb, lsb)
50
+ "#{hex[0, 8]}-#{hex[8, 4]}-#{hex[12, 4]}-#{hex[16, 4]}-#{hex[20, 12]}"
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module UUIDv7
6
+ module MonotonicGenerator
7
+ COUNTER_MAX = 0xFFF # 12 bits = 4095
8
+
9
+ @mutex = Mutex.new
10
+ @last_timestamp = 0
11
+ @counter = 0
12
+
13
+ class << self
14
+ def generate(&clock)
15
+ @mutex.synchronize do
16
+ timestamp = clock ? clock.call : (Time.now.to_f * 1000).to_i
17
+ counter_value = nil
18
+
19
+ if timestamp == @last_timestamp
20
+ @counter = (@counter + 1) & COUNTER_MAX
21
+
22
+ if @counter.zero?
23
+ loop do
24
+ timestamp = clock ? clock.call : (Time.now.to_f * 1000).to_i
25
+ break if timestamp != @last_timestamp
26
+
27
+ sleep(0.0001) unless clock
28
+ end
29
+ @counter = SecureRandom.random_number(COUNTER_MAX + 1)
30
+ end
31
+ counter_value = @counter
32
+ else
33
+ @counter = SecureRandom.random_number(COUNTER_MAX + 1)
34
+ counter_value = @counter
35
+ @last_timestamp = timestamp
36
+ end
37
+
38
+ rand_b = SecureRandom.random_number(2**62)
39
+ Generator.build(timestamp, counter_value, rand_b)
40
+ end
41
+ end
42
+
43
+ def generate_compact(&clock)
44
+ Base62.encode(generate(&clock))
45
+ end
46
+
47
+ def reset_state!
48
+ @mutex.synchronize do
49
+ @last_timestamp = 0
50
+ @counter = 0
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UUIDv7
4
+ VERSION = '0.1.0'
5
+ end
data/lib/uuidv7.rb ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'uuidv7/version'
4
+ require_relative 'uuidv7/base62'
5
+ require_relative 'uuidv7/generator'
6
+ require_relative 'uuidv7/monotonic_generator'
7
+
8
+ module UUIDv7
9
+ class Error < StandardError; end
10
+ class InvalidUUIDError < Error; end
11
+ class InvalidCompactStringError < Error; end
12
+
13
+ class << self
14
+ def generate(&clock)
15
+ Generator.generate(&clock)
16
+ end
17
+
18
+ def generate_compact(&clock)
19
+ Generator.generate_compact(&clock)
20
+ end
21
+
22
+ def timestamp(uuid)
23
+ Generator.timestamp(uuid)
24
+ end
25
+
26
+ def to_compact(uuid)
27
+ Base62.encode(uuid)
28
+ end
29
+
30
+ def from_compact(compact_string)
31
+ Base62.decode(compact_string)
32
+ end
33
+ end
34
+ end
35
+
36
+ module MonotonicUUIDv7
37
+ class << self
38
+ def generate(&clock)
39
+ UUIDv7::MonotonicGenerator.generate(&clock)
40
+ end
41
+
42
+ def generate_compact(&clock)
43
+ UUIDv7::MonotonicGenerator.generate_compact(&clock)
44
+ end
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: block-uuidv7
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Block, Inc.
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2026-01-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: UUID v7 is a time-ordered UUID format that encodes a Unix timestamp in
14
+ the most significant 48 bits, making UUIDs naturally sortable by creation time.
15
+ This library provides both high-performance and monotonic (strictly ordered) variants.
16
+ email:
17
+ - opensource@block.xyz
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - ".rspec"
23
+ - ".rubocop.yml"
24
+ - AGENTS.md
25
+ - README.md
26
+ - Rakefile
27
+ - block-uuidv7.gemspec
28
+ - lib/uuidv7.rb
29
+ - lib/uuidv7/base62.rb
30
+ - lib/uuidv7/generator.rb
31
+ - lib/uuidv7/monotonic_generator.rb
32
+ - lib/uuidv7/version.rb
33
+ homepage: https://github.com/block/uuidv7
34
+ licenses:
35
+ - Apache-2.0
36
+ metadata:
37
+ homepage_uri: https://github.com/block/uuidv7
38
+ source_code_uri: https://github.com/block/uuidv7/tree/main/ruby
39
+ rubygems_mfa_required: 'true'
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 3.0.0
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.4.19
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: A minimal, high-performance UUID v7 implementation for Ruby
59
+ test_files: []