bitary 0.1.5 → 0.1.7

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: 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