bin_struct 0.1.0 → 0.2.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.
@@ -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