ulid 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Gemfile.lock +6 -2
- data/Rakefile +10 -0
- data/lib/ext/time.rb +5 -0
- data/lib/ulid.rb +3 -5
- data/lib/ulid/generator.rb +24 -19
- data/lib/ulid/version.rb +1 -1
- data/spec/lib/ulid_spec.rb +42 -8
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac96b57e8fb7ee4afc17adb9070d46828667155a
|
4
|
+
data.tar.gz: f06ece64720bd8d8b5323ee69583e8ae3340562d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b28852c6c6e9ac75f331f6330338b9b49c36bc12f346e7d3cddc84f8704cfe7ced0c129c893222f9437855f97b829d1bb29573a94418c387f20afb1c8641dfde
|
7
|
+
data.tar.gz: d5d3ae42a1b1ed786ba3b87e1c9844fe6f89b41521a5e96782cda05a4beb8436c955ebb306517a1cf121f9eeb47a66822cbe91a8898653bdb5d08adfedd24335
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ulid (0.0
|
4
|
+
ulid (0.1.0)
|
5
5
|
sysrandom (>= 1.0.0, < 2.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
+
base32 (0.3.2)
|
10
11
|
byebug (9.0.5)
|
11
12
|
coderay (1.1.1)
|
12
13
|
metaclass (0.0.4)
|
@@ -23,16 +24,19 @@ GEM
|
|
23
24
|
pry (~> 0.10)
|
24
25
|
rake (10.5.0)
|
25
26
|
slop (3.6.0)
|
26
|
-
sysrandom (1.0.
|
27
|
+
sysrandom (1.0.3)
|
28
|
+
timecop (0.8.1)
|
27
29
|
|
28
30
|
PLATFORMS
|
29
31
|
ruby
|
30
32
|
|
31
33
|
DEPENDENCIES
|
34
|
+
base32
|
32
35
|
minitest
|
33
36
|
mocha
|
34
37
|
pry-byebug
|
35
38
|
rake (~> 10.0)
|
39
|
+
timecop
|
36
40
|
ulid!
|
37
41
|
|
38
42
|
BUNDLED WITH
|
data/Rakefile
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require 'rake/testtask'
|
3
|
+
require 'benchmark'
|
4
|
+
require 'ulid'
|
3
5
|
|
4
6
|
Rake::TestTask.new do |t|
|
5
7
|
t.libs += ["spec", "lib"]
|
6
8
|
t.test_files = FileList['spec/**/*_spec.rb']
|
7
9
|
end
|
10
|
+
|
11
|
+
desc "Benchmark base32 ULID generation (default 100,000 iterations)"
|
12
|
+
task :benchmark, [:iterations] do |t, args|
|
13
|
+
iterations = (args[:iterations] || 100_000).to_i
|
14
|
+
Benchmark.bm do |b|
|
15
|
+
b.report("#{iterations} iterations") { iterations.times { ULID.generate } }
|
16
|
+
end
|
17
|
+
end
|
data/lib/ext/time.rb
ADDED
data/lib/ulid.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
+
Dir.glob(File.join(File.dirname(__FILE__), "/**/*.rb")).sort.each { |f| require f }
|
2
|
+
|
1
3
|
module ULID
|
2
|
-
|
3
|
-
Generator.new.generate
|
4
|
-
end
|
4
|
+
extend Generator
|
5
5
|
end
|
6
|
-
|
7
|
-
Dir.glob(File.join(File.dirname(__FILE__), "/ulid/**/*.rb")).sort.each { |f| require f }
|
data/lib/ulid/generator.rb
CHANGED
@@ -1,36 +1,41 @@
|
|
1
1
|
require 'sysrandom'
|
2
2
|
|
3
3
|
module ULID
|
4
|
-
|
4
|
+
module Generator
|
5
5
|
ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' # Crockford's Base32
|
6
|
-
|
7
|
-
|
6
|
+
RANDOM_BYTES = 10
|
7
|
+
ENCODED_LENGTH = 26
|
8
|
+
BIT_LENGTH = 128
|
9
|
+
BITS_PER_B32_CHAR = 5
|
10
|
+
|
11
|
+
MASK = 0x1f
|
8
12
|
|
9
13
|
def generate
|
10
|
-
|
14
|
+
input = octo_word
|
15
|
+
(1..ENCODED_LENGTH).to_a.reduce("") do |s, n|
|
16
|
+
shift = BIT_LENGTH - BITS_PER_B32_CHAR * n
|
17
|
+
s + ENCODING[(input >> shift) & MASK]
|
18
|
+
end
|
11
19
|
end
|
12
20
|
|
13
|
-
|
21
|
+
def generate_bytes
|
22
|
+
time_48bit + random_bytes
|
23
|
+
end
|
14
24
|
|
15
|
-
|
16
|
-
length.times.reduce('') do |output|
|
17
|
-
mod = now % ENCODING.length
|
18
|
-
now = (now - mod) / ENCODING.length
|
25
|
+
private
|
19
26
|
|
20
|
-
|
21
|
-
|
27
|
+
def octo_word
|
28
|
+
(hi, lo) = generate_bytes.unpack("Q>Q>")
|
29
|
+
(hi << 64) | lo
|
22
30
|
end
|
23
31
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
output << ENCODING[random]
|
29
|
-
end.reverse
|
32
|
+
def time_48bit
|
33
|
+
hundred_micro_time = Time.now_100usec
|
34
|
+
[hundred_micro_time].pack("Q>")[2..-1]
|
30
35
|
end
|
31
36
|
|
32
|
-
def
|
33
|
-
(
|
37
|
+
def random_bytes
|
38
|
+
Sysrandom.random_bytes(RANDOM_BYTES)
|
34
39
|
end
|
35
40
|
end
|
36
41
|
end
|
data/lib/ulid/version.rb
CHANGED
data/spec/lib/ulid_spec.rb
CHANGED
@@ -1,17 +1,51 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'timecop'
|
3
|
+
require 'base32'
|
2
4
|
|
3
5
|
describe ULID do
|
4
|
-
|
5
|
-
|
6
|
+
describe "textual representation" do
|
7
|
+
it "ensures it has 26 chars" do
|
8
|
+
ulid = ULID.generate
|
6
9
|
|
7
|
-
|
10
|
+
ulid.length.must_equal 26
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is sortable" do
|
14
|
+
ulid_1, ulid_2 = nil
|
15
|
+
Timecop.freeze do
|
16
|
+
ulid_1 = ULID.generate
|
17
|
+
Timecop.travel Time.now + 1
|
18
|
+
ulid_2 = ULID.generate
|
19
|
+
end
|
20
|
+
assert ulid_2 > ulid_1
|
21
|
+
end
|
22
|
+
|
23
|
+
it "is valid Crockford Base32" do
|
24
|
+
Base32.table = ULID::Generator::ENCODING
|
25
|
+
ulid = ULID.generate
|
26
|
+
decoded = Base32.decode(ulid)
|
27
|
+
encoded = Base32.encode(decoded)[0...26]
|
28
|
+
assert encoded == ulid
|
29
|
+
end
|
8
30
|
end
|
9
31
|
|
10
|
-
|
11
|
-
|
12
|
-
|
32
|
+
describe "underlying binary" do
|
33
|
+
|
34
|
+
it "encodes the timestamp in the high 48 bits" do
|
35
|
+
Timecop.freeze do
|
36
|
+
now_100usec = Time.now_100usec
|
37
|
+
bytes = ULID.generate_bytes
|
38
|
+
ts = ("\x0\x0" + bytes[0...6]).unpack("Q>").first
|
39
|
+
assert ts == now_100usec
|
40
|
+
end
|
41
|
+
end
|
13
42
|
|
14
|
-
|
43
|
+
it "encodes the remaining 80 bits as random" do
|
44
|
+
random_bytes = Sysrandom.random_bytes(ULID::Generator::RANDOM_BYTES)
|
45
|
+
ULID.stubs(:random_bytes).returns(random_bytes)
|
46
|
+
bytes = ULID.generate_bytes
|
47
|
+
assert bytes[6..-1] == random_bytes
|
48
|
+
end
|
15
49
|
end
|
16
|
-
end
|
17
50
|
|
51
|
+
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: 0.0
|
4
|
+
version: 0.1.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: 2016-
|
11
|
+
date: 2016-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sysrandom
|
@@ -43,6 +43,7 @@ files:
|
|
43
43
|
- LICENSE
|
44
44
|
- README.md
|
45
45
|
- Rakefile
|
46
|
+
- lib/ext/time.rb
|
46
47
|
- lib/ulid.rb
|
47
48
|
- lib/ulid/generator.rb
|
48
49
|
- lib/ulid/version.rb
|