bin_struct 0.5.0 → 0.5.1

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: b6e644878c67b11f8006b130b0964a2349f0aa66645f2706cb97a20bf1ec6b77
4
- data.tar.gz: 0bbf06e91de1bc410888f9c0e79f8caa0b7bb7f7082b5c775186c41c4a3d04db
3
+ metadata.gz: f7d87b0168273fd5ed8cb81c89ecbc1726d93544bf70d57467490d5732033ebc
4
+ data.tar.gz: 5f14f873d4d45ee090b81033a952d62e3673334444b61a62825c9925d9574af6
5
5
  SHA512:
6
- metadata.gz: c1bd8b95ce395af08b53ea41385929e9d06490d4ab21588dd46e02d8ba1d66207879174ec2f3a98400667446956042b581a032d93e8b9b97cc2d8448b20ced44
7
- data.tar.gz: b81c04e4ddcf9a4bbe3af1b36735a5221014f69f43ef5d11c166d33e595aa989f0feb436ed2ba5547f42372c636383a5196c302f54548d0525d49057576f2467
6
+ metadata.gz: f82248767c36240d4774ebab9cffb25c05efb328981a068349256442034f5ff510abc72693398b6e320b9ab8f59ed3b9d87e8b6d9f44f30884ff62afb960c531
7
+ data.tar.gz: 80a67a76677dbad046463541b7e9d8208033243c9a0f4633d48e25e1375adc0085f261d50e3b53fdc34b2c89152652b30f13d3432ce59c5ebe0f3918bf071b4a
data/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4
4
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
5
5
 
6
+ ## 0.5.1 - 2025-04-21
7
+
8
+ ### Fixed
9
+
10
+ - Struct defined with bit attributes could not be cloned.
11
+
6
12
  ## 0.5.0 - 2025-02-17
7
13
 
8
14
  ### Added
@@ -32,8 +32,6 @@ module BinStruct
32
32
 
33
33
  # @return [Integer] width in bits of bit attribute
34
34
  attr_reader :width
35
- # @return [::Array[Symbol]]
36
- attr_reader :bit_methods
37
35
 
38
36
  # @private
39
37
  Parameters = Struct.new(:width, :fields, :int)
@@ -45,6 +43,10 @@ module BinStruct
45
43
  # @return [Parameters]
46
44
  attr_reader :parameters
47
45
 
46
+ # @private
47
+ # @return [::Array[Symbol]]
48
+ attr_reader :bit_methods
49
+
48
50
  # Create a new {BitAttr} subclass with specified parameters
49
51
  # @param [Integer] width size of bitfields in bits. Must be a size of an {Int} (8, 16, 24, 32 or 64 bits).
50
52
  # @param [:big,:little,:native] endian endianess of bit attribute as an integer
@@ -64,10 +66,7 @@ module BinStruct
64
66
  total_size = fields.reduce(0) { |acc, ary| acc + ary.last }
65
67
  raise ArgumentError, "sum of bitfield sizes is not equal to #{width}" unless total_size == width
66
68
 
67
- cache[hsh] = Class.new(self) do
68
- int_klass = BinStruct.const_get("Int#{width}")
69
- @parameters = Parameters.new(width, fields, int_klass.new(endian: endian)).freeze
70
- end
69
+ cache[hsh] = create_subclass(width, endian, fields.dup.freeze)
71
70
  end
72
71
 
73
72
  private
@@ -84,6 +83,39 @@ module BinStruct
84
83
  def compute_hash(*params)
85
84
  Digest::MD5.digest(Marshal.dump(params))
86
85
  end
86
+
87
+ def create_subclass(width, endian, fields)
88
+ klass = Class.new(self) do
89
+ int_klass = BinStruct.const_get("Int#{width}")
90
+ @parameters = Parameters.new(width, fields, int_klass.new(endian: endian)).freeze
91
+ @bit_methods = []
92
+ end
93
+
94
+ define_methods(klass, fields)
95
+ klass
96
+ end
97
+
98
+ # @param [Class] {BitAttr} subclass
99
+ # @param [Hash{Symbol => Integer}] fields
100
+ # @return [void]
101
+ def define_methods(klass, fields)
102
+ define_str = +''
103
+ fields.each do |name, size|
104
+ define_str << "def #{name}; @data[#{name.inspect}]; end\n"
105
+ klass.bit_methods << name
106
+ klass.bit_methods << :"#{name}="
107
+
108
+ if size == 1
109
+ define_str << "def #{name}?; @data[#{name.inspect}] != 0; end\n"
110
+ klass.bit_methods << :"#{name}?"
111
+ define_str << "def #{name}=(val); v = case val when TrueClass; 1 when FalseClass; 0 else val end; " \
112
+ "@data[#{name.inspect}] = v; end\n"
113
+ else
114
+ define_str << "def #{name}=(val); @data[#{name.inspect}] = val; end\n"
115
+ end
116
+ end
117
+ klass.class_eval(define_str)
118
+ end
87
119
  end
88
120
 
89
121
  # Initialize bit attribute
@@ -101,13 +133,21 @@ module BinStruct
101
133
  @data = {}
102
134
  @bit_methods = []
103
135
 
104
- parameters.fields.each do |name, size|
136
+ parameters.fields.each_key do |name|
105
137
  @data[name] = opts[name] || 0
106
- define_methods(name, size)
107
138
  end
108
139
  @bit_methods.freeze
109
140
  end
110
141
 
142
+ def initialize_copy(_other)
143
+ @data = @data.dup
144
+ end
145
+
146
+ # @return [::Array[Symbol]]
147
+ def bit_methods
148
+ self.class.bit_methods
149
+ end
150
+
111
151
  # Get type name
112
152
  # @return [::String]
113
153
  def type_name
@@ -175,24 +215,5 @@ module BinStruct
175
215
 
176
216
  self
177
217
  end
178
-
179
- # @param [Symbol] name
180
- # @return [void]
181
- def define_methods(name, size)
182
- instance_eval "def #{name}; @data[#{name.inspect}]; end\n", __FILE__, __LINE__ # def name; data[:name]; end
183
- bit_methods << name
184
- bit_methods << :"#{name}="
185
-
186
- # rubocop:disable Style/DocumentDynamicEvalDefinition
187
- if size == 1
188
- instance_eval "def #{name}?; @data[#{name.inspect}] != 0; end\n", __FILE__, __LINE__
189
- instance_eval "def #{name}=(val); v = case val when TrueClass; 1 when FalseClass; 0 else val end; " \
190
- "@data[#{name.inspect}] = v; end", __FILE__, __LINE__ - 1
191
- bit_methods << :"#{name}?"
192
- else
193
- instance_eval "def #{name}=(val); @data[#{name.inspect}] = val; end", __FILE__, __LINE__
194
- end
195
- # rubocop:enable Style/DocumentDynamicEvalDefinition
196
- end
197
218
  end
198
219
  end
@@ -268,13 +268,15 @@ module BinStruct
268
268
  bit_attr_klass = BitAttr.create(width: width, endian: endian, **fields)
269
269
  define_attr(attr, bit_attr_klass, default: default)
270
270
  fields.each_key { |field| register_bit_attr_field(attr, field) }
271
+ define_str = +''
271
272
  bit_attr_klass.new.bit_methods.each do |meth|
272
- if meth.to_s.end_with?('=')
273
- define_method(meth) { |value| self[attr].send(meth, value) }
274
- else
275
- define_method(meth) { self[attr].send(meth) }
276
- end
273
+ define_str << if meth.to_s.end_with?('=')
274
+ "def #{meth}(value); self[:#{attr}].#{meth}(value); end\n"
275
+ else
276
+ "def #{meth}; self[:#{attr}].#{meth}; end\n"
277
+ end
277
278
  end
279
+ class_eval(define_str)
278
280
  end
279
281
 
280
282
  # Define a bit attribute, before another attribute
@@ -8,5 +8,5 @@
8
8
 
9
9
  module BinStruct
10
10
  # BinStruct version
11
- VERSION = '0.5.0'
11
+ VERSION = '0.5.1'
12
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bin_struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - LemonTree55
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-17 00:00:00.000000000 Z
11
+ date: 2025-04-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'BinStruct is a binary dissector and generator. It eases manipulating
14
14
  complex binary data.