bitary 0.1.5 → 0.1.7

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: 0a3a73becac006670efcdd4a87b36aee0c3c9bc48c50f5cf48d68e47e1e7cad3
4
- data.tar.gz: e398cc62cdbfc33cf1f48146b59fe655f832b33d59caf8556a7898df1ef4e20d
3
+ metadata.gz: 537a58c702f90bfeade22439d4134d921df709d4d474279f29adae869ff08b0d
4
+ data.tar.gz: 90910632d7a7f40f89774a8d0ba2b1a6bbf04f5b281454ab18313359151f58b0
5
5
  SHA512:
6
- metadata.gz: 5f6d8328faf7a368daf44fc5dafedcfc4456369d2ae48b7a2e3736ad48bea686d76444b3fdd8c7c8d6b34774906e7544cf61cd78905350cfb60c94205916d832
7
- data.tar.gz: 86f6f32038489a43a9dc18613c536110af4e7aed65e228f2d763f6c472037aba0518ba382566bbe6edeec3ff76491584971c6a0bad64f4efe5dc1d68e443bca4
6
+ metadata.gz: 3c65d9bcd2b757bf0a3e2d8b25b51b6a50b239e589efba142eb3c1c7539d42ac88c311361aa934f6ecf5be06c18da53c4e3c138dda801f0c89330da7c030a745
7
+ data.tar.gz: 10169aa8520c4d2dc4ddc92e419b77b745688c14bc08214770f9da25ed35b66d66655db37ef32daa7967119514ad3cacb618d06be5bd3c69df45e2ed435e9fb1
data/.rubocop.yml CHANGED
@@ -1,5 +1,7 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
+ Exclude:
4
+ - 'bin/**/*'
3
5
 
4
6
  Style/Documentation:
5
7
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [0.1.6] - 2024-03-31
2
+
3
+ - enhance global perf by remove useless and heavy error handling
4
+
5
+ ## [0.1.5] - 2024-03-31
6
+
7
+ - enhance performance of #each_byte (4 seconds faster on average)
8
+
1
9
  ## [0.1.4] - 2024-03-31
2
10
 
3
11
  - more refactoring of Bitary class
@@ -2,132 +2,78 @@
2
2
 
3
3
  class Bitary
4
4
  class Bitwarr
5
- attr_reader :bpi
5
+ attr_reader :bpi, :bitsize
6
6
 
7
7
  def initialize(initial_data, bpi: Bitary::LONG)
8
- check_initial_data(initial_data)
9
- check_bpi(bpi)
8
+ @bitsize = init_bitsize(initial_data, bpi)
9
+ @array = init_array(initial_data, @bitsize, bpi)
10
+ @bpi = init_bpi(initial_data, bpi)
10
11
 
11
- @bpi = bpi
12
- @bitsize = init_bitsize(initial_data)
13
- @array = init_array(initial_data)
12
+ self.bpi = bpi
14
13
  end
15
14
 
16
- def method_missing(method, *, &)
17
- @array.respond_to?(method) ? @array.send(method, *, &) : super
18
- end
19
-
20
- def respond_to_missing?(method, include_all = false)
21
- @array.respond_to?(method, include_all) || super
22
- end
23
-
24
- def bitsize(bit_index = nil)
25
- if bit_index.nil?
26
- @bitsize
27
- else
28
- check_bit_index(bit_index)
29
-
30
- last_index = @array.length - 1
31
- if item_index(bit_index) == last_index
32
- @bitsize - (last_index * @bpi)
33
- else
34
- @bpi
35
- end
36
- end
37
- end
38
-
39
- def [](bit_index)
40
- @array[item_index(bit_index)]
41
- end
15
+ def [](bit_index) = @array[item_index(bit_index)]
16
+ def bit_at(index) = operate_bit_at(:get, index)
17
+ def bit_at!(index) = operate_bit_at!(:set, index)
18
+ def unbit_at!(index) = operate_bit_at!(:unset, index)
19
+ def to_s = @array.map { |item| to_binstr(item) }.join(' ')
42
20
 
43
21
  def []=(bit_index, value)
44
- raise ArgumentError unless value.is_a?(Integer)
45
-
46
22
  @array[item_index(bit_index)] = value
47
23
  end
48
24
 
49
- def relative_bit_index(bit_index)
50
- check_bit_index(bit_index)
51
-
52
- bit_index % @bpi
53
- end
54
-
55
- def item_index(bit_index)
56
- check_bit_index(bit_index)
57
-
58
- bit_index / @bpi
59
- end
60
-
61
- def bit_at(index)
62
- operate_bit_at(:get, index)
63
- end
64
-
65
- def bit_at!(index)
66
- operate_bit_at!(:set, index)
67
- end
68
-
69
- def unbit_at!(index)
70
- operate_bit_at!(:unset, index)
71
- end
72
-
73
- def each_byte
25
+ def each_byte(&proc)
74
26
  @array.each do |item|
75
- (@bpi / Bitary::BYTE).times do |i|
76
- byte = (item >> (@bpi - (Bitary::BYTE * (i + 1))))
77
- yield byte
78
- end
27
+ explode_item(item, Bitary::BYTE, @bpi, &proc)
79
28
  end
80
29
  end
81
30
 
82
- def to_s
83
- @array.map { |item| format("%0#{@bpi}d", item.to_s(2)) }.join(' ')
84
- end
85
-
86
31
  def bpi=(value)
87
- check_bpi(value)
32
+ return if value == @bpi
88
33
 
89
34
  update_items_size!(value)
90
-
91
35
  @bpi = value
92
36
  end
93
37
 
38
+ def method_missing(method, *, &)
39
+ @array.respond_to?(method) ? @array.send(method, *, &) : super
40
+ end
41
+
42
+ def respond_to_missing?(method, include_all = false)
43
+ @array.respond_to?(method, include_all) || super
44
+ end
45
+
94
46
  private
95
47
 
96
- def init_bitsize(initial_data)
97
- initial_data.is_a?(Array) ? @bpi * initial_data.length : initial_data
48
+ def init_bpi(initial_data, bpi)
49
+ initial_data.is_a?(Array) ? Bitary::BYTE : bpi
50
+ end
51
+
52
+ def init_bitsize(initial_data, bpi)
53
+ initial_data.is_a?(Array) ? bpi * initial_data.length : initial_data
98
54
  end
99
55
 
100
- def init_array(initial_data)
56
+ def init_array(initial_data, bitsize, bpi)
101
57
  if initial_data.is_a?(Array)
102
58
  initial_data.clone
103
59
  else
104
- [0] * (@bitsize / @bpi.to_f).ceil
60
+ [0] * (bitsize / bpi.to_f).ceil
105
61
  end
106
62
  end
107
63
 
108
- def check_initial_data(initial_data)
109
- raise ArgumentError unless [Array, Integer].include?(initial_data.class)
110
- end
111
-
112
- def check_bit_index(bit_index)
113
- raise ArgumentError unless bit_index.is_a?(Integer)
114
- raise IndexError if bit_index.negative? || bit_index >= @bitsize
64
+ def item_index(bit_index)
65
+ bit_index / @bpi
115
66
  end
116
67
 
117
- def check_bpi(bpi)
118
- raise ArgumentError unless [
119
- Bitary::BYTE,
120
- Bitary::SHORT,
121
- Bitary::INT,
122
- Bitary::LONG
123
- ].include?(bpi)
68
+ def to_binstr(item)
69
+ format("%0#{@bpi}d", item.to_s(2))
124
70
  end
125
71
 
126
72
  def operate_bit_at(operation, index)
127
73
  Factory
128
74
  .make("Handler::#{operation.capitalize}", self[index])
129
75
  .execute(
130
- index: relative_bit_index(index),
76
+ index: index % @bpi,
131
77
  size: @bpi
132
78
  )
133
79
  end
@@ -137,29 +83,34 @@ class Bitary
137
83
  end
138
84
 
139
85
  def update_items_size!(value)
140
- if value > @bpi
141
- increase_items_size!(value)
142
- else
143
- decrease_items_size!(value)
144
- end
86
+ value > @bpi ? increase_items_size!(value) : decrease_items_size!(value)
87
+ end
88
+
89
+ def append_bits(item, bpi, addend)
90
+ Factory.make('Handler::Append', item).execute(
91
+ offset: bpi,
92
+ value: addend
93
+ )
145
94
  end
146
95
 
147
96
  def increase_items_size(array, new_size, bpi)
148
97
  processed_bits = 0
149
- array.each_with_object([0]) do |value, acc|
150
- offset = bpi
151
- if processed_bits >= new_size
152
- offset = 0
98
+ res = array.each_with_object([0]) do |item, acc|
99
+ if processed_bits == new_size
153
100
  acc << 0
154
101
  processed_bits = 0
155
102
  end
156
103
 
157
- acc[-1] = Factory.make('Handler::Append', acc[-1]).execute(
158
- offset:,
159
- value:
160
- )
104
+ acc[-1] = append_bits(acc[-1], bpi, item)
161
105
  processed_bits += bpi
162
106
  end
107
+
108
+ while processed_bits < new_size
109
+ res[-1] = append_bits(res[-1], bpi, 0)
110
+ processed_bits += bpi
111
+ end
112
+
113
+ res
163
114
  end
164
115
 
165
116
  def increase_items_size!(value)
@@ -168,7 +119,9 @@ class Bitary
168
119
 
169
120
  def decrease_items_size(array, new_size, bpi)
170
121
  array.each_with_object([]) do |item, acc|
171
- acc.concat(explode_item(item, new_size, bpi))
122
+ explode_item(item, new_size, bpi) do |new_item|
123
+ acc << new_item
124
+ end
172
125
  end
173
126
  end
174
127
 
@@ -177,16 +130,10 @@ class Bitary
177
130
  end
178
131
 
179
132
  def explode_item(item, new_size, bpi)
180
- res = []
181
- offset = bpi
182
133
  mask = (2**new_size) - 1
183
-
184
- while offset.positive?
185
- offset -= new_size
186
- res << ((item >> offset) & mask)
134
+ (bpi / new_size).times do |i|
135
+ yield ((item >> (bpi - (new_size * (i + 1)))) & mask)
187
136
  end
188
-
189
- res
190
137
  end
191
138
  end
192
139
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'single_method/non_nil_enforcer'
4
- require_relative 'single_method/truthy_enforcer'
5
4
 
6
5
  class Bitary
7
6
  class Decorator
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'decorator/kwargs_validator'
4
3
  require_relative 'decorator/single_method'
5
4
 
6
5
  class Bitary
@@ -3,17 +3,6 @@
3
3
  class Bitary
4
4
  class Handler
5
5
  class Append < Bitary::Handler
6
- SPEC = {
7
- offset: {
8
- required: true,
9
- type: Integer
10
- },
11
- value: {
12
- required: true,
13
- type: Integer
14
- }
15
- }.freeze
16
-
17
6
  def execute(**kwargs)
18
7
  (@value << kwargs[:offset]) | kwargs[:value]
19
8
  end
@@ -3,23 +3,6 @@
3
3
  class Bitary
4
4
  class Handler
5
5
  class Get < Bitary::Handler
6
- SPEC = {
7
- index: {
8
- required: true,
9
- type: Integer,
10
- predicate: {
11
- callback: lambda do |**kwargs|
12
- kwargs[:index] >= 0 && kwargs[:index] < kwargs[:size]
13
- end,
14
- error: IndexError
15
- }
16
- },
17
- size: {
18
- required: true,
19
- type: Integer
20
- }
21
- }.freeze
22
-
23
6
  def execute(**kwargs)
24
7
  (@value >> (kwargs[:size] - kwargs[:index] - 1)) & 0x1
25
8
  end
@@ -3,23 +3,6 @@
3
3
  class Bitary
4
4
  class Handler
5
5
  class Set < Bitary::Handler
6
- SPEC = {
7
- index: {
8
- required: true,
9
- type: Integer,
10
- predicate: {
11
- callback: lambda do |**kwargs|
12
- kwargs[:index] >= 0 && kwargs[:index] < kwargs[:size]
13
- end,
14
- error: IndexError
15
- }
16
- },
17
- size: {
18
- required: true,
19
- type: Integer
20
- }
21
- }.freeze
22
-
23
6
  def execute(**kwargs)
24
7
  @value | (2**(kwargs[:size] - kwargs[:index] - 1))
25
8
  end
@@ -3,28 +3,10 @@
3
3
  class Bitary
4
4
  class Handler
5
5
  class Unset < Bitary::Handler
6
- SPEC = {
7
- index: {
8
- required: true,
9
- type: Integer,
10
- predicate: {
11
- callback: lambda do |**kwargs|
12
- kwargs[:index] >= 0 && kwargs[:index] < kwargs[:size]
13
- end,
14
- error: IndexError
15
- }
16
- },
17
- size: {
18
- required: true,
19
- type: Integer
20
- }
21
- }.freeze
22
-
23
6
  def execute(**kwargs)
24
- mask =
25
- (2**kwargs[:size]) - 1 - (2**(kwargs[:size] - kwargs[:index] - 1))
26
-
27
- @value & mask
7
+ size = kwargs[:size]
8
+ index = kwargs[:index]
9
+ @value & ((2**size) - 1 - (2**(size - index - 1)))
28
10
  end
29
11
  end
30
12
  end
@@ -7,20 +7,9 @@ require_relative 'handler/append'
7
7
 
8
8
  class Bitary
9
9
  class Handler
10
- SPEC = {}.freeze
11
-
12
10
  attr_reader :value
13
11
 
14
- def self.new(*arg, **kwargs)
15
- Decorator::SingleMethod::KwargsValidator.new(
16
- super,
17
- { execute: self::SPEC }
18
- )
19
- end
20
-
21
12
  def initialize(value)
22
- raise ArgumentError unless value.is_a?(Integer)
23
-
24
13
  @value = value
25
14
  end
26
15
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Bitary
4
- VERSION = '0.1.5'
4
+ VERSION = '0.1.7'
5
5
  end
data/lib/bitary.rb CHANGED
@@ -12,17 +12,24 @@ class Bitary
12
12
  include Size
13
13
 
14
14
  def initialize(initial_data, bpi: LONG)
15
- @internal_array = Bitwarr.new(initial_data, bpi:)
15
+ check_initial_data(initial_data)
16
+ check_bpi(bpi)
17
+
18
+ @bitwarr = Factory.make('Bitwarr', initial_data, bpi:)
16
19
  end
17
20
 
18
21
  def [](index)
19
- @internal_array.bit_at(index)
22
+ check_bit_index(index)
23
+
24
+ @bitwarr.bit_at(index)
20
25
  end
21
26
 
22
27
  def []=(index, value)
23
- case Mapper::ObjToBit.new.map(value)
24
- when 0 then @internal_array.unbit_at!(index)
25
- else @internal_array.bit_at!(index)
28
+ check_bit_index(index)
29
+
30
+ case Factory.make('Mapper::ObjToBit').map(value)
31
+ when 0 then @bitwarr.unbit_at!(index)
32
+ else @bitwarr.bit_at!(index)
26
33
  end
27
34
  end
28
35
 
@@ -35,27 +42,44 @@ class Bitary
35
42
  end
36
43
 
37
44
  def each_byte(&)
38
- @internal_array.each_byte(&)
45
+ @bitwarr.each_byte(&)
39
46
  end
40
47
 
41
48
  def to_a
42
- @internal_array.to_a
49
+ @bitwarr.to_a
43
50
  end
44
51
 
45
52
  def to_s
46
- @internal_array.to_s
53
+ @bitwarr.to_s
47
54
  end
48
55
 
49
56
  def bpi=(value)
50
- @internal_array.bpi = value
57
+ check_bpi(value)
58
+
59
+ @bitwarr.bpi = value
51
60
  end
52
61
 
53
62
  def size
54
- @internal_array.bitsize
63
+ @bitwarr.bitsize
55
64
  end
56
65
 
57
66
  def bpi
58
- @internal_array.bpi
67
+ @bitwarr.bpi
68
+ end
69
+
70
+ private
71
+
72
+ def check_initial_data(initial_data)
73
+ raise ArgumentError unless [Array, Integer].include?(initial_data.class)
74
+ end
75
+
76
+ def check_bpi(bpi)
77
+ raise ArgumentError unless [BYTE, SHORT, INT, LONG].include?(bpi)
78
+ end
79
+
80
+ def check_bit_index(bit_index)
81
+ raise ArgumentError unless bit_index.is_a?(Integer)
82
+ raise IndexError if bit_index.negative? || bit_index >= @bitwarr.bitsize
59
83
  end
60
84
 
61
85
  alias at []
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitary
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maximilien Ballesteros
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-31 00:00:00.000000000 Z
11
+ date: 2024-04-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby-based implementation of the bit array data structure
14
14
  email:
@@ -26,10 +26,8 @@ files:
26
26
  - lib/bitary.rb
27
27
  - lib/bitary/bitwarr.rb
28
28
  - lib/bitary/decorator.rb
29
- - lib/bitary/decorator/kwargs_validator.rb
30
29
  - lib/bitary/decorator/single_method.rb
31
30
  - lib/bitary/decorator/single_method/non_nil_enforcer.rb
32
- - lib/bitary/decorator/single_method/truthy_enforcer.rb
33
31
  - lib/bitary/factory.rb
34
32
  - lib/bitary/handler.rb
35
33
  - lib/bitary/handler/append.rb
@@ -1,174 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Bitary
4
- class Decorator
5
- class KwargsValidator < Bitary::Decorator
6
- SPEC_KEYS = %i[required default type predicate].freeze
7
-
8
- def initialize(wrappee, spec)
9
- super(wrappee) { |method| spec.key?(method) }
10
- @spec = check_spec(@wrappee, spec)
11
- end
12
-
13
- protected
14
-
15
- def precall(method, *, **)
16
- super(method, *, **check_kwargs(@spec, method, **))
17
- end
18
-
19
- private
20
-
21
- def check_spec(wrappee, spec)
22
- raise ArgumentError unless spec.is_a?(Hash)
23
-
24
- spec.each do |method, method_spec|
25
- check_spec_method(wrappee, method)
26
- check_spec_method_value(method_spec)
27
- end
28
- end
29
-
30
- def check_kwargs(spec, method, **kwargs)
31
- check_unexpected_user_kwargs(kwargs, spec[method])
32
- check_kwargs_against_spec(kwargs, spec[method])
33
- end
34
-
35
- def check_spec_method(wrappee, method)
36
- raise ArgumentError unless wrappee.respond_to?(method)
37
- end
38
-
39
- def check_spec_method_value(method_spec)
40
- raise ArgumentError unless method_spec.is_a?(Hash)
41
-
42
- method_spec.each_value do |arg_spec|
43
- raise ArgumentError unless arg_spec.is_a?(Hash)
44
-
45
- check_arg_spec(arg_spec)
46
- end
47
- end
48
-
49
- def check_arg_spec(arg_spec)
50
- raise ArgumentError unless arg_spec.keys.all? do |spec_key|
51
- SPEC_KEYS.include?(spec_key)
52
- end
53
-
54
- arg_spec.each do |spec_key, spec_value|
55
- check_arg_spec_entry(spec_key, spec_value)
56
- end
57
-
58
- return unless arg_spec.key?(:required) && arg_spec[:required]
59
- raise ArgumentError if arg_spec.key?(:default)
60
- end
61
-
62
- def check_arg_spec_entry(key, value)
63
- case key
64
- when :required then check_required(value)
65
- when :default then check_default(value)
66
- when :type then check_type(value)
67
- when :predicate then check_predicate(value)
68
- end
69
- end
70
-
71
- def check_required(value)
72
- raise ArgumentError unless [true, false].include?(value)
73
- end
74
-
75
- def check_default(value)
76
- # NOTHING TODO
77
- end
78
-
79
- def check_type(value)
80
- raise ArgumentError unless value.is_a?(Class)
81
- end
82
-
83
- def check_predicate(value)
84
- raise ArgumentError unless value.is_a?(Hash)
85
-
86
- check_predicate_keys(value)
87
- check_predicate_values(value)
88
- end
89
-
90
- def check_predicate_keys(value)
91
- available_keys = %i[callback error]
92
-
93
- raise ArgumentError unless value.keys.all? do |key|
94
- available_keys.include?(key)
95
- end
96
-
97
- raise KeyError unless value.key?(:callback) && value.key?(:error)
98
- end
99
-
100
- def check_predicate_values(value)
101
- raise ArgumentError unless value[:callback].is_a?(Proc)
102
- raise ArgumentError unless value[:error].is_a?(Class)
103
- raise ArgumentError unless value[:error] < Exception
104
- end
105
-
106
- def check_unexpected_user_kwargs(user_kwargs, method_spec)
107
- raise ArgumentError unless user_kwargs.keys.all? do |key|
108
- method_spec.include?(key)
109
- end
110
- end
111
-
112
- def check_kwargs_against_spec(user_kwargs, method_spec)
113
- predicates = []
114
-
115
- parsed_kwargs = method_spec.reduce({}) do |acc, entry|
116
- kwarg_name, kwarg_spec = entry
117
- loaded_spec = load_spec(kwarg_spec)
118
-
119
- validate_required(user_kwargs, loaded_spec, kwarg_name)
120
- validate_type(user_kwargs, loaded_spec, kwarg_name)
121
- predicates << loaded_spec[:predicate]
122
-
123
- acc.merge(
124
- kwarg_name => compute_value(user_kwargs, loaded_spec, kwarg_name)
125
- )
126
- end
127
-
128
- predicates.each do |predicate|
129
- validate_predicate(parsed_kwargs, predicate)
130
- end
131
-
132
- parsed_kwargs
133
- end
134
-
135
- def load_spec(kwarg_spec)
136
- {
137
- required: kwarg_spec[:required] || false,
138
- default: kwarg_spec[:default],
139
- type: kwarg_spec[:type] || Object,
140
- predicate: kwarg_spec[:predicate] || {
141
- callback: ->(_value) { true },
142
- error: ArgumentError
143
- }
144
- }
145
- end
146
-
147
- def validate_required(user_kwargs, spec, expected_key)
148
- return unless spec[:required]
149
-
150
- raise KeyError unless user_kwargs.key?(expected_key)
151
- end
152
-
153
- def validate_type(user_kwargs, spec, expected_key)
154
- return unless user_kwargs.key?(expected_key)
155
-
156
- raise ArgumentError unless user_kwargs[expected_key].is_a?(spec[:type])
157
- end
158
-
159
- def validate_predicate(parsed_kwargs, predicate)
160
- return if predicate[:callback].call(**parsed_kwargs)
161
-
162
- raise predicate[:error]
163
- end
164
-
165
- def compute_value(user_kwargs, spec, expected_key)
166
- if user_kwargs.key?(expected_key)
167
- user_kwargs[expected_key]
168
- else
169
- spec[:default]
170
- end
171
- end
172
- end
173
- end
174
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Bitary
4
- class Decorator
5
- class SingleMethod < Bitary::Decorator
6
- class TruthyEnforcer < Bitary::Decorator::SingleMethod
7
- protected
8
-
9
- def postcall(resp)
10
- resp or raise TypeError
11
- end
12
- end
13
- end
14
- end
15
- end