bin_struct 0.5.2 → 0.5.3

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: 18e365efdb982166cda39456fd9b1afb6c9a241aae1ed64df6a3121c0f67cee2
4
- data.tar.gz: bb98e9835da23a370375d5879e6210015dbae8d9a0cf1676aee22fac2ab804fb
3
+ metadata.gz: d31367b8cbffd8fd978aab672f493f0d2e1fc099daf19a4cc596ff54f862c43a
4
+ data.tar.gz: dbd457e23e12953f89576c4dc2790b56486d0da3c37dbdc92d3e1103710995c4
5
5
  SHA512:
6
- metadata.gz: 01f96e0383d3f826f6746f8a191f32edde871470015da56dcdc0a3871aaeee357a66b846ae27f4c1a8ad35aa82207333d96e12bba00a02bbc0c5a3f52cc73f5a
7
- data.tar.gz: 8d5a49b7702dae5b8e23617f11c03157c20eefc07857a156ee4c93df8e7429dcbb3ebbd6684230dd42e9b4ab149b3964a5e9933cda4bf4c5a1c95036346a460b
6
+ metadata.gz: 801697a0c78ee32edc0925e5bcf46efed24b91ae5404dd633c98a27dea80db4983c2634a1743983d8a6e310d73937b2c5a0aaa4808f8088d3fb5a5052577fcc8
7
+ data.tar.gz: 1a046d96ed17805e20928e60cceb8607d34055a7cd4b67bf4cacea3d80ded1d9c2044be480d21f4e21b92fe16b57a1653a21897b36d66244c440dfe0e1106bda
data/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
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.3 - 2026-01-07
7
+
8
+ ### Fixed
9
+
10
+ - Ensure `BitAttr` internal integer is always up to date.
11
+ - Clean up yard doc.
12
+
13
+ ### Removed
14
+
15
+ - Remove support for Ruby < 3.1
16
+
6
17
  ## 0.5.2 - 2025-08-14
7
18
 
8
19
  ### Fixed
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/bin_struct.svg)](https://badge.fury.io/rb/bin_struct)
2
- [![Specs](https://github.com/lemontree55/bin_struct/actions/workflows/main.yml/badge.svg)](https://github.com/lemontree55/bin_struct/actions/workflows/main.yml)
2
+ [![status-badge](https://ci.codeberg.org/api/badges/15063/status.svg)](https://ci.codeberg.org/repos/15063)
3
3
 
4
4
  # BinStruct
5
5
 
6
- BinStruct provides a simple way to create and dissect binary data. It is an extraction from [PacketGen](https://github.com/lemontree55/packetgen) 3.x Fields.
6
+ BinStruct provides a simple way to create and dissect binary data. It is an extraction from [PacketGen](https://codeberg.org/lemontree55/packetgen) 3.x Fields.
7
7
 
8
8
  ## Installation
9
9
 
@@ -74,12 +74,13 @@ module BinStruct
74
74
  # rubocop:disable Metrics/ParameterLists
75
75
 
76
76
  # Generate a TLV class
77
- # @param [Class] type_class Class to use for +type+
78
- # @param [Class] length_class Class to use for +length+
79
- # @param [Class] value_class Class to use for +value+
80
- # @param [::String] attr_order gives attribute order. Each character in [T,L,V] MUST be present once,
77
+ # @param type_class [Class] Class to use for +type+
78
+ # @param length_class [Class] Class to use for +length+
79
+ # @param value_class [Class] Class to use for +value+
80
+ # @param aliases [Hash{Symbol=>Symbol}] define aliases with key an alias to an existing accessor (the value)
81
+ # @param attr_order [::String] gives attribute order. Each character in [T,L,V] MUST be present once,
81
82
  # in the desired order.
82
- # @param [::String] attr_in_length give attributes to compute length on.
83
+ # @param attr_in_length [::String] give attributes to compute length on.
83
84
  # @return [Class]
84
85
  # @raise [Error] Called on {AbstractTLV} subclass
85
86
  def create(type_class: Int8Enum, length_class: Int8, value_class: String,
@@ -109,7 +110,7 @@ module BinStruct
109
110
  # rubocop:enable Metrics/ParameterLists
110
111
 
111
112
  # On inheritage, copy aliases and attr_in_length
112
- # @param [Class] klass inheriting class
113
+ # @param klass [Class] inheriting class
113
114
  # @return [void]
114
115
  # @since 0.4.0
115
116
  # @author LemonTree55
@@ -126,9 +127,10 @@ module BinStruct
126
127
  end
127
128
 
128
129
  # Derive a new TLV class from an existing one
129
- # @param [Class,nil] type_class New class to use for +type+. Unchanged if +nil+.
130
- # @param [Class,nil] length_class New class to use for +length+. Unchanged if +nil+.
131
- # @param [Class,nil] value_class New class to use for +value+. Unchanged if +nil+.
130
+ # @param type_class [Class,nil] New class to use for +type+. Unchanged if +nil+.
131
+ # @param length_class [Class,nil] New class to use for +length+. Unchanged if +nil+.
132
+ # @param value_class [Class,nil] New class to use for +value+. Unchanged if +nil+.
133
+ # @param aliases [Hash{Symbol=>Symbol}] define aliases with key an alias to an existing accessor (the value)
132
134
  # @return [Class]
133
135
  # @raise [Error] Called on {AbstractTLV} class
134
136
  # @since 0.4.0
@@ -167,7 +169,7 @@ module BinStruct
167
169
 
168
170
  # @abstract Should only be called on real TLV classes, created by {.create}.
169
171
  # Set enum hash for {#type} attribute.
170
- # @param [Hash{::String, Symbol => Integer}] hsh enum hash
172
+ # @param hsh [Hash{::String, Symbol => Integer}] enum hash
171
173
  # @return [void]
172
174
  def define_type_enum(hsh)
173
175
  attr_defs[:type][:options][:enum].clear
@@ -176,7 +178,7 @@ module BinStruct
176
178
 
177
179
  # @abstract Should only be called on real TLV classes, created by {.create}.
178
180
  # Set default value for {#type} attribute.
179
- # @param [Integer,::String,Symbol,nil] default default value from +hsh+ for type
181
+ # @param default [Integer,::String,Symbol,nil] default value from +hsh+ for type
180
182
  # @return [void]
181
183
  def define_type_default(default)
182
184
  attr_defs[:type][:default] = default
@@ -184,12 +186,19 @@ module BinStruct
184
186
 
185
187
  private
186
188
 
189
+ # Check +attr_in_length+ and raise if it contains unknown characters
190
+ # @param attr_in_length [::String]
191
+ # @return [void]
192
+ # @raise [Error] +attr_in_length+ contains unsupported characters
187
193
  def check_attr_in_length(attr_in_length)
188
194
  return if /^[TLV]{1,3}$/.match?(attr_in_length)
189
195
 
190
- raise 'attr_in_length must only contain T, L and/or V characters'
196
+ raise Error, 'attr_in_length must only contain T, L and/or V characters'
191
197
  end
192
198
 
199
+ # @param attr_order [::String]
200
+ # @return [void]
201
+ # @raise [Error] +attr_order+ contains unsupported characters
193
202
  def check_attr_order(attr_order)
194
203
  if attr_order.match(/^[TLV]{3,3}$/) &&
195
204
  (attr_order[0] != attr_order[1]) &&
@@ -198,9 +207,16 @@ module BinStruct
198
207
  return
199
208
  end
200
209
 
201
- raise 'attr_order must contain all three letters TLV, each once'
210
+ raise Error, 'attr_order must contain all three letters TLV, each once'
202
211
  end
203
212
 
213
+ # Set TLV classes and order on +klass+
214
+ # @param klass [Class]
215
+ # @param attr_order [::String]
216
+ # @param type_class [Class]
217
+ # @param length_class [Class]
218
+ # @param value_class [Class]
219
+ # @return [AbstractTLV]
204
220
  def generate_attributes(klass, attr_order, type_class, length_class, value_class)
205
221
  attr_order.each_char do |attr_type|
206
222
  case attr_type
@@ -218,6 +234,10 @@ module BinStruct
218
234
  end
219
235
  end
220
236
 
237
+ # Define given +aliases+ on +klass+
238
+ # @param klass [Class]
239
+ # @param aliases [Hash{Symbol=>Symbol}]
240
+ # @return [void]
221
241
  def generate_aliases_for(klass, aliases)
222
242
  aliases.each do |al, orig|
223
243
  klass.instance_eval do
@@ -243,7 +263,7 @@ module BinStruct
243
263
 
244
264
  # @abstract Should only be called on real TLV classes, created by {.create}.
245
265
  # Return a new instance of a real TLV class.
246
- # @param [Hash] options
266
+ # @param options [Hash]
247
267
  # @option options [Integer] :type
248
268
  # @option options [Integer] :length
249
269
  # @option options [Object] :value
@@ -261,12 +281,13 @@ module BinStruct
261
281
 
262
282
  # @abstract Should only be called on real TLV class instances.
263
283
  # Populate object from a binary string
264
- # @param [::String,nil] str
284
+ # @param str [::String,nil]
265
285
  # @return [AbstractTLV] self
266
286
  def read(str)
267
287
  return self if str.nil?
268
288
 
269
289
  idx = 0
290
+ str = str.b
270
291
  attributes.each do |attr_name|
271
292
  attr = self[attr_name]
272
293
  length = attr_name == :value ? real_length : attr.sz
@@ -279,7 +300,7 @@ module BinStruct
279
300
 
280
301
  # @abstract Should only be called on real TLV class instances.
281
302
  # Set +value+. May set +length+ if value is a {Types::String}.
282
- # @param [Object] val
303
+ # @param val [Object]
283
304
  # @return [Object]
284
305
  def value=(val)
285
306
  if val.is_a?(self[:value].class)
@@ -320,6 +341,8 @@ module BinStruct
320
341
 
321
342
  private
322
343
 
344
+ # Compute length to set in length attribute
345
+ # @return [::Integer]
323
346
  def real_length
324
347
  length = self.length
325
348
  length -= self[:type].sz if @attr_in_length.include?('T')
@@ -39,7 +39,7 @@ module BinStruct
39
39
 
40
40
  # @!method [](index)
41
41
  # Return the element at +index+.
42
- # @param [Integer] index
42
+ # @param index [Integer]
43
43
  # @return [Object]
44
44
  # @!method clear
45
45
  # Clear array.
@@ -77,7 +77,7 @@ module BinStruct
77
77
  end
78
78
 
79
79
  # Define type of objects in set. Used by {#read} and {#push}.
80
- # @param [Class] klass
80
+ # @param klass [Class]
81
81
  # @return [void]
82
82
  def set_of(klass)
83
83
  @klass = klass
@@ -85,7 +85,7 @@ module BinStruct
85
85
  end
86
86
  # rubocop:enable Naming/AccessorMethodName
87
87
 
88
- # @param [Hash] options
88
+ # @param options [Hash]
89
89
  # @option options [Int] counter Int object used as a counter for this set
90
90
  # @example counter example
91
91
  # # Define a counter
@@ -113,11 +113,12 @@ module BinStruct
113
113
  # Initialize array for copy:
114
114
  # * duplicate internal array.
115
115
  # @note Associated counter, if any, is not duplicated
116
- def initialize_copy(_other)
116
+ def initialize_copy(*)
117
117
  @array = @array.dup
118
118
  end
119
119
 
120
120
  # Check equality. Equality is checked on underlying array.
121
+ # @param other [Object]
121
122
  # @return [Boolean]
122
123
  def ==(other)
123
124
  @array == case other
@@ -137,7 +138,7 @@ module BinStruct
137
138
  end
138
139
 
139
140
  # Delete an object from this array. Update associated counter if any
140
- # @param [Object] obj
141
+ # @param obj [Object]
141
142
  # @return [Object] deleted object
142
143
  def delete(obj)
143
144
  deleted = @array.delete(obj)
@@ -146,7 +147,7 @@ module BinStruct
146
147
  end
147
148
 
148
149
  # Delete element at +index+. Update associated counter if any
149
- # @param [Integer] index
150
+ # @param index [Integer]
150
151
  # @return [Object,nil] deleted object
151
152
  def delete_at(index)
152
153
  deleted = @array.delete_at(index)
@@ -158,7 +159,7 @@ module BinStruct
158
159
  # declared by subclasses.
159
160
  # Add an object to this array. Do not update associated counter. If associated must be incremented, use
160
161
  # {#<<}
161
- # @param [Object] obj type depends on subclass
162
+ # @param obj [Object] type depends on subclass
162
163
  # @return [self]
163
164
  # @see #<<
164
165
  def push(obj)
@@ -176,7 +177,7 @@ module BinStruct
176
177
  # declared by subclasses.
177
178
  # Add an object to this array, and increment associated counter, if any. If associated counter must not be
178
179
  # incremented, use {#push}.
179
- # @param [Object] obj type depends on subclass
180
+ # @param obj [Object] type depends on subclass
180
181
  # @return [self]
181
182
  # @see #push
182
183
  def <<(obj)
@@ -186,7 +187,7 @@ module BinStruct
186
187
  end
187
188
 
188
189
  # Populate object from a string or from an array of hashes
189
- # @param [::String, ::Array<Hash>] data
190
+ # @param data [::String, ::Array<Hash>]
190
191
  # @return [self]
191
192
  def read(data)
192
193
  clear
@@ -227,6 +228,8 @@ module BinStruct
227
228
 
228
229
  # rubocop:disable Metrics/CyclomaticComplexity
229
230
 
231
+ # @param str [::String]
232
+ # @return [void]
230
233
  def read_from_string(str)
231
234
  return self if str.nil? || @counter&.to_i&.zero?
232
235
 
@@ -239,6 +242,8 @@ module BinStruct
239
242
  end
240
243
  # rubocop:enable Metrics/CyclomaticComplexity
241
244
 
245
+ # @param ary [::Array<Hash{Symbol=>Object}>]
246
+ # @return [void]
242
247
  def read_from_array(ary)
243
248
  return self if ary.empty?
244
249
 
@@ -247,6 +252,11 @@ module BinStruct
247
252
  end
248
253
  end
249
254
 
255
+ # @abstract Subclasses may override this method to customize {#<<}, {#push} and {#read}.
256
+ # A default implementation is provided.
257
+ # This method instanciate a {.set_of_klass} object from +hsh+.
258
+ # @param hsh [Hash{Symbol=>Object}]
259
+ # @return [Object] an object of (sub)class {.set_of_klass}
250
260
  def record_from_hash(hsh)
251
261
  obj_klass = self.class.set_of_klass
252
262
  unless obj_klass
@@ -254,15 +264,25 @@ module BinStruct
254
264
  'class should define #record_from_hash or declare type of elements in set with .set_of'
255
265
  end
256
266
 
257
- obj = obj_klass.new(hsh) if obj_klass
267
+ obj = obj_klass.new(hsh)
258
268
  klass = real_type(obj)
259
269
  klass == obj_klass ? obj : klass.new(hsh)
260
270
  end
261
271
 
272
+ # @abstract Subclasses may override thi method to customize {#<<}, {#push} and {#read}.
273
+ # A default implementation is provided.
274
+ # Return real type for +_obj+. Here, always return {.set_of_klass}.
275
+ # @param _obj [Object] not used here but may be by subclasses
276
+ # @return [Object] an object of class {.set_of_class}
262
277
  def real_type(_obj)
263
278
  self.class.set_of_klass
264
279
  end
265
280
 
281
+ # @abstract Subclasses may override thi method to customize {#<<}, {#push} and {#read}.
282
+ # A default implementation is provided.
283
+ # Instanicate an object to put in self from a String
284
+ # @param str [::String] not used here but may be by subclasses
285
+ # @return [Object] an object of class {.set_of_class}
266
286
  def create_object_from_str(str)
267
287
  klass = self.class.set_of_klass
268
288
  obj = klass.new.read(str)
@@ -277,17 +297,22 @@ module BinStruct
277
297
  end
278
298
 
279
299
  # @private
300
+ # Mixin to define common methods to all +ArrayOfInt*+ classes.
280
301
  module ArrayOfIntMixin
302
+ # Read data from an Array and instanciate an {Int} type (from {.set_of_klass}) for each element and put it in self.
303
+ # @param ary [::Array<Integer>]
304
+ # @return [void]
281
305
  def read_from_array(ary)
282
306
  return self if ary.empty?
283
307
 
308
+ inner_klass = self.class.set_of_klass
284
309
  ary.each do |i|
285
- self << self.class.set_of_klass.new(value: i)
310
+ self << inner_klass.new(value: i)
286
311
  end
287
312
  end
288
313
  end
289
314
 
290
- # Specialized {Array} to handle serie of {Int8}.
315
+ # Specialized {Array} to handle series of {Int8}.
291
316
  # @example
292
317
  # ary = BinStruct::ArrayOfInt8.new
293
318
  # ary.read([0, 1, 2])
@@ -297,10 +322,11 @@ module BinStruct
297
322
  # ary.map(&:to_i) #=> [5, 6]
298
323
  class ArrayOfInt8 < Array
299
324
  include ArrayOfIntMixin
325
+
300
326
  set_of Int8
301
327
  end
302
328
 
303
- # Specialized {Array} to handle serie of {Int16}.
329
+ # Specialized {Array} to handle series of {Int16}.
304
330
  # @example
305
331
  # ary = BinStruct::ArrayOfInt16.new
306
332
  # ary.read([0, 1, 2])
@@ -310,10 +336,11 @@ module BinStruct
310
336
  # ary.map(&:to_i) #=> [0x0506]
311
337
  class ArrayOfInt16 < Array
312
338
  include ArrayOfIntMixin
339
+
313
340
  set_of Int16
314
341
  end
315
342
 
316
- # Specialized {Array} to handle serie of {Int16le}.
343
+ # Specialized {Array} to handle series of {Int16le}.
317
344
  # @example
318
345
  # ary = BinStruct::ArrayOfInt16le.new
319
346
  # ary.read([0, 1, 2])
@@ -323,10 +350,11 @@ module BinStruct
323
350
  # ary.map(&:to_i) #=> [0x0605]
324
351
  class ArrayOfInt16le < Array
325
352
  include ArrayOfIntMixin
353
+
326
354
  set_of Int16le
327
355
  end
328
356
 
329
- # Specialized {Array} to handle serie of {Int32}.
357
+ # Specialized {Array} to handle series of {Int32}.
330
358
  # @example
331
359
  # ary = BinStruct::ArrayOfInt32.new
332
360
  # ary.read([0, 1, 2])
@@ -336,10 +364,11 @@ module BinStruct
336
364
  # ary.map(&:to_i) #=> [0x00000506]
337
365
  class ArrayOfInt32 < BinStruct::Array
338
366
  include ArrayOfIntMixin
367
+
339
368
  set_of Int32
340
369
  end
341
370
 
342
- # Specialized {Array} to handle serie of {Int32le}.
371
+ # Specialized {Array} to handle series of {Int32le}.
343
372
  # @example
344
373
  # ary = BinStruct::ArrayOfInt32le.new
345
374
  # ary.read([0, 1, 2])
@@ -349,6 +378,7 @@ module BinStruct
349
378
  # ary.map(&:to_i) #=> [0x06050000]
350
379
  class ArrayOfInt32le < BinStruct::Array
351
380
  include ArrayOfIntMixin
381
+
352
382
  set_of Int32le
353
383
  end
354
384
  end
@@ -34,6 +34,7 @@ module BinStruct
34
34
  attr_reader :width
35
35
 
36
36
  # @private
37
+ # @todo Ruby 3.2: replace Struct by Data
37
38
  Parameters = Struct.new(:width, :fields, :int)
38
39
 
39
40
  class << self
@@ -44,13 +45,13 @@ module BinStruct
44
45
  attr_reader :parameters
45
46
 
46
47
  # @private
47
- # @return [::Array[Symbol]]
48
+ # @return [::Array<Symbol>]
48
49
  attr_reader :bit_methods
49
50
 
50
51
  # Create a new {BitAttr} subclass with specified parameters
51
- # @param [Integer] width size of bitfields in bits. Must be a size of an {Int} (8, 16, 24, 32 or 64 bits).
52
- # @param [:big,:little,:native] endian endianess of bit attribute as an integer
53
- # @param [Hash{Symbol=>Integer}] fields hash associating field names with their size. Total size MUST be equal
52
+ # @param width [Integer] size of bitfields in bits. Must be a size of an {Int} (8, 16, 24, 32 or 64 bits).
53
+ # @param endian [Symbol] endianess of bit attribute as an integer (:big, :little or :native)
54
+ # @param fields [Hash{Symbol=>Integer}] hash associating field names with their size. Total size MUST be equal
54
55
  # to +width+.
55
56
  # @return [Class]
56
57
  # @raise [ArgumentError] raise if:
@@ -78,12 +79,16 @@ module BinStruct
78
79
  @cache = {}
79
80
  end
80
81
 
81
- # @param [::Array] params
82
+ # @param params [::Array]
82
83
  # @return [::String]
83
84
  def compute_hash(*params)
84
85
  Digest::MD5.digest(Marshal.dump(params))
85
86
  end
86
87
 
88
+ # @param width [::Integer]
89
+ # @param endian [Symbol] :little,:big or:native
90
+ # @param fields [Hash{Symbol=>Integer}]
91
+ # @return [Class] subclass of {BitAttr} with given parameters
87
92
  def create_subclass(width, endian, fields)
88
93
  klass = Class.new(self) do
89
94
  int_klass = BinStruct.const_get("Int#{width}")
@@ -95,8 +100,8 @@ module BinStruct
95
100
  klass
96
101
  end
97
102
 
98
- # @param [Class] {BitAttr} subclass
99
- # @param [Hash{Symbol => Integer}] fields
103
+ # @param klass [Class] {BitAttr} subclass
104
+ # @param fields [Hash{Symbol => Integer}]
100
105
  # @return [void]
101
106
  def define_methods(klass, fields)
102
107
  define_str = +''
@@ -109,9 +114,9 @@ module BinStruct
109
114
  define_str << "def #{name}?; @data[#{name.inspect}] != 0; end\n"
110
115
  klass.bit_methods << :"#{name}?"
111
116
  define_str << "def #{name}=(val); v = case val when TrueClass; 1 when FalseClass; 0 else val end; " \
112
- "@data[#{name.inspect}] = v; end\n"
117
+ "@data[#{name.inspect}] = v; @int.value = compute_integer; end\n"
113
118
  else
114
- define_str << "def #{name}=(val); @data[#{name.inspect}] = val; end\n"
119
+ define_str << "def #{name}=(val); @data[#{name.inspect}] = val; @int.value = compute_integer; end\n"
115
120
  end
116
121
  end
117
122
  klass.class_eval(define_str)
@@ -119,11 +124,11 @@ module BinStruct
119
124
  end
120
125
 
121
126
  # Initialize bit attribute
122
- # @param [Hash{Symbol=>Integer}] opts initialization values for fields, where keys are field names and values are
127
+ # @param values [Hash{Symbol=>Integer}] initialization values for fields, where keys are field names and values are
123
128
  # initialization values
124
129
  # @return [self]
125
130
  # @raise [NotImplementedError] raised when called on {BitAttr} class
126
- def initialize(opts = {})
131
+ def initialize(values = {})
127
132
  parameters = self.class.parameters
128
133
  raise NotImplementedError, "#initialize may only be called on subclass of #{self.class}" if parameters.nil?
129
134
 
@@ -131,19 +136,19 @@ module BinStruct
131
136
  @fields = parameters.fields
132
137
  @int = parameters.int.dup
133
138
  @data = {}
134
- @bit_methods = []
135
139
 
136
140
  parameters.fields.each_key do |name|
137
- @data[name] = opts[name] || 0
141
+ @data[name] = values[name] || 0
138
142
  end
139
- @bit_methods.freeze
143
+ @int.value = compute_integer
140
144
  end
141
145
 
142
- def initialize_copy(_other)
146
+ # Dup internal @data hash
147
+ def initialize_copy(*)
143
148
  @data = @data.dup
144
149
  end
145
150
 
146
- # @return [::Array[Symbol]]
151
+ # @return [::Array<Symbol>]
147
152
  def bit_methods
148
153
  self.class.bit_methods
149
154
  end
@@ -162,7 +167,7 @@ module BinStruct
162
167
  end
163
168
 
164
169
  # Populate bit attribute from +str+
165
- # @param [#to_s,nil] str
170
+ # @param str [#to_s,nil]
166
171
  # @return [self]
167
172
  def read(str)
168
173
  return self if str.nil?
@@ -174,30 +179,26 @@ module BinStruct
174
179
  # Give integer associated to this attribute
175
180
  # @return [Integer]
176
181
  def to_i
177
- v = 0
178
- @fields.each do |name, size|
179
- v <<= size
180
- v |= @data[name]
181
- end
182
-
183
- v
182
+ @int.to_i
184
183
  end
185
184
  alias to_human to_i
186
185
 
187
186
  # Return binary string
188
187
  # @return [::String]
189
188
  def to_s
190
- @int.value = to_i
191
189
  @int.to_s
192
190
  end
193
191
 
194
192
  # Set fields from associated integer
195
- # @param [#to_i] value
193
+ # @param value [#to_i]
196
194
  # @return [self]
197
195
  def from_human(value)
198
- compute_data(value.to_i)
196
+ ivalue = value.to_i
197
+ @int.value = ivalue
198
+ compute_data(ivalue)
199
199
  end
200
200
 
201
+ # @return [::String]
201
202
  def format_inspect
202
203
  str = @int.format_inspect << "\n"
203
204
  str << @data.map { |name, value| "#{name}:#{value}" }.join(' ')
@@ -205,7 +206,7 @@ module BinStruct
205
206
 
206
207
  private
207
208
 
208
- # @param [Integer] value
209
+ # @param value [Integer]
209
210
  # @return [self]
210
211
  def compute_data(value)
211
212
  @fields.reverse_each do |name, size|
@@ -215,5 +216,17 @@ module BinStruct
215
216
 
216
217
  self
217
218
  end
219
+
220
+ # Compute integer from fields
221
+ # @return [Integer]
222
+ def compute_integer
223
+ v = 0
224
+ @fields.each do |name, size|
225
+ v <<= size
226
+ v |= @data[name]
227
+ end
228
+
229
+ v
230
+ end
218
231
  end
219
232
  end
@@ -22,11 +22,11 @@ module BinStruct
22
22
  # @!method [](index)
23
23
  # @overload [](index)
24
24
  # Return the character at +index+.
25
- # @param [Integer] index
25
+ # @param index [Integer]
26
26
  # @overload [](start, length)
27
27
  # Return the substring starting at +start+ with +length+ length.
28
- # @param [Integer] start
29
- # @param [Integer] length
28
+ # @param start [Integer]
29
+ # @param length [Integer]
30
30
  # @return [::String,nil]
31
31
  # @!method length
32
32
  # Return string length (without null-terminator)
@@ -49,8 +49,8 @@ module BinStruct
49
49
  # @return [Encoding]
50
50
  # @!method index(substring, offset = 0)
51
51
  # Returns the Integer index of the first occurrence of the given substring, or +nil+ if none found.
52
- # @param [::String] substring
53
- # @param [Integer] offset
52
+ # @param substring [::String]
53
+ # @param offset [Integer]
54
54
  # @return [Integer,nil]
55
55
  # @!method empty?
56
56
  # Return +true+ is string is empty.
@@ -77,7 +77,7 @@ module BinStruct
77
77
  # @return [Integer,nil]
78
78
  attr_reader :static_length
79
79
 
80
- # @param [Hash] options
80
+ # @param options [Hash]
81
81
  # @option options [Integer] :static_length set a static length for this string
82
82
  # @option options [::String] :value string value (default to +""+)
83
83
  def initialize(options = {})
@@ -86,12 +86,12 @@ module BinStruct
86
86
  end
87
87
 
88
88
  # Populate self from binary string
89
- # @param [#to_s] str
89
+ # @param str [#to_s]
90
90
  # @return [self]
91
91
  def read(str)
92
92
  s = str.to_s
93
93
  s = s[0, static_length] if static_length?
94
- register_internal_string s
94
+ register_internal_string(s)
95
95
  remove_null_character
96
96
  self
97
97
  end
@@ -109,10 +109,10 @@ module BinStruct
109
109
  end
110
110
 
111
111
  # Append the given string to CString
112
- # @param [#to_s] str
112
+ # @param str [#to_s]
113
113
  # @return [self]
114
114
  def <<(str)
115
- @string << str.to_s
115
+ @string << str.to_s.b
116
116
  remove_null_character
117
117
  self
118
118
  end
@@ -134,7 +134,7 @@ module BinStruct
134
134
  end
135
135
 
136
136
  # Populate CString from a human readable string
137
- # @param [::String] str
137
+ # @param str [::String]
138
138
  # @return [self]
139
139
  def from_human(str)
140
140
  read(str)
@@ -148,12 +148,15 @@ module BinStruct
148
148
 
149
149
  private
150
150
 
151
+ # @param str [::String]
152
+ # @return [void]
151
153
  def register_internal_string(str)
152
154
  @string = str.b
153
155
  end
154
156
 
157
+ # @return [void]
155
158
  def remove_null_character
156
- idx = string.index(0.chr)
159
+ idx = string.index("\0")
157
160
  register_internal_string(string[0, idx]) unless idx.nil?
158
161
  end
159
162
  end