bitary 0.1.8 → 0.2.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: 293fa51d8a5a4b4cda3a7a283737d0695b84cfcb55414afde3b9c5bb6f9688aa
4
- data.tar.gz: 6d6541faa0fed549f62a3a1b99a293ca4422511c34527a7278ea7459683f506a
3
+ metadata.gz: 23912fd76ca478d49ef1760e9d8cdb47344b3493377d00db1d133b4131c11b6e
4
+ data.tar.gz: 49def92fa2d841953139bb16cd81779d92e8f9478b6fe8a395f0400b6344a05b
5
5
  SHA512:
6
- metadata.gz: 0a81bd80568d6b5fcb20d951f0b193f98941adafd448a896f0a68ae8c97eabecca07a34a2db1d48f4e630a64d1be165ed4efe5f370bc1aabd36f78de4a5b0e7d
7
- data.tar.gz: 94f16667978d9d9be2ccf141c6539834d7f3502397db12feee83424eb0586ace151be1ca7bee960b5bc40ba0ec6e9e12c0879c74f700d1cd86c35e21f85337bb
6
+ metadata.gz: 5faafe8215df8fc28fe075a0bf8a874b503c2346489c1327ddb94f1388c12e52cc6e0218fb25a876da9d75409e58a80f369cc71bde766c325ff4d01a02353330
7
+ data.tar.gz: 0f4b3584332df720e29be0069b42979af9471152df2e4347e5cde90972902a575bba323d7040ee133a8807b918a817d95a1d65f48032ef8f27d8d8708fed7ddc
data/.rubocop.yml CHANGED
@@ -23,3 +23,11 @@ Layout/LineLength:
23
23
  Style/MixinUsage:
24
24
  Exclude:
25
25
  - 'spec/**/*.rb'
26
+
27
+ Style/ArgumentsForwarding:
28
+ Exclude:
29
+ - /**/*.rb
30
+
31
+ Naming/BlockForwarding:
32
+ Exclude:
33
+ - /**/*.rb
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## [0.2.0] - 2024-04-14
2
+
3
+ - `Bitary#to_a` now returns a clone to prevent client code to misuse the data structure (same for `Bitary#each_byte`)
4
+ - Streamline the internal array initialization
5
+ - Enhance constructor implementation
6
+ - `Bitary#set` and `Bitary#set` are now suffixed by `!`
7
+
8
+ ## [0.1.9] - 2024-04-01
9
+
10
+ - boost perf even more by inlining mapping operations
11
+
12
+ ## [0.1.8] - 2024-04-01
13
+
14
+ - inline bit operations to regain original perf
15
+
1
16
  ## [0.1.7] - 2024-04-01
2
17
 
3
18
  - loads of refactoring and perf improvements
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Ruby-based implementation of the bit array data structure.
4
4
 
5
- It's still under development, but as of now, it implements simple and well-optimized logic allowing you to set, unset and retrieve bits (as well as some extra features, see below).
5
+ It implements simple and well-optimized logic allowing you to set, unset and retrieve bits (as well as some extra features, see below).
6
6
 
7
7
  ## Installation
8
8
 
@@ -20,23 +20,22 @@ $ gem install bitary
20
20
 
21
21
  ## Usage
22
22
 
23
- Documentation still needs to be written, but here is a breakdown
24
- of the main capabilities brought by the current bit array implementation:
23
+ Here is a breakdown of the main capabilities brought by the current implementation:
25
24
 
26
25
  ```ruby
27
26
  require 'bitary'
28
27
 
29
28
  bit_array_sz = Bitary.new(128) # give an explicit size. Defaults to 64 bits used per item
30
29
  bit_array_ar = Bitary.new(
31
- [255, 10, 20],
30
+ bytes: [255, 10, 20],
32
31
  bpi: Bitary::BYTE # 8 bits
33
32
  ) # create based on some integer array
34
33
 
35
34
  bit_array_sz.bpi # 64
36
35
  bit_array_ar.bpi # 8
37
36
 
38
- bit_array_ar.size # 128
39
- bit_array_ar.size # 24
37
+ bit_array_ar.bits # 128
38
+ bit_array_ar.bits # 24
40
39
 
41
40
  # set/unset/get
42
41
  bit_array_sz[23] = 1 # set bit at position 23 (0-indexed)
@@ -58,8 +57,8 @@ bit_array_ar.to_s # "01111111 00001010 00010100"
58
57
 
59
58
  # increase/decrease bits used per item
60
59
  bit_array_ar.bpi = Bitary::LONG # 64 bits
61
- bit_array_ar.to_a # [8_325_652]
62
- bit_array_ar.to_s # "0000000000000000000000000000000000000000011111110000101000010100"
60
+ bit_array_ar.to_a # [9154151182816509952]
61
+ bit_array_ar.to_s # "0111111100001010000101000000000000000000000000000000000000000000"
63
62
 
64
63
  bit_array_sz.bpi # 64
65
64
  bit_array_sz.to_a # [1_099_511_627_776, 0]
@@ -73,6 +72,14 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
73
72
 
74
73
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
75
74
 
75
+ Access the technical documentation in HTML format by issuing:
76
+
77
+ ```bash
78
+ $ bundle exec yardoc # or simply yardoc if bundler is not being used
79
+ ```
80
+
81
+ The YARD documentation will be generated under `/doc`.
82
+
76
83
  ## Contributing
77
84
 
78
85
  Bug reports and pull requests are welcome on GitHub at https://github.com/Patacode/bitary.
@@ -2,14 +2,14 @@
2
2
 
3
3
  class Bitary
4
4
  class Bitwarr
5
- attr_reader :bpi, :bitsize
5
+ attr_reader :bpi, :bits
6
6
 
7
- def initialize(initial_data, bpi: Bitary::LONG)
8
- @bitsize = init_bitsize(initial_data, bpi)
9
- @array = init_array(initial_data, @bitsize, bpi)
10
- @bpi = init_bpi(initial_data, bpi)
7
+ DEFAULT_INIT_CAP = Bitary::Size::LONG * 2
11
8
 
12
- self.bpi = bpi
9
+ def initialize(init_cap, bytes:, bpi:)
10
+ @array = init_array(init_cap, bytes, bpi)
11
+ @bits = init_bits(init_cap, bytes)
12
+ @bpi = bpi
13
13
  end
14
14
 
15
15
  def [](bit_index) = @array[item_index(bit_index)]
@@ -26,11 +26,14 @@ class Bitary
26
26
  end
27
27
 
28
28
  def to_s = @array.map { |item| to_binstr(item) }.join(' ')
29
+ def to_a = @array.clone
29
30
 
30
31
  def each_byte(&proc)
32
+ raise ArgumentError if proc.nil?
33
+
31
34
  @array.each do |item|
32
35
  explode_item(item, Bitary::BYTE, @bpi, &proc)
33
- end
36
+ end.clone
34
37
  end
35
38
 
36
39
  def bpi=(value)
@@ -40,30 +43,61 @@ class Bitary
40
43
  @bpi = value
41
44
  end
42
45
 
43
- def method_missing(method, *, &)
44
- @array.respond_to?(method) ? @array.send(method, *, &) : super
45
- end
46
+ private
46
47
 
47
- def respond_to_missing?(method, include_all = false)
48
- @array.respond_to?(method, include_all) || super
48
+ def init_bits(init_cap, bytes)
49
+ if init_cap.nil?
50
+ if bytes.nil?
51
+ DEFAULT_INIT_CAP
52
+ else
53
+ bytes.length * Bitary::BYTE
54
+ end
55
+ else
56
+ init_cap
57
+ end
49
58
  end
50
59
 
51
- private
60
+ def compute_nb_items(init_cap, bpi)
61
+ (init_cap / bpi.to_f).ceil
62
+ end
52
63
 
53
- def init_bpi(initial_data, bpi)
54
- initial_data.is_a?(Array) ? Bitary::BYTE : bpi
64
+ def init_array(init_cap, bytes, bpi)
65
+ if init_cap.nil?
66
+ if bytes.nil?
67
+ fill_array(0, DEFAULT_INIT_CAP, bpi)
68
+ else
69
+ adjust_array(bytes, bpi)
70
+ end
71
+ elsif bytes.nil?
72
+ fill_array(0, init_cap, bpi)
73
+ else
74
+ clone = adjust_array(bytes, bpi)
75
+ if init_cap > clone.length * bpi
76
+ adjust_array_to_cap(clone, init_cap, bpi)
77
+ end
78
+ clone
79
+ end
55
80
  end
56
81
 
57
- def init_bitsize(initial_data, bpi)
58
- initial_data.is_a?(Array) ? bpi * initial_data.length : initial_data
82
+ def fill_array(value, size, bpi)
83
+ [value] * compute_nb_items(size, bpi)
59
84
  end
60
85
 
61
- def init_array(initial_data, bitsize, bpi)
62
- if initial_data.is_a?(Array)
63
- initial_data.clone
86
+ def adjust_array(bytes, bpi)
87
+ if bpi == Bitary::BYTE
88
+ bytes.clone
64
89
  else
65
- [0] * (bitsize / bpi.to_f).ceil
90
+ increase_items_size(bytes, bpi, Bitary::BYTE)
91
+ end
92
+ end
93
+
94
+ def adjust_array_to_cap(bytes, init_cap, bpi)
95
+ target_size = compute_nb_items(init_cap, bpi)
96
+ while target_size > bytes.length
97
+ bytes << 0
98
+ target_size -= 1
66
99
  end
100
+ bytes
67
101
  end
68
102
 
69
103
  def item_index(bit_index)
@@ -74,21 +108,16 @@ class Bitary
74
108
  format("%0#{@bpi}d", item.to_s(2))
75
109
  end
76
110
 
77
- def operate_bit_at(operation, index)
78
- Factory
79
- .make("Handler::#{operation.capitalize}", self[index])
80
- .execute(
81
- index: index % @bpi,
82
- size: @bpi
83
- )
84
- end
85
-
86
- def operate_bit_at!(operation, index)
87
- self[index] = operate_bit_at(operation, index)
111
+ def update_items_size!(new_size)
112
+ @array = update_items_size(@array, new_size, @bpi)
88
113
  end
89
114
 
90
- def update_items_size!(value)
91
- value > @bpi ? increase_items_size!(value) : decrease_items_size!(value)
115
+ def update_items_size(array, new_size, bpi)
116
+ if new_size > bpi
117
+ increase_items_size(array, new_size, bpi)
118
+ else
119
+ decrease_items_size(array, new_size, bpi)
120
+ end
92
121
  end
93
122
 
94
123
  def append_bits(item, bpi, addend)
@@ -115,10 +144,6 @@ class Bitary
115
144
  res
116
145
  end
117
146
 
118
- def increase_items_size!(value)
119
- @array = increase_items_size(@array, value, @bpi)
120
- end
121
-
122
147
  def decrease_items_size(array, new_size, bpi)
123
148
  array.each_with_object([]) do |item, acc|
124
149
  explode_item(item, new_size, bpi) do |new_item|
@@ -127,10 +152,6 @@ class Bitary
127
152
  end
128
153
  end
129
154
 
130
- def decrease_items_size!(value)
131
- @array = decrease_items_size(@array, value, @bpi)
132
- end
133
-
134
155
  def explode_item(item, new_size, bpi)
135
156
  mask = (2**new_size) - 1
136
157
  (bpi / new_size).times do |i|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Bitary
4
- VERSION = '0.1.8'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/bitary.rb CHANGED
@@ -2,83 +2,205 @@
2
2
 
3
3
  require_relative 'bitary/size'
4
4
  require_relative 'bitary/version'
5
- require_relative 'bitary/factory'
6
5
  require_relative 'bitary/bitwarr'
7
- require_relative 'bitary/decorator'
8
- require_relative 'bitary/mapper'
9
6
 
7
+ # Bit array facade through client code SHOULD interact with.
10
8
  class Bitary
11
9
  include Size
12
10
 
13
- def initialize(initial_data, bpi: LONG)
14
- check_initial_data(initial_data)
11
+ # Creates a new bit array.
12
+ #
13
+ # If the initial bit capacity is not given (or `nil`), it will be deducted
14
+ # from the given byte array. In such case, if no byte array is given, it
15
+ # will default to {Bitwarr::DEFAULT_INIT_CAP}.
16
+ #
17
+ # If no byte array is given (or `nil`), the resulting bit array's items will
18
+ # all be set to 0.
19
+ #
20
+ # Note that, no check is performed on the byte array parameter to ensure
21
+ # that it has `Integer` items only, as it would considerably impact the
22
+ # data structure performance at initialization time. So be careful with
23
+ # it.
24
+ #
25
+ # @param init_cap [Integer?] an optional initial bit capacity
26
+ # @param bytes [Array<Integer>?] an optional byte array used to preset
27
+ # the bit array
28
+ # @param bpi [Integer] the number of bits used per item internally.
29
+ # Defaults to {LONG}
30
+ #
31
+ # @raise [TypeError] if **init_cap** is neither an `Integer` nor `nil`
32
+ # @raise [TypeError] if **bytes** is neither an `Array` nor `nil`
33
+ # @raise [TypeError] if **bpi** is not an `Integer`
34
+ # @raise [ArgumentError] if **init_cap** is <= 0
35
+ # @raise [ArgumentError] if **bpi** is not equal to one of the constants
36
+ # defined in {Size}
37
+ def initialize(init_cap = nil, bytes: nil, bpi: LONG)
38
+ check_init_cap(init_cap)
39
+ check_bytes(bytes)
15
40
  check_bpi(bpi)
16
41
 
17
- @bitwarr = Factory.make('Bitwarr', initial_data, bpi:)
42
+ @bitwarr = Bitwarr.new(init_cap, bytes:, bpi:)
18
43
  end
19
44
 
45
+ # Gets the bit at given index.
46
+ #
47
+ # @param index [Integer] the index of the bit to retrieve
48
+ #
49
+ # @raise [TypeError] if **index** is not an `Integer`
50
+ # @raise [IndexError] if **index** is < 0 || >= {#bits}
51
+ #
52
+ # @return [Integer] the bit at given index
20
53
  def [](index)
21
54
  check_bit_index(index)
22
55
 
23
56
  @bitwarr.bit_at(index)
24
57
  end
25
58
 
59
+ # Sets or unsets the bit at given index.
60
+ #
61
+ # The bit at given index will be set to 1 if given value is truthy but 0,
62
+ # or 0 otherwise.
63
+ #
64
+ # @param index [Integer] the index of the bit to set/unset
65
+ # @param value [Object] the object used to set/unset the bit at given index
66
+ #
67
+ # @raise [TypeError] if **index** is not an `Integer`
68
+ # @raise [IndexError] if **index** is < 0 || >= {#bits}
69
+ #
70
+ # @return [Object] the given **value**
26
71
  def []=(index, value)
27
72
  check_bit_index(index)
28
73
 
29
- case Factory.make('Mapper::ObjToBit').map(value)
74
+ case obj_to_bit(value)
30
75
  when 0 then @bitwarr.unbit_at!(index)
31
76
  else @bitwarr.bit_at!(index)
32
77
  end
33
78
  end
34
79
 
35
- def set(index)
80
+ # Sets the bit at given index to 1 (set).
81
+ #
82
+ # Specialization method of {#[]=} that is similar to `bitary[index] = 1`.
83
+ #
84
+ # @param index [Integer] the index of the bit to set
85
+ #
86
+ # @raise [TypeError] if **index** is not an `Integer`
87
+ # @raise [IndexError] if **index** is < 0 || >= {#bits}
88
+ #
89
+ # @return [Integer] 1
90
+ def set!(index)
36
91
  self[index] = 1
37
92
  end
38
93
 
39
- def unset(index)
94
+ # Sets the bit at given index to 0 (unset).
95
+ #
96
+ # Specialization method of {#[]=} that is similar to `bitary[index] = 0`.
97
+ #
98
+ # @param index [Integer] the index of the bit to unset
99
+ #
100
+ # @raise [TypeError] if **index** is not an `Integer`
101
+ # @raise [IndexError] if **index** is < 0 || >= {#bits}
102
+ #
103
+ # @return [Integer] 0
104
+ def unset!(index)
40
105
  self[index] = 0
41
106
  end
42
107
 
43
- def each_byte(&)
44
- @bitwarr.each_byte(&)
108
+ # Traverses each byte of this bit array starting with its byte at most
109
+ # significant address.
110
+ #
111
+ # @param block [Proc] the block to execute during byte traversal
112
+ #
113
+ # @yield [Integer] each byte of this bit array
114
+ #
115
+ # @return [Array<Integer>] a clone of the internal backed array (same
116
+ # as {#to_a})
117
+ def each_byte(&block)
118
+ @bitwarr.each_byte(&block)
45
119
  end
46
120
 
121
+ # Returns a clone of the internal backed array used by this bit array.
122
+ #
123
+ # @return [Array<Integer>] a clone of the internal backed array
47
124
  def to_a
48
125
  @bitwarr.to_a
49
126
  end
50
127
 
128
+ # Converts this bit array into an equivalent binary string.
129
+ #
130
+ # @return [String] the binary string representation of this bit array
51
131
  def to_s
52
132
  @bitwarr.to_s
53
133
  end
54
134
 
135
+ # Updates the number of bits used internally by each item.
136
+ #
137
+ # Depending on the use case, increasing/decreasing the number of bits used
138
+ # per item could reduce the memory footprint of this bit array.
139
+ #
140
+ # The idea is just to pay attention to potential internal fragmentation
141
+ # and find the right balance between the total number of bits you want to
142
+ # use and the number of bits that will be used by each item internally.
143
+ #
144
+ # @param value [Integer] the new bpi to be used by this bit array
145
+ #
146
+ # @raise [TypeError] if **value** is not an `Integer`
147
+ # @raise [ArgumentError] if **value** is not equal to one of the constants
148
+ # defined in {Size}
55
149
  def bpi=(value)
56
150
  check_bpi(value)
57
151
 
58
152
  @bitwarr.bpi = value
59
153
  end
60
154
 
61
- def size
62
- @bitwarr.bitsize
155
+ # Returns the total number of bits used by this bit array.
156
+ #
157
+ # @return [Integer] he total number of bits used by this bit array
158
+ def bits
159
+ @bitwarr.bits
63
160
  end
64
161
 
162
+ # Returns the number of bits used per item internally.
163
+ #
164
+ # @return [Integer] the number of bits used per item internally
65
165
  def bpi
66
166
  @bitwarr.bpi
67
167
  end
68
168
 
69
169
  private
70
170
 
71
- def check_initial_data(initial_data)
72
- raise ArgumentError unless [Array, Integer].include?(initial_data.class)
171
+ def check_init_cap(init_cap)
172
+ return if init_cap.nil?
173
+
174
+ raise TypeError unless init_cap.is_a?(Integer)
175
+ raise ArgumentError unless init_cap.positive?
176
+ end
177
+
178
+ def check_bytes(bytes)
179
+ return if bytes.nil?
180
+
181
+ raise TypeError unless bytes.is_a?(Array)
73
182
  end
74
183
 
75
184
  def check_bpi(bpi)
185
+ raise TypeError unless bpi.is_a?(Integer)
76
186
  raise ArgumentError unless [BYTE, SHORT, INT, LONG].include?(bpi)
77
187
  end
78
188
 
79
189
  def check_bit_index(bit_index)
80
- raise ArgumentError unless bit_index.is_a?(Integer)
81
- raise IndexError if bit_index.negative? || bit_index >= @bitwarr.bitsize
190
+ raise TypeError unless bit_index.is_a?(Integer)
191
+ raise IndexError if bit_index.negative? || bit_index >= bits
192
+ end
193
+
194
+ def obj_to_bit(value)
195
+ !!value ? truthy_to_bit(value) : 0
196
+ end
197
+
198
+ def truthy_to_bit(value)
199
+ value.is_a?(Integer) ? int_to_bit(value) : 1
200
+ end
201
+
202
+ def int_to_bit(value)
203
+ value.zero? ? 0 : 1
82
204
  end
83
205
 
84
206
  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.8
4
+ version: 0.2.0
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-04-01 00:00:00.000000000 Z
11
+ date: 2024-04-14 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby-based implementation of the bit array data structure
14
14
  email:
@@ -19,19 +19,13 @@ extra_rdoc_files: []
19
19
  files:
20
20
  - ".rspec"
21
21
  - ".rubocop.yml"
22
+ - ".yardopts"
22
23
  - CHANGELOG.md
23
24
  - LICENSE.txt
24
25
  - README.md
25
26
  - Rakefile
26
27
  - lib/bitary.rb
27
28
  - lib/bitary/bitwarr.rb
28
- - lib/bitary/decorator.rb
29
- - lib/bitary/decorator/single_method.rb
30
- - lib/bitary/decorator/single_method/non_nil_enforcer.rb
31
- - lib/bitary/factory.rb
32
- - lib/bitary/mapper.rb
33
- - lib/bitary/mapper/int_to_bit.rb
34
- - lib/bitary/mapper/obj_to_bit.rb
35
29
  - lib/bitary/size.rb
36
30
  - lib/bitary/version.rb
37
31
  - sig/bitary.rbs
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Bitary
4
- class Decorator
5
- class SingleMethod < Bitary::Decorator
6
- class NonNilEnforcer < Bitary::Decorator::SingleMethod
7
- protected
8
-
9
- def postcall(resp)
10
- (resp.nil? and raise TypeError) || resp
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'single_method/non_nil_enforcer'
4
-
5
- class Bitary
6
- class Decorator
7
- class SingleMethod < Bitary::Decorator
8
- def initialize(wrappee, method)
9
- super(wrappee) { |meth| meth == method }
10
- check_method(wrappee, method)
11
- end
12
-
13
- private
14
-
15
- def check_method(wrappee, method)
16
- raise ArgumentError unless method.is_a?(Symbol)
17
- raise NoMethodError unless wrappee.respond_to?(method)
18
- end
19
- end
20
- end
21
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'decorator/single_method'
4
-
5
- class Bitary
6
- class Decorator
7
- def initialize(wrappee, &proc)
8
- @wrappee = wrappee
9
- @predicate = proc || ->(_method) { true }
10
- end
11
-
12
- def method_missing(method, *, **, &)
13
- if @wrappee.respond_to?(method)
14
- if @predicate.call(method)
15
- args, kwargs = precall(method, *, **)
16
- resp = @wrappee.send(method, *args, **kwargs, &)
17
- postcall(resp)
18
- else
19
- @wrappee.send(method, *, **, &)
20
- end
21
- else
22
- super
23
- end
24
- end
25
-
26
- def respond_to_missing?(method, include_all = false)
27
- @wrappee.respond_to?(method, include_all) || super
28
- end
29
-
30
- def wrappee
31
- res = @wrappee
32
- res = res.wrappee while res.respond_to?(:wrappee)
33
- res
34
- end
35
-
36
- protected
37
-
38
- def precall(_method, *args, **kwargs)
39
- [args, kwargs]
40
- end
41
-
42
- def postcall(resp)
43
- resp
44
- end
45
- end
46
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Bitary
4
- class Factory
5
- private_class_method :new
6
- @memo = {}
7
-
8
- def self.make(name, *, **)
9
- raise ArgumentError unless name.is_a?(String)
10
-
11
- name.split('::').reduce(Bitary) do |cls, str|
12
- cls.const_get(str)
13
- end.new(*, **)
14
- end
15
-
16
- def self.make_memo(name, *args, **kwargs)
17
- raise ArgumentError unless name.is_a?(String)
18
- if @memo.key?(name.to_sym) && !args.empty? && !kwargs.empty?
19
- raise ArgumentError
20
- end
21
-
22
- @memo[name.to_sym] ||= make(name, *args, **kwargs)
23
- end
24
- end
25
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Bitary
4
- class Mapper
5
- class IntToBit < Bitary::Mapper
6
- def map(value)
7
- if value.is_a?(Integer)
8
- value.zero? ? 0 : 1
9
- else
10
- 1
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Bitary
4
- class Mapper
5
- class ObjToBit < Bitary::Mapper
6
- def map(value)
7
- case !!value
8
- when true then IntToBit.new.map(value)
9
- when false then 0
10
- end
11
- end
12
- end
13
- end
14
- end
data/lib/bitary/mapper.rb DELETED
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'mapper/int_to_bit'
4
- require_relative 'mapper/obj_to_bit'
5
-
6
- class Bitary
7
- class Mapper
8
- def self.new(*arg, **kwargs)
9
- Decorator::SingleMethod::NonNilEnforcer.new(super, :map)
10
- end
11
-
12
- def map(value)
13
- raise NotImplementedError
14
- end
15
- end
16
- end