ulid 0.1.0 → 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/.rubocop.yml +23 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +7 -6
- data/Gemfile.lock +33 -18
- data/README.md +2 -3
- data/Rakefile +4 -4
- data/lib/ulid.rb +1 -1
- data/lib/ulid/generator.rb +25 -14
- data/lib/ulid/version.rb +1 -1
- data/spec/lib/ulid_spec.rb +29 -22
- data/ulid.gemspec +9 -9
- metadata +5 -4
- data/lib/ext/time.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05e031d4a39689363080536ace29cba73abcd17f
|
4
|
+
data.tar.gz: fc7499bb1b9cd0d83e59837d11870b00ad125ad5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a7616e25abef1433f0d455be7343f21ffd78dcaefc71e953bbc0e1320d1d8d7379b2e76aebf6b284d9b499840fcdce41c4c17c8cca3098f11f93e7d1bc2998b
|
7
|
+
data.tar.gz: 3e79b136fa36bf5e713676ff86ef65e2e035e1176c4a4a0d3419d0aa2b188f25f569b6ae353e266115812cac7f4d5f3206f5b5e2c8147e49b1318a16771baf88
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Style/Documentation:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Style/TrailingCommaInArguments:
|
5
|
+
EnforcedStyleForMultiline: comma
|
6
|
+
|
7
|
+
Style/TrailingCommaInLiteral:
|
8
|
+
EnforcedStyleForMultiline: comma
|
9
|
+
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
BlockLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Metrics/LineLength:
|
17
|
+
Max: 120
|
18
|
+
|
19
|
+
Metrics/MethodLength:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Lint/RescueWithoutErrorClass:
|
23
|
+
Enabled: false
|
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
@@ -3,13 +3,14 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
group :development, :test do
|
6
|
-
gem
|
7
|
-
gem
|
6
|
+
gem 'pry-byebug'
|
7
|
+
gem 'rake'
|
8
|
+
gem 'rubocop'
|
8
9
|
end
|
9
10
|
|
10
11
|
group :test do
|
11
|
-
gem
|
12
|
-
gem
|
13
|
-
gem
|
14
|
-
gem
|
12
|
+
gem 'base32-crockford'
|
13
|
+
gem 'minitest'
|
14
|
+
gem 'mocha'
|
15
|
+
gem 'timecop'
|
15
16
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,43 +1,58 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ulid (
|
4
|
+
ulid (1.0.0)
|
5
5
|
sysrandom (>= 1.0.0, < 2.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
ast (2.3.0)
|
11
|
+
base32-crockford (0.1.0)
|
12
|
+
byebug (9.1.0)
|
13
|
+
coderay (1.1.2)
|
13
14
|
metaclass (0.0.4)
|
14
|
-
method_source (0.
|
15
|
-
minitest (5.
|
16
|
-
mocha (1.
|
15
|
+
method_source (0.9.0)
|
16
|
+
minitest (5.10.3)
|
17
|
+
mocha (1.3.0)
|
17
18
|
metaclass (~> 0.0.1)
|
18
|
-
|
19
|
+
parallel (1.12.0)
|
20
|
+
parser (2.4.0.0)
|
21
|
+
ast (~> 2.2)
|
22
|
+
powerpack (0.1.1)
|
23
|
+
pry (0.11.3)
|
19
24
|
coderay (~> 1.1.0)
|
20
|
-
method_source (~> 0.
|
21
|
-
|
22
|
-
|
23
|
-
byebug (~> 9.0)
|
25
|
+
method_source (~> 0.9.0)
|
26
|
+
pry-byebug (3.5.1)
|
27
|
+
byebug (~> 9.1)
|
24
28
|
pry (~> 0.10)
|
29
|
+
rainbow (2.2.2)
|
30
|
+
rake
|
25
31
|
rake (10.5.0)
|
26
|
-
|
27
|
-
|
28
|
-
|
32
|
+
rubocop (0.50.0)
|
33
|
+
parallel (~> 1.10)
|
34
|
+
parser (>= 2.3.3.1, < 3.0)
|
35
|
+
powerpack (~> 0.1)
|
36
|
+
rainbow (>= 2.2.2, < 3.0)
|
37
|
+
ruby-progressbar (~> 1.7)
|
38
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
39
|
+
ruby-progressbar (1.8.3)
|
40
|
+
sysrandom (1.0.5)
|
41
|
+
timecop (0.9.1)
|
42
|
+
unicode-display_width (1.3.0)
|
29
43
|
|
30
44
|
PLATFORMS
|
31
45
|
ruby
|
32
46
|
|
33
47
|
DEPENDENCIES
|
34
|
-
base32
|
48
|
+
base32-crockford
|
35
49
|
minitest
|
36
50
|
mocha
|
37
51
|
pry-byebug
|
38
|
-
rake
|
52
|
+
rake
|
53
|
+
rubocop
|
39
54
|
timecop
|
40
55
|
ulid!
|
41
56
|
|
42
57
|
BUNDLED WITH
|
43
|
-
1.
|
58
|
+
1.16.0
|
data/README.md
CHANGED
@@ -82,9 +82,9 @@ The components are encoded as 16 octets. Each component is encoded with the Most
|
|
82
82
|
0 1 2 3
|
83
83
|
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
|
84
84
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
85
|
-
|
|
85
|
+
| 32_bit_uint_time_high |
|
86
86
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
87
|
-
|
|
87
|
+
| 16_bit_uint_time_low | 16_bit_uint_random |
|
88
88
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
89
89
|
| 32_bit_uint_random |
|
90
90
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
@@ -111,4 +111,3 @@ bundle exec rake test
|
|
111
111
|
### Credits and references:
|
112
112
|
|
113
113
|
* https://github.com/alizain/ulid
|
114
|
-
* https://github.com/ulid-org/spec
|
data/Rakefile
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'benchmark'
|
4
4
|
require 'ulid'
|
5
5
|
|
6
6
|
Rake::TestTask.new do |t|
|
7
|
-
t.libs += [
|
7
|
+
t.libs += %w[spec lib]
|
8
8
|
t.test_files = FileList['spec/**/*_spec.rb']
|
9
9
|
end
|
10
10
|
|
11
|
-
desc
|
12
|
-
task :benchmark, [:iterations] do |
|
11
|
+
desc 'Benchmark base32 ULID generation (default 100,000 iterations)'
|
12
|
+
task :benchmark, [:iterations] do |_t, args|
|
13
13
|
iterations = (args[:iterations] || 100_000).to_i
|
14
14
|
Benchmark.bm do |b|
|
15
15
|
b.report("#{iterations} iterations") { iterations.times { ULID.generate } }
|
data/lib/ulid.rb
CHANGED
data/lib/ulid/generator.rb
CHANGED
@@ -2,7 +2,7 @@ require 'sysrandom'
|
|
2
2
|
|
3
3
|
module ULID
|
4
4
|
module Generator
|
5
|
-
ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' # Crockford's Base32
|
5
|
+
ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'.freeze # Crockford's Base32
|
6
6
|
RANDOM_BYTES = 10
|
7
7
|
ENCODED_LENGTH = 26
|
8
8
|
BIT_LENGTH = 128
|
@@ -10,28 +10,39 @@ module ULID
|
|
10
10
|
|
11
11
|
MASK = 0x1f
|
12
12
|
|
13
|
-
def generate
|
14
|
-
input = octo_word
|
15
|
-
|
16
|
-
|
17
|
-
s + ENCODING[(input >> shift) & MASK]
|
18
|
-
end
|
13
|
+
def generate(time = Time.now)
|
14
|
+
input = octo_word(time)
|
15
|
+
|
16
|
+
encode(input, ENCODED_LENGTH)
|
19
17
|
end
|
20
18
|
|
21
|
-
def generate_bytes
|
22
|
-
time_48bit + random_bytes
|
19
|
+
def generate_bytes(time = Time.now)
|
20
|
+
time_48bit(time) + random_bytes
|
23
21
|
end
|
24
22
|
|
25
23
|
private
|
26
24
|
|
27
|
-
def
|
28
|
-
|
25
|
+
def encode(n, length)
|
26
|
+
e = '0' * length
|
27
|
+
i = length - 1
|
28
|
+
|
29
|
+
while n > 0
|
30
|
+
e[i] = ENCODING[n & MASK]
|
31
|
+
n >>= 5
|
32
|
+
i -= 1
|
33
|
+
end
|
34
|
+
|
35
|
+
e
|
36
|
+
end
|
37
|
+
|
38
|
+
def octo_word(time = Time.now)
|
39
|
+
(hi, lo) = generate_bytes(time).unpack('Q>Q>')
|
29
40
|
(hi << 64) | lo
|
30
41
|
end
|
31
42
|
|
32
|
-
def time_48bit
|
33
|
-
|
34
|
-
[
|
43
|
+
def time_48bit(time = Time.now)
|
44
|
+
time_ms = (time.to_f * 1000).to_i
|
45
|
+
[time_ms].pack('Q>')[2..-1]
|
35
46
|
end
|
36
47
|
|
37
48
|
def random_bytes
|
data/lib/ulid/version.rb
CHANGED
data/spec/lib/ulid_spec.rb
CHANGED
@@ -1,51 +1,58 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'timecop'
|
3
|
-
require 'base32'
|
3
|
+
require 'base32/crockford'
|
4
4
|
|
5
5
|
describe ULID do
|
6
|
-
describe
|
7
|
-
it
|
6
|
+
describe 'textual representation' do
|
7
|
+
it 'ensures it has 26 chars' do
|
8
8
|
ulid = ULID.generate
|
9
9
|
|
10
10
|
ulid.length.must_equal 26
|
11
11
|
end
|
12
12
|
|
13
|
-
it
|
14
|
-
|
13
|
+
it 'is sortable' do
|
14
|
+
ulid1, ulid2 = nil
|
15
15
|
Timecop.freeze do
|
16
|
-
|
16
|
+
ulid1 = ULID.generate
|
17
17
|
Timecop.travel Time.now + 1
|
18
|
-
|
18
|
+
ulid2 = ULID.generate
|
19
19
|
end
|
20
|
-
assert
|
20
|
+
assert ulid2 > ulid1
|
21
21
|
end
|
22
22
|
|
23
|
-
it
|
24
|
-
Base32.table = ULID::Generator::ENCODING
|
23
|
+
it 'is valid Crockford Base32' do
|
25
24
|
ulid = ULID.generate
|
26
|
-
decoded = Base32.decode(ulid)
|
27
|
-
encoded = Base32.encode(decoded)
|
28
|
-
|
25
|
+
decoded = Base32::Crockford.decode(ulid)
|
26
|
+
encoded = Base32::Crockford.encode(decoded, length: 26)
|
27
|
+
assert_equal ulid, encoded
|
29
28
|
end
|
30
|
-
end
|
31
29
|
|
32
|
-
|
30
|
+
it 'encodes the timestamp in the first 10 characters' do
|
31
|
+
# test case taken from original ulid README:
|
32
|
+
# https://github.com/alizain/ulid#seed-time
|
33
|
+
Timecop.freeze(Time.at(1_469_918_176.385)) do
|
34
|
+
ulid = ULID.generate(Time.at(1_469_918_176.385))
|
35
|
+
assert_equal '01ARYZ6S41', ulid[0...10]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
33
39
|
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
describe 'underlying binary' do
|
41
|
+
it 'encodes the timestamp in the high 48 bits' do
|
42
|
+
input_time = Time.now.utc
|
43
|
+
Timecop.freeze(input_time) do
|
37
44
|
bytes = ULID.generate_bytes
|
38
|
-
|
39
|
-
|
45
|
+
(time_ms,) = "\x0\x0#{bytes[0...6]}".unpack('Q>')
|
46
|
+
encoded_time = Time.at(time_ms / 1000.0).utc
|
47
|
+
assert_in_delta input_time, encoded_time, 0.001
|
40
48
|
end
|
41
49
|
end
|
42
50
|
|
43
|
-
it
|
51
|
+
it 'encodes the remaining 80 bits as random' do
|
44
52
|
random_bytes = Sysrandom.random_bytes(ULID::Generator::RANDOM_BYTES)
|
45
53
|
ULID.stubs(:random_bytes).returns(random_bytes)
|
46
54
|
bytes = ULID.generate_bytes
|
47
55
|
assert bytes[6..-1] == random_bytes
|
48
56
|
end
|
49
57
|
end
|
50
|
-
|
51
58
|
end
|
data/ulid.gemspec
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
4
|
require 'ulid/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'ulid'
|
8
8
|
spec.version = ULID::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.homepage =
|
13
|
-
spec.license =
|
9
|
+
spec.authors = ['Rafael Sales']
|
10
|
+
spec.email = ['rafaelcds@gmail.com']
|
11
|
+
spec.summary = 'Universally Unique Lexicographically Sortable Identifier implementation for Ruby'
|
12
|
+
spec.homepage = 'https://github.com/rafaelsales/ulid'
|
13
|
+
spec.license = 'MIT'
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
-
spec.require_paths = [
|
18
|
+
spec.require_paths = ['lib']
|
19
19
|
|
20
|
-
spec.add_dependency
|
20
|
+
spec.add_dependency 'sysrandom', '>= 1.0.0', '< 2.0'
|
21
21
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ulid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rafael Sales
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sysrandom
|
@@ -38,12 +38,13 @@ extensions: []
|
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
40
|
- ".gitignore"
|
41
|
+
- ".rubocop.yml"
|
42
|
+
- CHANGELOG.md
|
41
43
|
- Gemfile
|
42
44
|
- Gemfile.lock
|
43
45
|
- LICENSE
|
44
46
|
- README.md
|
45
47
|
- Rakefile
|
46
|
-
- lib/ext/time.rb
|
47
48
|
- lib/ulid.rb
|
48
49
|
- lib/ulid/generator.rb
|
49
50
|
- lib/ulid/version.rb
|
@@ -71,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
72
|
version: '0'
|
72
73
|
requirements: []
|
73
74
|
rubyforge_project:
|
74
|
-
rubygems_version: 2.
|
75
|
+
rubygems_version: 2.6.8
|
75
76
|
signing_key:
|
76
77
|
specification_version: 4
|
77
78
|
summary: Universally Unique Lexicographically Sortable Identifier implementation for
|