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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ac96b57e8fb7ee4afc17adb9070d46828667155a
4
- data.tar.gz: f06ece64720bd8d8b5323ee69583e8ae3340562d
3
+ metadata.gz: 05e031d4a39689363080536ace29cba73abcd17f
4
+ data.tar.gz: fc7499bb1b9cd0d83e59837d11870b00ad125ad5
5
5
  SHA512:
6
- metadata.gz: b28852c6c6e9ac75f331f6330338b9b49c36bc12f346e7d3cddc84f8704cfe7ced0c129c893222f9437855f97b829d1bb29573a94418c387f20afb1c8641dfde
7
- data.tar.gz: d5d3ae42a1b1ed786ba3b87e1c9844fe6f89b41521a5e96782cda05a4beb8436c955ebb306517a1cf121f9eeb47a66822cbe91a8898653bdb5d08adfedd24335
6
+ metadata.gz: 3a7616e25abef1433f0d455be7343f21ffd78dcaefc71e953bbc0e1320d1d8d7379b2e76aebf6b284d9b499840fcdce41c4c17c8cca3098f11f93e7d1bc2998b
7
+ data.tar.gz: 3e79b136fa36bf5e713676ff86ef65e2e035e1176c4a4a0d3419d0aa2b188f25f569b6ae353e266115812cac7f4d5f3206f5b5e2c8147e49b1318a16771baf88
@@ -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
@@ -0,0 +1,3 @@
1
+ # 1.0.0
2
+
3
+ - PR #110 - Fix time encoding by @dcuddeback
data/Gemfile CHANGED
@@ -3,13 +3,14 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development, :test do
6
- gem "rake", "~> 10.0"
7
- gem "pry-byebug"
6
+ gem 'pry-byebug'
7
+ gem 'rake'
8
+ gem 'rubocop'
8
9
  end
9
10
 
10
11
  group :test do
11
- gem "minitest"
12
- gem "mocha"
13
- gem "timecop"
14
- gem "base32"
12
+ gem 'base32-crockford'
13
+ gem 'minitest'
14
+ gem 'mocha'
15
+ gem 'timecop'
15
16
  end
@@ -1,43 +1,58 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ulid (0.1.0)
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
- base32 (0.3.2)
11
- byebug (9.0.5)
12
- coderay (1.1.1)
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.8.2)
15
- minitest (5.9.0)
16
- mocha (1.1.0)
15
+ method_source (0.9.0)
16
+ minitest (5.10.3)
17
+ mocha (1.3.0)
17
18
  metaclass (~> 0.0.1)
18
- pry (0.10.4)
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.8.1)
21
- slop (~> 3.4)
22
- pry-byebug (3.4.0)
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
- slop (3.6.0)
27
- sysrandom (1.0.3)
28
- timecop (0.8.1)
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 (~> 10.0)
52
+ rake
53
+ rubocop
39
54
  timecop
40
55
  ulid!
41
56
 
42
57
  BUNDLED WITH
43
- 1.12.5
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
- | 32_bit_uint_time_low |
85
+ | 32_bit_uint_time_high |
86
86
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87
- | 16_bit_uint_time_high | 16_bit_uint_random |
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 "bundler/gem_tasks"
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 += ["spec", "lib"]
7
+ t.libs += %w[spec lib]
8
8
  t.test_files = FileList['spec/**/*_spec.rb']
9
9
  end
10
10
 
11
- desc "Benchmark base32 ULID generation (default 100,000 iterations)"
12
- task :benchmark, [:iterations] do |t, args|
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 } }
@@ -1,4 +1,4 @@
1
- Dir.glob(File.join(File.dirname(__FILE__), "/**/*.rb")).sort.each { |f| require f }
1
+ Dir.glob(File.join(File.dirname(__FILE__), '/**/*.rb')).sort.each { |f| require f }
2
2
 
3
3
  module ULID
4
4
  extend Generator
@@ -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
- (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
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 octo_word
28
- (hi, lo) = generate_bytes.unpack("Q>Q>")
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
- hundred_micro_time = Time.now_100usec
34
- [hundred_micro_time].pack("Q>")[2..-1]
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
@@ -1,3 +1,3 @@
1
1
  module ULID
2
- VERSION = '0.1.0'
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -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 "textual representation" do
7
- it "ensures it has 26 chars" do
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 "is sortable" do
14
- ulid_1, ulid_2 = nil
13
+ it 'is sortable' do
14
+ ulid1, ulid2 = nil
15
15
  Timecop.freeze do
16
- ulid_1 = ULID.generate
16
+ ulid1 = ULID.generate
17
17
  Timecop.travel Time.now + 1
18
- ulid_2 = ULID.generate
18
+ ulid2 = ULID.generate
19
19
  end
20
- assert ulid_2 > ulid_1
20
+ assert ulid2 > ulid1
21
21
  end
22
22
 
23
- it "is valid Crockford Base32" do
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)[0...26]
28
- assert encoded == ulid
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
- describe "underlying binary" do
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
- it "encodes the timestamp in the high 48 bits" do
35
- Timecop.freeze do
36
- now_100usec = Time.now_100usec
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
- ts = ("\x0\x0" + bytes[0...6]).unpack("Q>").first
39
- assert ts == now_100usec
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 "encodes the remaining 80 bits as random" do
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
@@ -1,21 +1,21 @@
1
- # coding: utf-8
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 = "ulid"
7
+ spec.name = 'ulid'
8
8
  spec.version = ULID::VERSION
9
- spec.authors = ["Rafael Sales"]
10
- spec.email = ["rafaelcds@gmail.com"]
11
- spec.summary = %q{Universally Unique Lexicographically Sortable Identifier implementation for Ruby}
12
- spec.homepage = "https://github.com/rafaelsales/ulid"
13
- spec.license = "MIT"
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 = ["lib"]
18
+ spec.require_paths = ['lib']
19
19
 
20
- spec.add_dependency "sysrandom", ">= 1.0.0", "< 2.0"
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: 0.1.0
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: 2016-09-29 00:00:00.000000000 Z
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.5.1
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
@@ -1,5 +0,0 @@
1
- class Time
2
- def self.now_100usec
3
- (now.to_f * 10_000).to_i
4
- end
5
- end