uuid-v9 0.0.1 → 1.0.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/LICENSE +1 -1
- data/README.md +6 -4
- data/lib/uuid-v9.rb +20 -9
- data/spec/uuid-v9_spec.rb +7 -7
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e91cef6ff913feedd5498b37b4caa47d35289c22f1524bee3318e0e9e178eea3
|
|
4
|
+
data.tar.gz: 8628af9c15b93665e006711d747755d16b893cd6743fe8287214e6b194f4336e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7057703635d13911723d7ce085975bcb524f1e4c03a3013eee2d3c1ea93f2ba23b5c451444d85eff5f3a7f67ca63f0a15861354b83bc4acccb45e10bbee0de13
|
|
7
|
+
data.tar.gz: a6bb594d12d619499eb4e61388a6294582a1062584b3b27bccb0b466a068c3301948c23e100d2a2f3231245e55ac7d3406cb1bdd3edf3f3ed110aeecdb96ad07
|
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Fast, lightweight, zero-dependency Ruby implementation of UUID version 9
|
|
4
4
|
|
|
5
|
-
The v9 UUID supports both sequential (time-based) and non-sequential (random) UUIDs with an optional prefix of up to four bytes, an optional checksum, and sufficient randomness to avoid collisions. It uses the UNIX timestamp for sequential UUIDs and CRC-8 for checksums.
|
|
5
|
+
The v9 UUID supports both sequential (time-based) and non-sequential (random) UUIDs with an optional prefix of up to four bytes, an optional checksum, and sufficient randomness to avoid collisions. It uses the UNIX timestamp for sequential UUIDs and CRC-8 for checksums. The version can be added if desired, but is omitted by default.
|
|
6
6
|
|
|
7
7
|
To learn more about UUID v9, please visit the website: https://uuidv9.jhunt.dev
|
|
8
8
|
|
|
@@ -11,13 +11,13 @@ To learn more about UUID v9, please visit the website: https://uuidv9.jhunt.dev
|
|
|
11
11
|
Install UUID v9 from Rubygems
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
gem install
|
|
14
|
+
gem install uuid-v9
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
19
|
```ruby
|
|
20
|
-
require '
|
|
20
|
+
require 'uuid-v9'
|
|
21
21
|
|
|
22
22
|
ordered_id = UUIDv9::UUIDv9.generate
|
|
23
23
|
prefixed_ordered_id = UUIDv9::UUIDv9.generate(prefix: 'a1b2c3d4')
|
|
@@ -44,4 +44,6 @@ _*Legacy mode adds version and variant digits to immitate v1 or v4 UUIDs dependi
|
|
|
44
44
|
|
|
45
45
|
## License
|
|
46
46
|
|
|
47
|
-
This project is licensed under the [MIT License](LICENSE).
|
|
47
|
+
This project is licensed under the [MIT License](LICENSE).
|
|
48
|
+
|
|
49
|
+
<><
|
data/lib/uuid-v9.rb
CHANGED
|
@@ -31,8 +31,7 @@ class UUIDv9
|
|
|
31
31
|
def self.check_version(uuid, version = nil)
|
|
32
32
|
version_digit = uuid[14]
|
|
33
33
|
variant_digit = uuid[19]
|
|
34
|
-
(!version || version_digit == version
|
|
35
|
-
(version_digit == '9' || (['1', '4'].include?(version_digit) && "89abAB".include?(variant_digit)))
|
|
34
|
+
(!version || (version_digit == version.to_s && "89abAB".include?(variant_digit)))
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
def self.is_uuid?(uuid)
|
|
@@ -42,7 +41,7 @@ class UUIDv9
|
|
|
42
41
|
def self.is_valid_uuidv9?(uuid, options)
|
|
43
42
|
is_uuid?(uuid) &&
|
|
44
43
|
(!options.key?(:checksum) || !options[:checksum] || verify_checksum(uuid)) &&
|
|
45
|
-
(!options.key?(:version) || !options[:version] || check_version(uuid))
|
|
44
|
+
(!options.key?(:version) || !options[:version] || check_version(uuid, options[:version]))
|
|
46
45
|
end
|
|
47
46
|
|
|
48
47
|
def self.random_bytes(count)
|
|
@@ -58,27 +57,39 @@ class UUIDv9
|
|
|
58
57
|
end
|
|
59
58
|
|
|
60
59
|
def self.validate_prefix(prefix)
|
|
61
|
-
raise ArgumentError, 'Prefix must be a string'
|
|
60
|
+
raise ArgumentError, 'Prefix must be a string' unless prefix.is_a?(String) # isinstance?(prefix, str)
|
|
62
61
|
raise ArgumentError, 'Prefix must be no more than 8 characters' if prefix.length > 8
|
|
63
62
|
raise ArgumentError, 'Prefix must be only hexadecimal characters' unless is_base16?(prefix)
|
|
64
63
|
end
|
|
65
64
|
|
|
65
|
+
def self.validate_suffix(suffix)
|
|
66
|
+
raise ArgumentError, 'Suffix must be a string' unless suffix.is_a?(String) # isinstance?(suffix, str)
|
|
67
|
+
raise ArgumentError, 'Suffix must be no more than 4 characters' if suffix.length > 4
|
|
68
|
+
raise ArgumentError, 'Suffix must be only hexadecimal characters' unless is_base16?(suffix)
|
|
69
|
+
end
|
|
70
|
+
|
|
66
71
|
def self.add_dashes(str)
|
|
67
72
|
"#{str[0, 8]}-#{str[8, 4]}-#{str[12, 4]}-#{str[16, 4]}-#{str[20..]}"
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
def self.generate(options = {})
|
|
71
|
-
prefix = options.fetch(:prefix, nil).to_s
|
|
76
|
+
prefix = options.fetch(:prefix, nil) # .to_s
|
|
72
77
|
timestamp = options.fetch(:timestamp, true)
|
|
73
78
|
checksum = options.fetch(:checksum, false)
|
|
74
79
|
version = options.fetch(:version, false)
|
|
75
80
|
legacy = options.fetch(:legacy, false)
|
|
81
|
+
suffix = options.fetch(:suffix, nil) # .to_s
|
|
76
82
|
|
|
77
83
|
if prefix && !prefix.empty?
|
|
78
84
|
validate_prefix(prefix)
|
|
79
85
|
prefix = prefix.downcase
|
|
80
86
|
end
|
|
81
87
|
|
|
88
|
+
if suffix && !suffix.empty?
|
|
89
|
+
validate_suffix(suffix)
|
|
90
|
+
suffix = suffix.downcase
|
|
91
|
+
end
|
|
92
|
+
|
|
82
93
|
center = case timestamp
|
|
83
94
|
when true
|
|
84
95
|
Time.now.to_i.to_s(16)
|
|
@@ -90,15 +101,15 @@ class UUIDv9
|
|
|
90
101
|
''
|
|
91
102
|
end
|
|
92
103
|
|
|
93
|
-
|
|
94
|
-
|
|
104
|
+
random_length = 32 - (prefix ? prefix.length : 0) - (suffix ? suffix.length : 0) - center.length - (checksum ? 2 : 0) - ((legacy || version) ? 2 : 0) # (legacy ? 2 : (version ? 1 : 0))
|
|
105
|
+
random = random_bytes(random_length)
|
|
95
106
|
|
|
96
|
-
joined = "#{prefix}#{center}#{suffix}"
|
|
107
|
+
joined = "#{prefix}#{center}#{random}#{suffix}"
|
|
97
108
|
|
|
98
109
|
if legacy
|
|
99
110
|
joined = "#{joined[0, 12]}#{center.length > 0 ? '1' : '4'}#{joined[12, 3]}#{random_char('89ab')}#{joined[15..]}"
|
|
100
111
|
elsif version
|
|
101
|
-
joined = "#{joined[0, 12]}9#{joined[12..]}"
|
|
112
|
+
joined = "#{joined[0, 12]}9#{joined[12, 3]}#{random_char('89ab')}#{joined[15..]}" # {joined[12..]}
|
|
102
113
|
end
|
|
103
114
|
|
|
104
115
|
joined += calc_checksum(joined) if checksum
|
data/spec/uuid-v9_spec.rb
CHANGED
|
@@ -4,7 +4,7 @@ require_relative '../lib/uuid-v9'
|
|
|
4
4
|
UUID_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/
|
|
5
5
|
UUID_V1_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-1[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/
|
|
6
6
|
UUID_V4_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/
|
|
7
|
-
UUID_V9_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-9[0-9a-fA-F]{3}-[0-9a-fA-F]{
|
|
7
|
+
UUID_V9_REGEX = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-9[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/
|
|
8
8
|
|
|
9
9
|
describe 'UUIDv9' do
|
|
10
10
|
it 'should validate as a UUID' do
|
|
@@ -109,9 +109,9 @@ describe 'UUIDv9' do
|
|
|
109
109
|
id2 = UUIDv9.generate({ timestamp: false, checksum: true })
|
|
110
110
|
id3 = UUIDv9.generate({ prefix: 'a1b2c3d4', checksum: true })
|
|
111
111
|
id4 = UUIDv9.generate({ prefix: 'a1b2c3d4', timestamp: false, checksum: true })
|
|
112
|
-
id5 = UUIDv9.generate({ checksum: true,
|
|
113
|
-
id6 = UUIDv9.generate({ checksum: true, legacy: true })
|
|
114
|
-
id7 = UUIDv9.generate({
|
|
112
|
+
id5 = UUIDv9.generate({ checksum: true, legacy: true })
|
|
113
|
+
id6 = UUIDv9.generate({ timestamp: false, checksum: true, legacy: true })
|
|
114
|
+
id7 = UUIDv9.generate({ checksum: true, version: true })
|
|
115
115
|
|
|
116
116
|
expect(UUIDv9.is_uuid?(id1)).to be true
|
|
117
117
|
expect(UUIDv9.is_uuid?('not-a-real-uuid')).to be false
|
|
@@ -119,9 +119,9 @@ describe 'UUIDv9' do
|
|
|
119
119
|
expect(UUIDv9.is_valid_uuidv9?(id2, { checksum: true })).to be true
|
|
120
120
|
expect(UUIDv9.is_valid_uuidv9?(id3, { checksum: true })).to be true
|
|
121
121
|
expect(UUIDv9.is_valid_uuidv9?(id4, { checksum: true })).to be true
|
|
122
|
-
expect(UUIDv9.is_valid_uuidv9?(id5, { checksum: true, version:
|
|
123
|
-
expect(UUIDv9.is_valid_uuidv9?(id6, { checksum: true, version:
|
|
124
|
-
expect(UUIDv9.is_valid_uuidv9?(id7, { checksum: true, version:
|
|
122
|
+
expect(UUIDv9.is_valid_uuidv9?(id5, { checksum: true, version: 1 })).to be true
|
|
123
|
+
expect(UUIDv9.is_valid_uuidv9?(id6, { checksum: true, version: 4 })).to be true
|
|
124
|
+
expect(UUIDv9.is_valid_uuidv9?(id7, { checksum: true, version: 9 })).to be true
|
|
125
125
|
expect(UUIDv9.verify_checksum(id1)).to be true
|
|
126
126
|
expect(UUIDv9.verify_checksum(id2)).to be true
|
|
127
127
|
expect(UUIDv9.verify_checksum(id3)).to be true
|
metadata
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: uuid-v9
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- JHunt
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-05-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: '"The v9 UUID supports both sequential (time-based) and non-sequential
|
|
14
14
|
(random) UUIDs with an optional prefix of up to four bytes, an optional checksum,
|
|
15
15
|
and sufficient randomness to avoid collisions. It uses the UNIX timestamp for sequential
|
|
16
|
-
UUIDs and CRC-8 for checksums.
|
|
16
|
+
UUIDs and CRC-8 for checksums. The version can be added if desired, but is omitted
|
|
17
17
|
by default."'
|
|
18
18
|
email:
|
|
19
|
-
-
|
|
19
|
+
- mail+uuidv9@jhunt.dev
|
|
20
20
|
executables: []
|
|
21
21
|
extensions: []
|
|
22
22
|
extra_rdoc_files: []
|