uuid7 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7b24060fdf8c607bf359e96657d4f160151726fffd5c08a34c72f2bd1043ac0d
4
+ data.tar.gz: d767c79de58c110731b009c74952a14b4ba15c42daaa8efaa761eb7a6e79ce51
5
+ SHA512:
6
+ metadata.gz: c36b7c1219d9f57c8e5dc1a5a9b8d314731daff3ac173e8225710508d86ec653a91d4f1b30461ee1955638179ba3919a3dd38df875b4400d73bf4d24fd4b1eff
7
+ data.tar.gz: fe600303dfb8942c46f2fb978f8037786d9c6214a485032d40f95249924bd2813f41c4c69c72b39292d08e85519bea836a05f8daf82350ab18e9ffca544e071d
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright © 2021 Alexander Obukhov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # UUID7
2
+
3
+ Implementation of [UUIDv7](https://github.com/uuid6/uuid6-ietf-draft) in [Ruby](https://www.ruby-lang.org/).
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'uuid7'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install uuid7
20
+
21
+ ## Usage
22
+
23
+ ```
24
+ UUID7.generate
25
+ ```
26
+
27
+ ## Performance
28
+
29
+ | Library | Iterations/second |
30
+ |--------:|----------------------:|
31
+ | UUIDv7 | 412.324k (± 0.5%) i/s |
32
+ | UUIDv4 | 483.110k (± 0.7%) i/s |
33
+ | ULID | 156.675k (± 0.7%) i/s |
34
+ | KSUID | 108.075k (± 0.9%) i/s |
35
+
36
+ See [examples](https://github.com/sprql/uuid7-ruby/examples/bench.rb)
37
+
38
+ ## Development
39
+
40
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
41
+
42
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
43
+
44
+ ## Contributing
45
+
46
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sprql/uuid7-ruby.
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UUID7
4
+ # UUIDv7 with millisecond precision layout
5
+ #
6
+ # @api private
7
+ #
8
+ # 32 bits for unix timestamp seconds
9
+ # 12 bits for millisecond precision
10
+ # 62 bits for random data
11
+ #
12
+ module Generator
13
+ VERSION_7 = 0x7000
14
+ VARIANT_RFC4122 = 0x8000
15
+
16
+ # Instantiates a new layout
17
+ #
18
+ # @example Generate a new UUID v7 layout for the millisecond and sequence count
19
+ # UUID::V7.generate(timestamp, sequence)
20
+ #
21
+ # @param timestamp [Integer] the timestamp to use for the layout
22
+ # @param seq [Integer] the sequence to use for the layout
23
+ # @return [Array<Integer>] the generated UUID v7 layout
24
+ def self.generate(timestamp, seq)
25
+ unixts = timestamp / 1_000 # seconds of unix timestamp
26
+ unixts1 = (unixts >> 4) & 0xffffffff # take 32 most significant bits of 36
27
+ unixts2 = (unixts & 0xf) << 12 # take 4 least significant bits of 36
28
+
29
+ msec = timestamp % 1_000 # milliseconds of unix timestamp
30
+ msec &= 0xfff # take 12 bits of 16
31
+
32
+ rand1, rand2, rand3 = SecureRandom.gen_random(8).unpack("nnN")
33
+ rand1 &= 0x3fff # take 14 bits of 16
34
+
35
+ # https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-01#section-4.4.4.1
36
+ #
37
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
38
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39
+ # | unixts1 |
40
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41
+ # |unixts2| msec | ver | seq |
42
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43
+ # |var| rand1 | rand2 |
44
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45
+ # | rand3 |
46
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47
+ [
48
+ unixts1,
49
+ (unixts2 | msec),
50
+ (VERSION_7 | seq),
51
+ (VARIANT_RFC4122 | rand1),
52
+ rand2,
53
+ rand3
54
+ ]
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UUID7
4
+ # Monotonic clock sequence counter
5
+ class Sequencer
6
+ def self.sequence(time)
7
+ @sequencer ||= new
8
+ @sequencer.sequence(time)
9
+ end
10
+
11
+ def initialize
12
+ @sequence = 0
13
+ @last_timestamp = 0
14
+ @mutex = Mutex.new
15
+ end
16
+
17
+ def sequence(timestamp)
18
+ @mutex.synchronize do
19
+ @sequence = if timestamp <= @last_timestamp
20
+ # TODO: handle overflow
21
+ ((@sequence + 1) & 0xfff) # 12 bits
22
+ else
23
+ 0
24
+ end
25
+ @last_timestamp = timestamp
26
+ end
27
+
28
+ [timestamp, @sequence]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module UUID7
4
+ VERSION = "0.1.0"
5
+ end
data/lib/uuid7.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "zeitwerk"
4
+ loader = Zeitwerk::Loader.for_gem
5
+ loader.inflector.inflect("uuid7" => "UUID7")
6
+ loader.setup
7
+
8
+ # UUID v7 Generator
9
+ #
10
+ module UUID7
11
+ # Generate a new UUID v7
12
+ #
13
+ # @api public
14
+ #
15
+ # @example Generate a new UUID v7 for the current timestamp
16
+ # UUID7.generate
17
+ #
18
+ # @param timestamp [Integer] the timestamp to use for UUID v7
19
+ # @return [String] the generated UUID v7 string
20
+ def self.generate(timestamp: Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond))
21
+ format("%08x-%04x-%04x-%04x-%04x%08x", *Generator.generate(*Sequencer.sequence(timestamp)))
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: uuid7
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Obukhov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-09-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: zeitwerk
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.4'
27
+ description: Implementation of UUID v7
28
+ email:
29
+ - dev@sprql.space
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - LICENSE
35
+ - README.md
36
+ - lib/uuid7.rb
37
+ - lib/uuid7/generator.rb
38
+ - lib/uuid7/sequencer.rb
39
+ - lib/uuid7/version.rb
40
+ homepage: https://github.com/sprql/uuid7-ruby
41
+ licenses:
42
+ - MIT
43
+ metadata:
44
+ homepage_uri: https://github.com/sprql/uuid7-ruby
45
+ source_code_uri: https://github.com/sprql/uuid7-ruby
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 2.5.0
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubygems_version: 3.2.15
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: UUID v7 generator
65
+ test_files: []