tins 1.46.0 → 1.48.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
  SHA256:
3
- metadata.gz: 2d1b389e636a16cc5689bf6289e6ec7eb0242c245851fbf208d14284df4fb941
4
- data.tar.gz: f1d2211dfed516bbff6a93a94a0ac02dc2ab1aa029dd741655eac116e35d2cb6
3
+ metadata.gz: e6498c3e89e39b8351e408abc526110d4a67b7666990a100657ebcb30d626312
4
+ data.tar.gz: a131c7c65f440c56fbfd295478acb9400ccaf27e2b07e43ea8e4e6b17f89bdd9
5
5
  SHA512:
6
- metadata.gz: 408866a386efdeaf813f5c0ece264da6851ff6e4332a4838c8daa5f7e50d4689e652201ec0160f38d7e92d738d19fef9800842a7ec4e301a37458ca378a27afa
7
- data.tar.gz: 213f32c4de0712be8e495a6ffebb2f36172e77016b56831bb5106efb5b020322317b0870ed2b3ab11f88bf469c1ba60fc539c4003ce1bbf86a53a591ac667455
6
+ metadata.gz: 2905a2fa59926a1406cbbfc2ffcf5d68f536558287e852a701b61f9df0f7dfd4e9cd98e62113806cd44015ac26bb0187a55314f6a0246c97baa4ec9bb2aad848
7
+ data.tar.gz: c5bbe5c05a230bcf2127355e021ca2c90d72ccab8260543b11f8dfd9664746ffc1ea667f7cf7433e2a740e60a51aa4b199cd614e0f811f89086bca4adf0112b8
data/CHANGES.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changes
2
2
 
3
+ ## 2025-12-05 v1.48.0
4
+
5
+ - Added `Tins::Token.analyze` class method to calculate bit strength
6
+ - Moved bit calculation logic from `initialize` to `analyze` method for reuse
7
+ - Implemented bit strength calculation using formula: `length ×
8
+ log₂(alphabet_size)`
9
+ - Added comprehensive tests for the `analyze` method with various alphabets
10
+ - Support both token string and length-based analysis
11
+ - Implemented proper error handling for required parameters
12
+ - Updated `initialize` method to use the new `analyze` method
13
+ - Test cases verify bit strength for **BASE16**, **BASE64**, and **BASE32**
14
+ alphabets
15
+ - Method returns integer bit strength for cryptographic token analysis
16
+
17
+ ## 2025-11-14 v1.47.0
18
+
19
+ - Tins::GO
20
+ - Renamed `EnumerableExtension` module to `ArrayExtension` throughout the
21
+ codebase
22
+ - Updated method calls from `<<` to `push` for consistency with
23
+ `ArrayExtension`
24
+ - Modified `to_a` method implementation to return `@arguments` directly
25
+ - Updated test assertions to expect `ArrayExtension` instead of
26
+ `EnumerableExtension`
27
+ - Changed documentation comments to reflect the new `ArrayExtension` name
28
+ - Updated type checking from `EnumerableExtension` to `ArrayExtension` in
29
+ conditional logic
30
+
3
31
  ## 2025-11-10 v1.46.0
4
32
 
5
33
  - Updated `s.rubygems_version` from **3.6.9** to **3.7.2** in gemspec
data/lib/tins/go.rb CHANGED
@@ -12,15 +12,12 @@ module Tins
12
12
  # @example Multiple values for same option
13
13
  # # Handle: -f foo -f bar -f baz
14
14
  # options = Tins::GO.go('f:', ARGV)
15
- # # options['f'] will contain an EnumerableExtension collection with all
15
+ # # options['f'] will contain an ArrayExtension collection with all
16
16
  # values, see `option['f'].to_a`
17
17
  module GO
18
- # An extension module that provides Enumerable behavior for collecting
19
- # multiple values associated with the same command-line option.
20
- #
21
- # This extension enables command-line flags like `-f foo -f bar` to be
22
- # collected into a single collection that can be queried via #to_a or #each.
23
- module EnumerableExtension
18
+ # A module that provides extension methods for Strings let them double as
19
+ # arrays.
20
+ module ArrayExtension
24
21
  # Adds an element to the collection.
25
22
  #
26
23
  # This method allows for chaining operations and collects multiple
@@ -34,30 +31,11 @@ module Tins
34
31
  self
35
32
  end
36
33
 
37
- # Alias for {#push}
38
- #
39
- # Enables intuitive syntax for adding elements: `collection << item`
40
- #
41
- # @see #push
42
- alias << push
43
-
44
- # Iterates over each element in the collection.
45
- #
46
- # Implements the Enumerable interface, allowing the use of all Enumerable
47
- # methods like map, select, find, etc.
48
- #
49
- # @yield [element] Yields each element in the collection
50
- # @yieldparam element [Object] Each element in the collection
51
- # @return [self] Returns self to enable method chaining
52
- def each(&block)
53
- @arguments.each(&block)
54
- self
34
+ # The to_a method converts the object to an array.
35
+ # @return [Array] a new array containing the object's elements
36
+ def to_a
37
+ @arguments
55
38
  end
56
-
57
- # Includes the Enumerable module to provide rich iteration capabilities.
58
- #
59
- # This enables the use of methods like map, select, find, etc.
60
- include Enumerable
61
39
  end
62
40
 
63
41
  module_function
@@ -89,7 +67,7 @@ module Tins
89
67
  # @example Multiple values for same option
90
68
  # # Handle: -f foo -f bar -f baz
91
69
  # options = Tins::GO.go('f:', ARGV)
92
- # # options['f'] will contain an EnumerableExtension collection with
70
+ # # options['f'] will contain an ArrayExtension collection with
93
71
  # # all values, see options['f'].to_a
94
72
  #
95
73
  # @example Boolean flag counting
@@ -145,13 +123,13 @@ module Tins
145
123
  else
146
124
  a = p
147
125
  end
148
- if v[o].nil? || !(EnumerableExtension === v[o])
126
+ if v[o].nil? || !(ArrayExtension === v[o])
149
127
  a = a.dup
150
- a.extend EnumerableExtension
151
- a << a
128
+ a.extend ArrayExtension
129
+ a.push a
152
130
  v[o] = a
153
131
  else
154
- v[o] << a
132
+ v[o].push a
155
133
  end
156
134
  break
157
135
  elsif b.key?(o)
@@ -167,10 +145,10 @@ module Tins
167
145
  end
168
146
  r.reject! { |a| (b[p] = false) || true if /\A~(?<p>.)/ =~ a }
169
147
  v.transform_values! do |w|
170
- if w.is_a?(String) && !w.is_a?(EnumerableExtension)
148
+ if w.is_a?(String) && !w.is_a?(ArrayExtension)
171
149
  w = w.dup
172
- w.extend EnumerableExtension
173
- w << w
150
+ w.extend ArrayExtension
151
+ w.push w
174
152
  else
175
153
  w
176
154
  end
data/lib/tins/token.rb CHANGED
@@ -81,7 +81,7 @@ module Tins
81
81
  bits > 0 or raise ArgumentError, 'bits has to be positive'
82
82
  length = (Math.log(1 << bits) / Math.log(alphabet.size)).ceil
83
83
  end
84
- self.bits = (Math.log(alphabet.size ** length) / Math.log(2)).floor
84
+ self.bits = self.class.analyze(alphabet:, length:)
85
85
  token = +''
86
86
  length.times { token << alphabet[random.random_number(alphabet.size)] }
87
87
  super token
@@ -91,5 +91,22 @@ module Tins
91
91
  #
92
92
  # @return [Integer] the number of bits of entropy in the token
93
93
  attr_accessor :bits
94
+
95
+ # The analyze method calculates the bit length of a token based on its
96
+ # alphabet and length.
97
+ #
98
+ # @param alphabet [String] the alphabet used for token generation, defaults
99
+ # to Tins::Token::DEFAULT_ALPHABET
100
+ # @param token [String, nil] the token string to analyze, optional
101
+ # @param length [Integer, nil] the length of the token, optional
102
+ #
103
+ # @return [Integer] the calculated bit length of the token
104
+ #
105
+ # @raise [ArgumentError] if neither token nor length is provided, or if both are provided
106
+ def self.analyze(alphabet: Tins::Token::DEFAULT_ALPHABET, token: nil, length: nil)
107
+ token.nil? ^ length.nil? or raise ArgumentError, 'either token or length is required'
108
+ length ||= token.length
109
+ (Math.log(alphabet.size ** length) / Math.log(2)).floor
110
+ end
94
111
  end
95
112
  end
data/lib/tins/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Tins
2
2
  # Tins version
3
- VERSION = '1.46.0'
3
+ VERSION = '1.48.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
data/tests/go_test.rb CHANGED
@@ -61,8 +61,8 @@ module Tins
61
61
  def test_defaults
62
62
  r = go('bv:w:', args = %w[ -v bar ], defaults: { ?b => true, ?v => 'foo', ?w => 'baz' })
63
63
  assert_equal({ ?b => 1, 'v' => 'bar', 'w' => 'baz' }, r)
64
- assert_kind_of(Tins::GO::EnumerableExtension, r[?v])
65
- assert_kind_of(Tins::GO::EnumerableExtension, r[?w])
64
+ assert_kind_of(Tins::GO::ArrayExtension, r[?v])
65
+ assert_kind_of(Tins::GO::ArrayExtension, r[?w])
66
66
  assert_equal [], args
67
67
  r = go('bv:', args = %w[ -v bar ~b baz ], defaults: { ?b => true, ?v => 'foo' })
68
68
  assert_equal({ ?b => false, 'v' => 'bar' }, r)
data/tests/token_test.rb CHANGED
@@ -32,6 +32,37 @@ module Tins
32
32
  assert_equal 128, token.length
33
33
  assert_equal 256, token.bits
34
34
  end
35
+
36
+ def test_analyze_method
37
+ # Test with default alphabet and length
38
+ bits = Tins::Token.analyze(alphabet: Tins::Token::DEFAULT_ALPHABET, length: 22)
39
+ assert_equal 130, bits
40
+
41
+ # Test with hex alphabet and length
42
+ bits = Tins::Token.analyze(alphabet: Tins::Token::BASE16_LOWERCASE_ALPHABET, length: 32)
43
+ assert_equal 128, bits # 32 × 4 = 128 bits
44
+
45
+ # Test with base64 alphabet and length
46
+ bits = Tins::Token.analyze(alphabet: Tins::Token::BASE64_ALPHABET, length: 44)
47
+ assert_equal 264, bits # 44 × 6 = 264 bits
48
+
49
+ # Test with base32 alphabet and length
50
+ bits = Tins::Token.analyze(alphabet: Tins::Token::BASE32_ALPHABET, length: 52)
51
+ assert_equal 260, bits # 52 × 5 = 260 bits
52
+
53
+ # Test with token string instead of length
54
+ token = "5f4dcc3b5aa765d61d8327deb882cf99"
55
+ bits = Tins::Token.analyze(alphabet: Tins::Token::BASE16_LOWERCASE_ALPHABET, token: token)
56
+ assert_equal 128, bits
57
+
58
+ # Test error handling
59
+ assert_raise(ArgumentError) do
60
+ Tins::Token.analyze(alphabet: Tins::Token::DEFAULT_ALPHABET)
61
+ end
62
+
63
+ assert_raise(ArgumentError) do
64
+ Tins::Token.analyze(alphabet: Tins::Token::DEFAULT_ALPHABET, token: "test", length: 5)
65
+ end
66
+ end
35
67
  end
36
68
  end
37
-
data/tins.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: tins 1.46.0 ruby lib
2
+ # stub: tins 1.48.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "tins".freeze
6
- s.version = "1.46.0".freeze
6
+ s.version = "1.48.0".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tins
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.46.0
4
+ version: 1.48.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank