base58_id 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 350af1c45ca377d67a9d8223e069a2fe4d7578ba2a1428f54fa0ed9dfc3935e0
4
- data.tar.gz: bb0a090804ba8890d5d3c1a851932dd137ff64985b806c01736c1b3c9b63fe0a
3
+ metadata.gz: dd3d7a523d5b93c35c0773ca5df06767274d9116cae07e1457c3d2c09b6c8e35
4
+ data.tar.gz: 6a8e96357d3ffbfa18f90f3330b63e8415e09b213ad096fe9d03373e29fed3d6
5
5
  SHA512:
6
- metadata.gz: 39220e72e36409269d9d6d6dc74bf54a6aef3c40a45096f049190e3e89a0b68df150e6ab843deadb951b99c6e630981a29b05db18a757293845caeaea938a2b6
7
- data.tar.gz: 5450dc9d8a03b82716ba14c8bb9000654b80918200586b10c1ba1211626962d73fbb9a0f698ec8098e6c6951608373537cdb746790130034e7a816e87be4cca6
6
+ metadata.gz: d3d498e760c27a5cb75cca28ce381397c1ada700961269706c47112ed5bc8696fd9d294deb7277e30bf2a6249f1d814c8c377c655d429f7c44787be738717762
7
+ data.tar.gz: 30c46dffd66c05d49b3bb62d1d7ddbc8e4cebf79533d88edd94dd5a1335c9cb34397017788bae93458f77b874fcdf06c9c371c27597c5452775901842f9d7730
data/.rubocop.yml CHANGED
@@ -3,47 +3,50 @@ require:
3
3
  - rubocop-rspec
4
4
 
5
5
  AllCops:
6
- TargetRubyVersion: 2.7
6
+ TargetRubyVersion: 3.1
7
7
  NewCops: enable
8
8
 
9
9
  Metrics/BlockLength:
10
10
  Exclude:
11
- - 'spec/**/*.rb'
11
+ - spec/**/*.rb
12
12
  Metrics/MethodLength:
13
13
  Exclude:
14
- - 'spec/**/*.rb'
14
+ - spec/**/*.rb
15
15
 
16
- Layout/LineLength:
17
- Max: 120
16
+ Layout/ArrayAlignment:
17
+ Enabled: false
18
18
  Layout/HashAlignment:
19
19
  Enabled: false
20
+ Layout/LineLength:
21
+ Max: 120
20
22
  Layout/SpaceInsideArrayPercentLiteral:
21
23
  Enabled: false
22
- Layout/ArrayAlignment:
23
- Enabled: false
24
24
 
25
25
  Style/Documentation:
26
26
  Enabled: false
27
- Style/WhileUntilModifier:
28
- Enabled: false
29
- Style/WordArray:
30
- Enabled: false
31
- Style/SymbolArray:
32
- Enabled: false
33
27
  Style/NumericLiterals:
34
28
  Enabled: false
35
29
  Style/StringLiterals:
36
30
  Enabled: false
31
+ Style/SymbolArray:
32
+ Enabled: false
37
33
  Style/TrailingCommaInArrayLiteral:
38
34
  Enabled: false
39
35
  Style/TrailingCommaInHashLiteral:
40
36
  Enabled: false
37
+ Style/WhileUntilModifier:
38
+ Enabled: false
39
+ Style/WordArray:
40
+ Enabled: false
41
+
42
+ Naming/MethodParameterName:
43
+ Enabled: false
41
44
 
42
45
  RSpec/ExampleLength:
43
46
  Enabled: false
47
+ RSpec/LetBeforeExamples:
48
+ Enabled: false
44
49
  RSpec/MultipleExpectations:
45
50
  Enabled: false
46
51
  RSpec/NestedGroups:
47
52
  Enabled: false
48
- RSpec/LetBeforeExamples:
49
- Enabled: false
data/Gemfile CHANGED
@@ -3,3 +3,11 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
+
7
+ gem 'bundler', '~> 2.4'
8
+ gem 'pry-byebug', '~> 3.10'
9
+ gem 'rspec', '~> 3.12'
10
+ gem 'rubocop', '~> 1.56'
11
+ gem 'rubocop-performance', '~> 1.19'
12
+ gem 'rubocop-rspec', '~> 2.23'
13
+ gem 'simplecov', '~> 0.22.0'
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Base58Id
2
2
 
3
- Convert an Integer ID or a UUID String to/from Base58 String
3
+ Convert Integer ID or UUID String to/from Base58 String; Generate random Base58 String
4
4
 
5
5
  ## Install
6
6
 
@@ -15,14 +15,14 @@ Or via `Gemfile` in your project:
15
15
  ```sh
16
16
  source 'https://rubygems.org'
17
17
 
18
- gem 'base58_id', '~> 1.0'
18
+ gem 'base58_id', '~> 1.2'
19
19
  ```
20
20
 
21
21
  Or build and install the gem locally:
22
22
 
23
23
  ```sh
24
24
  gem build base58_id.gemspec
25
- gem install base58_id-1.0.0.gem
25
+ gem install base58_id-1.2.0.gem
26
26
  ```
27
27
 
28
28
  Require it in your Ruby code and the `Base58Id` class will be available:
@@ -41,7 +41,9 @@ a b c d e f g h i j k m n o p q r s t u v w x y z
41
41
  1 2 3 4 5 6 7 8 9
42
42
  ```
43
43
 
44
- ## Example
44
+ ## Examples
45
+
46
+ ### Converting
45
47
 
46
48
  ```rb
47
49
  require 'base58_id'
@@ -82,12 +84,14 @@ Base58Id::UUID_PATTERN
82
84
  # => /\A(0x)?[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}\z/i
83
85
  ```
84
86
 
85
- ### Note
87
+ ### Notes about zero
86
88
 
87
89
  As it performs an integer conversion, Base58 leading zeros (represented by `A`)
88
90
  are ignored/lost:
89
91
 
90
92
  ```rb
93
+ require 'base58_id'
94
+
91
95
  Base58Id.base58_to_integer('A') == Base58Id.base58_to_integer('AAAAAA')
92
96
  # => true
93
97
 
@@ -102,6 +106,8 @@ Base58Id.integer_to_base58(Base58Id.base58_to_integer('AAAAAAqocqGYw9LEfu4WVujMz
102
106
  And an empty Base58 String also represents zero:
103
107
 
104
108
  ```rb
109
+ require 'base58_id'
110
+
105
111
  Base58Id.base58_to_integer('')
106
112
  # => 0
107
113
 
@@ -112,6 +118,66 @@ Base58Id.base58_to_integer('') == Base58Id.base58_to_integer('A')
112
118
  # => true
113
119
  ```
114
120
 
121
+ ### Generating random Base58 number strings from Integers
122
+
123
+ ```rb
124
+ require 'base58_id'
125
+
126
+ # Using the default range [0, 2^63 - 1]
127
+ Base58Id.random_number
128
+ # => "RvHTkxcYYJ4"
129
+
130
+ # With a custom max, i.e. [0, max)
131
+ Base58Id.random_number(100) # [0, 100)
132
+ # => "BW"
133
+
134
+ # With custom ranges
135
+ Base58Id.random_number(100..1_000) # [100, 1000]
136
+ # => "L2"
137
+ Base58Id.random_number(100...1_000) # [100, 1000)
138
+ # => "Qv"
139
+ ```
140
+
141
+ Under the hood, the implementation just passes the `max_or_range` argument to
142
+ `SecureRandom.random_number` and then the result to `Base58Id.integer_to_base58`:
143
+
144
+ ```rb
145
+ require 'securerandom'
146
+ require 'base58_id'
147
+
148
+ class Base58Id
149
+ # ...
150
+
151
+ DEFAULT_RANDOM_RANGE = 0..(2**63 - 1)
152
+
153
+ # ...
154
+
155
+ def self.random_number(max_or_range = nil)
156
+ max_or_range = DEFAULT_RANDOM_RANGE if max_or_range.nil?
157
+
158
+ integer_to_base58(SecureRandom.random_number(max_or_range))
159
+ end
160
+
161
+ def self.rand(*args)
162
+ random_number(*args)
163
+ end
164
+ end
165
+ ```
166
+
167
+ ### Generating random Base58 string digits
168
+
169
+ ```rb
170
+ require 'base58_id'
171
+
172
+ # Using the default number of random digits, 10
173
+ Base58Id.random_digits
174
+ # => "EWcSDcga66"
175
+
176
+ # With a custom number of random digits
177
+ Base58Id.random_digits(42)
178
+ # => "YJn8u1UhkS9vt3YrWFPTXzMjzqFze7v2nWUbcdmnrU"
179
+ ```
180
+
115
181
  ## Tests
116
182
 
117
183
  Run tests with:
data/base58_id.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.name = 'base58_id'
7
7
  s.version = Base58Id::VERSION
8
8
  s.license = 'MIT'
9
- s.summary = 'Convert an Integer ID or a UUID String to/from Base58 String'
9
+ s.summary = 'Convert Integer ID or UUID String to/from Base58 String; Generate random Base58 String'
10
10
  s.homepage = 'https://github.com/elias19r/base58_id'
11
11
  s.author = 'Elias Rodrigues'
12
12
 
@@ -21,17 +21,9 @@ Gem::Specification.new do |s|
21
21
  'base58_id.gemspec'
22
22
  ]
23
23
 
24
- s.required_ruby_version = '>= 2.7'
24
+ s.required_ruby_version = '>= 3.1.4'
25
25
  s.metadata = {
26
26
  'source_code_uri' => "https://github.com/elias19r/base58_id/tree/v#{Base58Id::VERSION}",
27
27
  'rubygems_mfa_required' => 'true'
28
28
  }
29
-
30
- s.add_development_dependency 'bundler', '~> 2.1'
31
- s.add_development_dependency 'pry-byebug', '~> 3.9'
32
- s.add_development_dependency 'rspec', '~> 3.11'
33
- s.add_development_dependency 'rubocop', '~> 1.31'
34
- s.add_development_dependency 'rubocop-performance', '~> 1.14'
35
- s.add_development_dependency 'rubocop-rspec', '~> 2.11'
36
- s.add_development_dependency 'simplecov', '~> 0.21.0'
37
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Base58Id
4
- VERSION = '1.0.0'
4
+ VERSION = '1.2.0'
5
5
  end
data/lib/base58_id.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'securerandom'
4
+
3
5
  class Base58Id
4
6
  # Based on Base64 URL-safe alphabet but with I, O, l, 0, -, _ removed.
5
7
  ALPHABET_58 = %w[
@@ -10,11 +12,14 @@ class Base58Id
10
12
 
11
13
  ALPHABET_58_INVERT = ALPHABET_58.each_with_index.to_h
12
14
  ALPHABET_58_CHARS = ALPHABET_58.join
13
- CARET_ALPHABET_58_CHARS = "^#{ALPHABET_58_CHARS}"
15
+ CARET_ALPHABET_58_CHARS = "^#{ALPHABET_58_CHARS}".freeze
14
16
 
15
- UUID_PATTERN = /\A(0x)?[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}\z/i.freeze
17
+ UUID_PATTERN = /\A(0x)?[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}\z/i
16
18
  UUID_BYTES_FORMAT = '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x'
17
19
 
20
+ DEFAULT_RANDOM_RANGE = (0..((2**63) - 1))
21
+ DEFAULT_RANDOM_DIGITS = 10
22
+
18
23
  def self.integer_to_base58(integer)
19
24
  raise ArgumentError, 'argument must be an Integer' unless integer.is_a?(Integer)
20
25
  raise ArgumentError, 'argument must be greater than or equal to zero' if integer.negative?
@@ -70,4 +75,22 @@ class Base58Id
70
75
 
71
76
  value.match?(UUID_PATTERN)
72
77
  end
78
+
79
+ def self.random_number(max_or_range = nil)
80
+ max_or_range = DEFAULT_RANDOM_RANGE if max_or_range.nil?
81
+
82
+ integer_to_base58(SecureRandom.random_number(max_or_range))
83
+ end
84
+
85
+ def self.rand(*args)
86
+ random_number(*args)
87
+ end
88
+
89
+ def self.random_digits(n = nil)
90
+ n = DEFAULT_RANDOM_DIGITS if n.nil?
91
+
92
+ raise ArgumentError, 'argument must be an Integer' unless n.is_a?(Integer)
93
+
94
+ n.times.reduce('') { |str, _| str + ALPHABET_58[SecureRandom.random_number(58)] }
95
+ end
73
96
  end
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
  require 'base58_id'
5
5
 
6
6
  RSpec.describe Base58Id do
7
- it 'converts an Integer ID or a UUID String to/from Base58 String' do
7
+ it 'converts Integer ID or UUID String to/from Base58 String' do
8
8
  base58 = generate_base58
9
9
 
10
10
  expect(
@@ -366,6 +366,108 @@ RSpec.describe Base58Id do
366
366
  end
367
367
  end
368
368
 
369
+ describe '.random_number' do
370
+ context 'when max_or_range is not set or nil' do
371
+ it 'generates a random Base58 String using the default range' do
372
+ expected_default_random_range = 0..((2**63) - 1)
373
+
374
+ allow(SecureRandom).to receive(:random_number).with(expected_default_random_range).and_return(1000)
375
+
376
+ expect(described_class.random_number).to eq('TQ')
377
+ expect(described_class.random_number(nil)).to eq('TQ')
378
+
379
+ expect(SecureRandom).to have_received(:random_number).with(expected_default_random_range).twice
380
+ end
381
+ end
382
+
383
+ context 'when max_or_range is set and not nil' do
384
+ it 'generates a random Base58 String using the given range' do
385
+ max_or_range = 100
386
+
387
+ allow(SecureRandom).to receive(:random_number).and_return(99)
388
+
389
+ expect(described_class.random_number(max_or_range)).to eq('Bs')
390
+
391
+ expect(SecureRandom).to have_received(:random_number).with(max_or_range).once
392
+ end
393
+ end
394
+ end
395
+
396
+ describe '.rand as an alias to random_number' do
397
+ context 'when max_or_range is not set or nil' do
398
+ it 'generates a random Base58 String using the default range' do
399
+ expected_default_random_range = 0..((2**63) - 1)
400
+
401
+ allow(SecureRandom).to receive(:random_number).with(expected_default_random_range).and_return(1000)
402
+
403
+ expect(described_class.rand).to eq('TQ')
404
+ expect(described_class.rand(nil)).to eq('TQ')
405
+
406
+ expect(SecureRandom).to have_received(:random_number).with(expected_default_random_range).twice
407
+ end
408
+ end
409
+
410
+ context 'when max_or_range is set and not nil' do
411
+ it 'generates a random Base58 String using the given range' do
412
+ max_or_range = 100
413
+
414
+ allow(SecureRandom).to receive(:random_number).and_return(99)
415
+
416
+ expect(described_class.rand(max_or_range)).to eq('Bs')
417
+
418
+ expect(SecureRandom).to have_received(:random_number).with(max_or_range).once
419
+ end
420
+ end
421
+ end
422
+
423
+ describe '.random_digits' do
424
+ context 'when n is set to non-nil but not an Integer' do
425
+ it 'raises an ArgumentError' do
426
+ non_integer = Object.new
427
+
428
+ expect do
429
+ described_class.random_digits(non_integer)
430
+ end.to raise_error(ArgumentError, 'argument must be an Integer')
431
+ end
432
+ end
433
+
434
+ context 'when n is not set or nil' do
435
+ it 'generates a random string of 10 Base58 digits' do
436
+ string = described_class.random_digits
437
+
438
+ expect(string.size).to eq(10)
439
+ expect(string.count("^#{base58_chars.join}")).to eq(0)
440
+
441
+ string = described_class.random_digits(nil)
442
+
443
+ expect(string.size).to eq(10)
444
+ expect(string.count("^#{base58_chars.join}")).to eq(0)
445
+ end
446
+ end
447
+
448
+ context 'when n is zero or a negative Integer' do
449
+ it 'returns an empty string' do
450
+ string = described_class.random_digits(0)
451
+
452
+ expect(string).to eq('')
453
+
454
+ string = described_class.random_digits(generate_negative_integer)
455
+
456
+ expect(string).to eq('')
457
+ end
458
+ end
459
+
460
+ context 'when n is a positive Integer' do
461
+ it 'generates a random string of n Base58 digits' do
462
+ n = SecureRandom.random_number(1..256)
463
+ string = described_class.random_digits(n)
464
+
465
+ expect(string.size).to eq(n)
466
+ expect(string.count("^#{base58_chars.join}")).to eq(0)
467
+ end
468
+ end
469
+ end
470
+
369
471
  def generate_uuid
370
472
  SecureRandom.uuid
371
473
  end
metadata CHANGED
@@ -1,113 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: base58_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elias Rodrigues
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-30 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.1'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.1'
27
- - !ruby/object:Gem::Dependency
28
- name: pry-byebug
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '3.9'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '3.9'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '3.11'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '3.11'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.31'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.31'
69
- - !ruby/object:Gem::Dependency
70
- name: rubocop-performance
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.14'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.14'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop-rspec
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '2.11'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '2.11'
97
- - !ruby/object:Gem::Dependency
98
- name: simplecov
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: 0.21.0
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: 0.21.0
11
+ date: 2023-09-07 00:00:00.000000000 Z
12
+ dependencies: []
111
13
  description:
112
14
  email:
113
15
  executables: []
@@ -128,7 +30,7 @@ homepage: https://github.com/elias19r/base58_id
128
30
  licenses:
129
31
  - MIT
130
32
  metadata:
131
- source_code_uri: https://github.com/elias19r/base58_id/tree/v1.0.0
33
+ source_code_uri: https://github.com/elias19r/base58_id/tree/v1.2.0
132
34
  rubygems_mfa_required: 'true'
133
35
  post_install_message:
134
36
  rdoc_options: []
@@ -138,15 +40,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
40
  requirements:
139
41
  - - ">="
140
42
  - !ruby/object:Gem::Version
141
- version: '2.7'
43
+ version: 3.1.4
142
44
  required_rubygems_version: !ruby/object:Gem::Requirement
143
45
  requirements:
144
46
  - - ">="
145
47
  - !ruby/object:Gem::Version
146
48
  version: '0'
147
49
  requirements: []
148
- rubygems_version: 3.1.6
50
+ rubygems_version: 3.3.26
149
51
  signing_key:
150
52
  specification_version: 4
151
- summary: Convert an Integer ID or a UUID String to/from Base58 String
53
+ summary: Convert Integer ID or UUID String to/from Base58 String; Generate random
54
+ Base58 String
152
55
  test_files: []