bin_struct 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,10 +9,10 @@
9
9
  module BinStruct
10
10
  # Base integer class to handle binary integers
11
11
  # @abstract
12
- # @author Sylvain Daubert
12
+ # @author Sylvain Daubert (2016-2024)
13
13
  # @author LemonTree55
14
14
  class Int
15
- include Fieldable
15
+ include Structable
16
16
 
17
17
  # Integer value
18
18
  # @return [Integer,nil]
@@ -21,22 +21,22 @@ module BinStruct
21
21
  # @return [:little,:big,:native,nil]
22
22
  attr_accessor :endian
23
23
  # Integer size, in bytes
24
- # @return [Integer, nil]
24
+ # @return [Integer]
25
25
  attr_accessor :width
26
26
  # Integer default value
27
27
  # @return [Integer]
28
28
  attr_accessor :default
29
29
 
30
30
  # @param [Hash] options
31
- # @option options [Integer, nil] :value
32
- # @option options [:little,:big,nil] :endian
33
- # @option options [Integer,nil] :width
34
- # @option options [Integer] :default
31
+ # @option options [Integer, nil] :value Value to set Int to
32
+ # @option options [:little,:big,:native,nil] :endian Int's endianess
33
+ # @option options [Integer,nil] :width Int's width in bytes
34
+ # @option options [Integer] :default Default value to use when {#value} is not set (Default to +0+).
35
35
  # @author LemonTree55
36
36
  def initialize(options = {})
37
37
  @value = options[:value]
38
38
  @endian = options[:endian]
39
- @width = options[:width]
39
+ @width = options[:width] || 0
40
40
  @default = options[:default] || 0
41
41
  end
42
42
 
@@ -69,6 +69,7 @@ module BinStruct
69
69
  end
70
70
  alias to_human to_i
71
71
 
72
+ # Initialize value from an Integer.
72
73
  # @param [Integer] value
73
74
  # @return [self]
74
75
  def from_human(value)
@@ -88,8 +89,8 @@ module BinStruct
88
89
  width
89
90
  end
90
91
 
91
- # Format Int type when inspecting header or packet
92
- # @return [String]
92
+ # Format Int type when inspecting Struct
93
+ # @return [::String]
93
94
  def format_inspect
94
95
  format_str % [to_i.to_s, to_i]
95
96
  end
@@ -108,12 +109,10 @@ module BinStruct
108
109
  end
109
110
 
110
111
  # One byte unsigned integer
111
- # @author Sylvain Daubert
112
112
  # @author LemonTree55
113
113
  class Int8 < Int
114
114
  # @param [Hash] options
115
115
  # @option options [Integer,nil] :value
116
- # @author LemonTree55
117
116
  def initialize(options = {})
118
117
  options[:endian] = nil
119
118
  options[:width] = 1
@@ -123,12 +122,10 @@ module BinStruct
123
122
  end
124
123
 
125
124
  # One byte signed integer
126
- # @author Sylvain Daubert
127
125
  # @author LemonTree55
128
126
  class SInt8 < Int
129
127
  # @param [Hash] options
130
128
  # @option options [Integer,nil] :value
131
- # @author LemonTree55
132
129
  def initialize(options = {})
133
130
  options[:endian] = nil
134
131
  options[:width] = 1
@@ -138,12 +135,12 @@ module BinStruct
138
135
  end
139
136
 
140
137
  # 2-byte unsigned integer
141
- # @author Sylvain Daubert
138
+ # @author Sylvain Daubert (2016-2024)
142
139
  # @author LemonTree55
143
140
  class Int16 < Int
144
141
  # @param [Hash] options
145
142
  # @option options [Integer,nil] :value
146
- # @option [:big, :little, :native] :endian
143
+ # @option options [:big,:little,:native] :endian
147
144
  def initialize(options = {})
148
145
  opts = { value: options[:value], endian: options[:endian] || :big, width: 2 }
149
146
  super(opts)
@@ -151,17 +148,16 @@ module BinStruct
151
148
  end
152
149
  end
153
150
 
154
- # big endian 2-byte unsigned integer
155
- # @author Sylvain Daubert
151
+ # Big endian 2-byte unsigned integer
152
+ # @author Sylvain Daubert (2016-2024)
156
153
  class Int16be < Int16
157
154
  undef endian=
158
155
  end
159
156
 
160
- # little endian 2-byte unsigned integer
161
- # @author Sylvain Daubert
157
+ # Little endian 2-byte unsigned integer
158
+ # @author Sylvain Daubert (2016-2024)
162
159
  # @author LemonTree55
163
160
  class Int16le < Int16
164
- # @param [Integer,nil] value
165
161
  undef endian=
166
162
 
167
163
  # @param [Hash] options
@@ -172,16 +168,13 @@ module BinStruct
172
168
  end
173
169
  end
174
170
 
175
- # native endian 2-byte unsigned integer
176
- # @author Sylvain Daubert
171
+ # Native endian 2-byte unsigned integer
177
172
  # @author LemonTree55
178
173
  class Int16n < Int16
179
- # @param [Integer,nil] value
180
174
  undef endian=
181
175
 
182
176
  # @param [Hash] options
183
177
  # @option options [Integer,nil] :value
184
- # @author LemonTree55
185
178
  def initialize(options = {})
186
179
  opts = { value: options[:value], endian: :native }
187
180
  super(opts)
@@ -189,12 +182,12 @@ module BinStruct
189
182
  end
190
183
 
191
184
  # 2-byte signed integer
192
- # @author Sylvain Daubert
185
+ # @author Sylvain Daubert (2016-2024)
193
186
  # @author LemonTree55
194
187
  class SInt16 < Int16
195
188
  # @param [Hash] options
196
189
  # @option options [Integer,nil] :value
197
- # @author LemonTree55
190
+ # @option options [:big,:little,:native] :endian
198
191
  def initialize(options = {})
199
192
  opts = { value: options[:value], endian: options[:endian] || :big }
200
193
  super(opts)
@@ -202,20 +195,20 @@ module BinStruct
202
195
  end
203
196
  end
204
197
 
205
- # big endian 2-byte signed integer
206
- # @author Sylvain Daubert
198
+ # Big endian 2-byte signed integer
199
+ # @author Sylvain Daubert (2016-2024)
207
200
  class SInt16be < SInt16
208
201
  undef endian=
209
202
  end
210
203
 
211
- # little endian 2-byte signed integer
212
- # @author Sylvain Daubert
204
+ # Little endian 2-byte signed integer
205
+ # @author Sylvain Daubert (2016-2024)
213
206
  # @author LemonTree55
214
207
  class SInt16le < SInt16
215
- # @param [Integer,nil] value
216
208
  undef endian=
217
209
 
218
- # @param [Integer, nil] value
210
+ # @param [Hash] options
211
+ # @option options [Integer,nil] :value
219
212
  # @author LemonTree55
220
213
  def initialize(options = {})
221
214
  opts = { value: options[:value], endian: :little }
@@ -223,15 +216,14 @@ module BinStruct
223
216
  end
224
217
  end
225
218
 
226
- # native endian 2-byte signed integer
227
- # @author Sylvain Daubert
219
+ # Native endian 2-byte signed integer
220
+ # @author Sylvain Daubert (2016-2024)
228
221
  # @author LemonTree55
229
222
  class SInt16n < SInt16
230
- # @param [Integer,nil] value
231
223
  undef endian=
232
224
 
233
- # @param [Integer, nil] value
234
- # @author LemonTree55
225
+ # @param [Hash] options
226
+ # @option options [Integer,nil] :value
235
227
  def initialize(options = {})
236
228
  opts = { value: options[:value], endian: :native }
237
229
  super(opts)
@@ -259,8 +251,8 @@ module BinStruct
259
251
  super(opts)
260
252
  end
261
253
 
262
- # Read an 3-byte Int from a binary string
263
- # @param [String] str
254
+ # Read a 3-byte Int from a binary string
255
+ # @param [::String] value
264
256
  # @return [self]
265
257
  def read(value)
266
258
  return self if value.nil?
@@ -275,7 +267,7 @@ module BinStruct
275
267
  self
276
268
  end
277
269
 
278
- # @author Sylvain Daubert
270
+ # @author Sylvain Daubert (2016-2024)
279
271
  # @return [::String]
280
272
  def to_s
281
273
  up8 = to_i >> 16
@@ -288,16 +280,15 @@ module BinStruct
288
280
  end
289
281
  end
290
282
 
291
- # big endian 3-byte unsigned integer
292
- # @author Sylvain Daubert
283
+ # Big endian 3-byte unsigned integer
284
+ # @author Sylvain Daubert (2016-2024)
293
285
  class Int24be < Int24
294
286
  undef endian=
295
287
  end
296
288
 
297
- # little endian 3-byte unsigned integer
289
+ # Little endian 3-byte unsigned integer
298
290
  # @author LemonTree55
299
291
  class Int24le < Int24
300
- # @param [Integer,nil] value
301
292
  undef endian=
302
293
 
303
294
  # @param [Hash] options
@@ -308,10 +299,9 @@ module BinStruct
308
299
  end
309
300
  end
310
301
 
311
- # native endian 3-byte unsigned integer
302
+ # Native endian 3-byte unsigned integer
312
303
  # @author LemonTree55
313
304
  class Int24n < Int24
314
- # @param [Integer,nil] value
315
305
  undef endian=
316
306
 
317
307
  # @param [Hash] options
@@ -327,7 +317,7 @@ module BinStruct
327
317
  class Int32 < Int
328
318
  # @param [Hash] options
329
319
  # @option options [Integer,nil] :value
330
- # @option [:big, :little, :native] :endian
320
+ # @option options [:big,:little,:native] :endian
331
321
  def initialize(options = {})
332
322
  opts = { value: options[:value], endian: options[:endian] || :big, width: 4 }
333
323
  super(opts)
@@ -335,16 +325,15 @@ module BinStruct
335
325
  end
336
326
  end
337
327
 
338
- # big endian 4-byte unsigned integer
339
- # @author Sylvain Daubert
328
+ # Big endian 4-byte unsigned integer
329
+ # @author Sylvain Daubert (2016-2024)
340
330
  class Int32be < Int32
341
331
  undef endian=
342
332
  end
343
333
 
344
- # little endian 4-byte unsigned integer
334
+ # Little endian 4-byte unsigned integer
345
335
  # @author LemonTree55
346
336
  class Int32le < Int32
347
- # @param [Integer,nil] value
348
337
  undef endian=
349
338
 
350
339
  # @param [Hash] options
@@ -355,10 +344,9 @@ module BinStruct
355
344
  end
356
345
  end
357
346
 
358
- # native endian 4-byte unsigned integer
347
+ # Native endian 4-byte unsigned integer
359
348
  # @author LemonTree55
360
349
  class Int32n < Int32
361
- # @param [Integer,nil] value
362
350
  undef endian=
363
351
 
364
352
  # @param [Hash] options
@@ -369,12 +357,12 @@ module BinStruct
369
357
  end
370
358
  end
371
359
 
372
- # 4-byte unsigned integer
360
+ # 4-byte signed integer
373
361
  # @author LemonTree55
374
362
  class SInt32 < Int32
375
363
  # @param [Hash] options
376
364
  # @option options [Integer] :value
377
- # @option options [:big, :little, :native] :endian
365
+ # @option options [:big,:little,:native] :endian
378
366
  def initialize(options = {})
379
367
  opts = { value: options[:value], endian: options[:endian] || :big }
380
368
  super(opts)
@@ -382,16 +370,15 @@ module BinStruct
382
370
  end
383
371
  end
384
372
 
385
- # big endian 4-byte unsigned integer
386
- # @author Sylvain Daubert
373
+ # Big endian 4-byte signed integer
374
+ # @author Sylvain Daubert (2016-2024)
387
375
  class SInt32be < SInt32
388
376
  undef endian=
389
377
  end
390
378
 
391
- # little endian 4-byte unsigned integer
379
+ # Little endian 4-byte signed integer
392
380
  # @author LemonTree55
393
381
  class SInt32le < SInt32
394
- # @param [Integer,nil] value
395
382
  undef endian=
396
383
 
397
384
  # @param [Hash] options
@@ -402,10 +389,9 @@ module BinStruct
402
389
  end
403
390
  end
404
391
 
405
- # native endian 4-byte unsigned integer
392
+ # Native endian 4-byte signed integer
406
393
  # @author LemonTree55
407
394
  class SInt32n < SInt32
408
- # @param [Integer,nil] value
409
395
  undef endian=
410
396
 
411
397
  # @param [Hash] options
@@ -421,7 +407,7 @@ module BinStruct
421
407
  class Int64 < Int
422
408
  # @param [Hash] options
423
409
  # @option options [Integer] :value
424
- # @option options [:big, :little, :native] :endian
410
+ # @option options [:big,:little,:native] :endian
425
411
  def initialize(options = {})
426
412
  opts = options.slice(:value, :endian)
427
413
  opts[:endian] ||= :big
@@ -431,16 +417,15 @@ module BinStruct
431
417
  end
432
418
  end
433
419
 
434
- # big endian 8-byte unsigned integer
435
- # @author Sylvain Daubert
420
+ # Big endian 8-byte unsigned integer
421
+ # @author Sylvain Daubert (2016-2024)
436
422
  class Int64be < Int64
437
423
  undef endian=
438
424
  end
439
425
 
440
- # little endian 8-byte unsigned integer
426
+ # Little endian 8-byte unsigned integer
441
427
  # @author LemonTree55
442
428
  class Int64le < Int64
443
- # @param [Integer,nil] value
444
429
  undef endian=
445
430
 
446
431
  # @param [Hash] options
@@ -451,10 +436,9 @@ module BinStruct
451
436
  end
452
437
  end
453
438
 
454
- # native endian 8-byte unsigned integer
439
+ # Native endian 8-byte unsigned integer
455
440
  # @author LemonTree55
456
441
  class Int64n < Int64
457
- # @param [Integer,nil] value
458
442
  undef endian=
459
443
 
460
444
  # @param [Hash] options
@@ -465,12 +449,12 @@ module BinStruct
465
449
  end
466
450
  end
467
451
 
468
- # 8-byte unsigned integer
452
+ # 8-byte signed integer
469
453
  # @author LemonTree55
470
454
  class SInt64 < Int64
471
455
  # @param [Hash] options
472
456
  # @option options [Integer] :value
473
- # @option options [:big, :little, :native] :endian
457
+ # @option options [:big,:little,:native] :endian
474
458
  def initialize(options = {})
475
459
  opts = options.slice(:value, :endian)
476
460
  super(opts)
@@ -478,16 +462,15 @@ module BinStruct
478
462
  end
479
463
  end
480
464
 
481
- # big endian 8-byte unsigned integer
482
- # @author Sylvain Daubert
465
+ # Big endian 8-byte signed integer
466
+ # @author Sylvain Daubert (2016-2024)
483
467
  class SInt64be < SInt64
484
468
  undef endian=
485
469
  end
486
470
 
487
- # little endian 8-byte unsigned integer
471
+ # Little endian 8-byte signed integer
488
472
  # @author LemonTree55
489
473
  class SInt64le < SInt64
490
- # @param [Integer,nil] value
491
474
  undef endian=
492
475
 
493
476
  # @param [Hash] options
@@ -498,10 +481,9 @@ module BinStruct
498
481
  end
499
482
  end
500
483
 
501
- # native endian 8-byte unsigned integer
484
+ # Native endian 8-byte signed integer
502
485
  # @author LemonTree55
503
486
  class SInt64n < SInt64
504
- # @param [Integer,nil] value
505
487
  undef endian=
506
488
 
507
489
  # @param [Hash] options
@@ -7,27 +7,29 @@
7
7
  # This program is published under MIT license.
8
8
 
9
9
  module BinStruct
10
- # Provides a class for creating strings preceeded by their length as a {Int}.
10
+ # Provides a class for creating strings preceeded by their length as an {Int}.
11
11
  # By default, a null string will have one byte length (length byte set to 0).
12
- # @author Sylvain Daubert
12
+ # @author Sylvain Daubert (2016-2024)
13
+ # @author LemonTree55
13
14
  class IntString
14
- include Fieldable
15
+ include Structable
15
16
 
16
17
  # internal string
17
- # @return [String]
18
+ # @return [::String]
18
19
  attr_reader :string
19
20
 
20
21
  # @param [Hash] options
21
22
  # @option options [Class] :length_type should be a {Int} subclass. Default to {Int8}.
22
- # @option options [::String] :string String value. Default to +''+
23
+ # @option options [::String] :value String value. Default to +""+
23
24
  def initialize(options = {})
24
- @string = BinStruct::String.new.read(options[:string] || '')
25
+ @string = BinStruct::String.new.read(options[:value] || +'')
25
26
  @length = (options[:length_type] || Int8).new
26
27
  calc_length
27
28
  end
28
29
 
30
+ # Populate IntString from a binary String
29
31
  # @param [::String] str
30
- # @return [IntString] self
32
+ # @return [self]
31
33
  def read(str)
32
34
  unless str[0, @length.width].size == @length.width
33
35
  raise Error,
@@ -38,19 +40,25 @@ module BinStruct
38
40
  self
39
41
  end
40
42
 
43
+ # Set length
41
44
  # @param [Integer] len
42
45
  # @return [Integer]
43
46
  def length=(len)
44
47
  @length.from_human(len)
48
+ # rubocop:disable Lint/Void
49
+ len
50
+ # rubocop:enable Lint/Void
45
51
  end
46
52
 
53
+ # Get length as registered in +IntLength+
47
54
  # @return [Integer]
48
55
  def length
49
56
  @length.to_i
50
57
  end
51
58
 
59
+ # Set string without setting {#length}
52
60
  # @param [#to_s] str
53
- # @return [String]
61
+ # @return [::String]
54
62
  def string=(str)
55
63
  @length.value = str.to_s.size
56
64
  @string = str.to_s
@@ -63,17 +71,16 @@ module BinStruct
63
71
  end
64
72
 
65
73
  # Set from a human readable string
66
- # @param [String] str
74
+ # @param [::String] str
67
75
  # @return [self]
68
76
  def from_human(str)
69
- @string.read str
77
+ @string.read(str)
70
78
  calc_length
71
79
  self
72
80
  end
73
81
 
74
82
  # Get human readable string
75
83
  # @return [::String]
76
- # @since 2.2.0
77
84
  def to_human
78
85
  @string
79
86
  end
@@ -81,10 +88,10 @@ module BinStruct
81
88
  # Set length from internal string length
82
89
  # @return [Integer]
83
90
  def calc_length
84
- @length.read @string.length
91
+ @length.from_human(@string.length)
85
92
  end
86
93
 
87
- # Give binary string length (including +length+ field)
94
+ # Give binary string length (including +length+ attribute)
88
95
  # @return [Integer]
89
96
  def sz
90
97
  to_s.size
@@ -10,16 +10,16 @@ module BinStruct
10
10
  # This module is a mixin adding +length_from+ capacity to a type.
11
11
  # +length_from+ capacity is the capacity, for a type, to gets its
12
12
  # length from another object.
13
- # @author Sylvain Daubert
14
- # @since 3.0.0
13
+ # @author Sylvain Daubert (2016-2024)
14
+ # @author LemonTree55
15
15
  module LengthFrom
16
16
  # Max value returned by {#sz_to_read}.
17
17
  MAX_SZ_TO_READ = 65_535
18
18
 
19
- # Initialize +length from+ capacity.
20
- # Should be call by extensed object's initialize.
19
+ # Initialize +length_from+ capacity.
20
+ # Should be called by extended object's initialize method.
21
21
  # @param [Hash] options
22
- # @option options [Types::Int,Proc] :length_from object or proc from which
22
+ # @option options [Int,Proc] :length_from object or proc from which
23
23
  # takes length when reading
24
24
  # @return [void]
25
25
  def initialize_length_from(options)
@@ -28,7 +28,7 @@ module BinStruct
28
28
 
29
29
  # Return a substring from +str+ of length given in another object.
30
30
  # @param [#to_s] str
31
- # @return [String]
31
+ # @return [::String]
32
32
  def read_with_length_from(str)
33
33
  s = BinStruct.force_binary(str.to_s)
34
34
  s[0, sz_to_read]
@@ -11,23 +11,26 @@ module BinStruct
11
11
  # oui = OUI.new
12
12
  # oui.from_human('00:01:02')
13
13
  # oui.to_human # => "00:01:02"
14
- # @author Sylvain Daubert
15
- class OUI < Fields
16
- include Fieldable
14
+ # oui.to_s # => "\x00\x01\x03"
15
+ # @author Sylvain Daubert (2016-2024)
16
+ # @author LemonTree55
17
+ class OUI < Struct
18
+ include Structable
17
19
 
18
20
  # @attribute b2
19
21
  # @return [Integer] left-most byte
20
- define_field :b2, Int8
22
+ define_attr :b2, Int8
21
23
  # @attribute b1
22
24
  # @return [Integer] center byte
23
- define_field :b1, Int8
25
+ define_attr :b1, Int8
24
26
  # @attribute b0
25
27
  # @return [Integer] right-most byte
26
- define_field :b0, Int8
28
+ define_attr :b0, Int8
27
29
 
28
30
  # Read a human-readable string to populate object
29
- # @param [String] str
30
- # @return [OUI] self
31
+ # @param [::String] str
32
+ # @return [self]
33
+ # @raise [ArgumentError] OUI cannot be recognized from +str+
31
34
  def from_human(str)
32
35
  return self if str.nil?
33
36
 
@@ -41,9 +44,9 @@ module BinStruct
41
44
  end
42
45
 
43
46
  # Get OUI in human readable form (colon-separated bytes)
44
- # @return [String]
47
+ # @return [::String]
45
48
  def to_human
46
- fields.map { |m| '%02x' % self[m] }.join(':')
49
+ attributes.map { |m| '%02x' % self[m] }.join(':')
47
50
  end
48
51
  end
49
52
  end
@@ -9,42 +9,49 @@
9
9
  require 'forwardable'
10
10
 
11
11
  module BinStruct
12
- # This class mimics regular String, but it is {Fieldable}.
13
- # @author Sylvain Daubert
14
- # @since 3.1.6 no more a subclass or regular String
12
+ # This class mimics regular String, but it is {Structable}.
13
+ # @author Sylvain Daubert (2016-2024)
14
+ # @author LemonTree55
15
15
  class String
16
16
  extend Forwardable
17
- include Fieldable
17
+ include Structable
18
18
  include LengthFrom
19
19
 
20
- def_delegators :@string, :[], :to_s, :length, :size, :inspect, :==,
20
+ def_delegators :@string, :[], :length, :size, :inspect, :==,
21
21
  :unpack, :force_encoding, :encoding, :index, :empty?,
22
22
  :encode, :slice, :slice!, :[]=
23
23
 
24
+ # Underlying Ruby String
24
25
  # @return [::String]
25
26
  attr_reader :string
27
+ # String static length, if set
26
28
  # @return [Integer]
27
29
  attr_reader :static_length
28
30
 
29
31
  # @param [Hash] options
30
- # @option options [Types::Int,Proc] :length_from object or proc from which
32
+ # @option options [Int,Proc] :length_from object or proc from which
31
33
  # takes length when reading
32
34
  # @option options [Integer] :static_length set a static length for this string
35
+ # @option options [::String] :value string value (default to +''+)
33
36
  def initialize(options = {})
34
- register_internal_string(+'')
37
+ register_internal_string(options[:value] || +'')
35
38
  initialize_length_from(options)
36
39
  @static_length = options[:static_length]
37
40
  end
38
41
 
42
+ # Initialize object on copying:
43
+ # * duplicate underlying Ruby String
44
+ # @return [void]
39
45
  def initialize_copy(_orig)
40
46
  @string = @string.dup
41
47
  end
42
48
 
49
+ # Populate String from a binary String. Limit length using {LengthFrom} or {#static_length}, if one is set.
43
50
  # @param [::String] str
44
- # @return [String] self
51
+ # @return [self]
45
52
  def read(str)
46
53
  s = read_with_length_from(str)
47
- register_internal_string s
54
+ register_internal_string(s)
48
55
  self
49
56
  end
50
57
 
@@ -52,9 +59,8 @@ module BinStruct
52
59
  private :old_sz_to_read
53
60
 
54
61
  # Size to read.
55
- # Computed from static_length or length_from, if defined.
62
+ # Computed from {#static_length} or +length_from+, if one defined.
56
63
  # @return [Integer]
57
- # @since 3.1.6
58
64
  def sz_to_read
59
65
  return static_length if static_length?
60
66
 
@@ -63,11 +69,12 @@ module BinStruct
63
69
 
64
70
  # Say if a static length is defined
65
71
  # @return [Boolean]
66
- # @since 3.1.6
67
72
  def static_length?
68
73
  !static_length.nil?
69
74
  end
70
75
 
76
+ # Format String when inspecting from a {Struct}
77
+ # @return [::String]
71
78
  def format_inspect
72
79
  inspect
73
80
  end
@@ -76,10 +83,16 @@ module BinStruct
76
83
  # @param [#to_s] str
77
84
  # @return [self]
78
85
  def <<(str)
79
- @string << str.to_s
86
+ @string << BinStruct.force_binary(str.to_s)
80
87
  self
81
88
  end
82
89
 
90
+ # Generate binary string
91
+ # @return [::String]
92
+ def to_s
93
+ @string
94
+ end
95
+
83
96
  alias sz length
84
97
  alias to_human to_s
85
98
  alias from_human read