bit-struct 0.13.5 → 0.17
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 +7 -0
- data/History.txt +22 -1
- data/LICENSE +56 -0
- data/{README.txt → README.md} +94 -92
- data/Rakefile +56 -30
- data/examples/field-ripper.rb +1 -1
- data/examples/ip.rb +6 -6
- data/examples/longlong.rb +2 -2
- data/examples/md.rb +1 -1
- data/examples/modular-def.rb +2 -2
- data/examples/native.rb +3 -3
- data/examples/ping.rb +1 -1
- data/examples/raw.rb +1 -1
- data/examples/switch-endian.rb +2 -2
- data/examples/vector.rb +2 -2
- data/lib/bit-struct.rb +0 -11
- data/lib/bit-struct/bit-struct.rb +61 -143
- data/lib/bit-struct/char-field.rb +3 -3
- data/lib/bit-struct/field.rb +94 -0
- data/lib/bit-struct/fields.rb +13 -13
- data/lib/bit-struct/float-field.rb +4 -4
- data/lib/bit-struct/hex-octet-field.rb +3 -3
- data/lib/bit-struct/nested-field.rb +8 -8
- data/lib/bit-struct/octet-field.rb +4 -4
- data/lib/bit-struct/signed-field.rb +23 -28
- data/lib/bit-struct/text-field.rb +2 -2
- data/lib/bit-struct/unsigned-field.rb +24 -27
- data/lib/bit-struct/vector-field.rb +7 -7
- data/lib/bit-struct/vector.rb +24 -22
- data/lib/bit-struct/yaml.rb +22 -3
- data/test/test-endian.rb +5 -5
- data/test/test-vector.rb +6 -6
- data/test/test.rb +71 -46
- metadata +43 -69
- data/.gitignore +0 -3
- data/TODO +0 -20
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -201
- data/tasks/git.rake +0 -40
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -34
- data/tasks/rdoc.rake +0 -51
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -292
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
- data/tasks/zentest.rake +0 -36
data/examples/longlong.rb
CHANGED
@@ -10,8 +10,8 @@ pkt = MyPacket.new
|
|
10
10
|
pkt.x = 59843759843759843
|
11
11
|
pkt.y = 59843759843759843
|
12
12
|
|
13
|
-
p pkt.x # 59843759843759843
|
14
|
-
p pkt.y # 59843759843759843
|
13
|
+
p pkt.x # 59843759843759843
|
14
|
+
p pkt.y # 59843759843759843
|
15
15
|
|
16
16
|
p pkt
|
17
17
|
# #<MyPacket x=59843759843759843, y=59843759843759843>
|
data/examples/md.rb
CHANGED
data/examples/modular-def.rb
CHANGED
@@ -6,7 +6,7 @@ module ModuleMethodSaver
|
|
6
6
|
@saved ||= []
|
7
7
|
@saved << [meth, args, block]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def included(m)
|
11
11
|
if @saved
|
12
12
|
@saved.each do |meth, args, block|
|
@@ -21,7 +21,7 @@ require 'bit-struct'
|
|
21
21
|
|
22
22
|
module M
|
23
23
|
extend ModuleMethodSaver
|
24
|
-
|
24
|
+
|
25
25
|
unsigned :x, 13
|
26
26
|
signed :y, 7
|
27
27
|
end
|
data/examples/native.rb
CHANGED
@@ -6,15 +6,15 @@ class NativeNumbers < BitStruct
|
|
6
6
|
unsigned :x1, 13, :endian => :native
|
7
7
|
unsigned :x2, 2, :endian => :native
|
8
8
|
unsigned :x3, 32, :endian => :native
|
9
|
-
|
9
|
+
|
10
10
|
float :f1, 32, :endian => :native
|
11
11
|
float :f2, 64, :endian => :native
|
12
12
|
float :f3, 32
|
13
13
|
float :f4, 64
|
14
|
-
|
14
|
+
|
15
15
|
default_options :endian => :native
|
16
16
|
# affects fields defined after this and in subclasses
|
17
|
-
|
17
|
+
|
18
18
|
unsigned :y1, 32
|
19
19
|
|
20
20
|
end
|
data/examples/ping.rb
CHANGED
data/examples/raw.rb
CHANGED
data/examples/switch-endian.rb
CHANGED
@@ -3,7 +3,7 @@ module ModuleMethodSaver
|
|
3
3
|
@saved ||= []
|
4
4
|
@saved << [meth, args, block]
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def included(m)
|
8
8
|
if @saved
|
9
9
|
@saved.each do |meth, args, block|
|
@@ -18,7 +18,7 @@ require 'bit-struct'
|
|
18
18
|
|
19
19
|
module MyFields
|
20
20
|
extend ModuleMethodSaver
|
21
|
-
|
21
|
+
|
22
22
|
unsigned :x, 16
|
23
23
|
end
|
24
24
|
|
data/examples/vector.rb
CHANGED
@@ -5,7 +5,7 @@ class Vec < BitStruct::Vector
|
|
5
5
|
# these declarations apply to *each* entry in the vector:
|
6
6
|
unsigned :x, 16
|
7
7
|
signed :y, 32
|
8
|
-
|
8
|
+
|
9
9
|
Entry = struct_class # Give it a name, just for inspect to look nice
|
10
10
|
end
|
11
11
|
|
@@ -72,7 +72,7 @@ puts
|
|
72
72
|
# Example 4: vector field in a bitstruct
|
73
73
|
class Packet < BitStruct
|
74
74
|
unsigned :stuff, 32, "whatever"
|
75
|
-
|
75
|
+
|
76
76
|
# Using the Vec class defined above
|
77
77
|
vector :v, Vec, "a vector", 5
|
78
78
|
|
data/lib/bit-struct.rb
CHANGED
@@ -1,14 +1,3 @@
|
|
1
|
-
# A Convenience to load all field classes and yaml handling.
|
2
|
-
|
3
|
-
if "a"[0].kind_of? Fixnum
|
4
|
-
unless Fixnum.methods.include? :ord
|
5
|
-
class Fixnum
|
6
|
-
def ord; self; end
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
1
|
require 'bit-struct/bit-struct'
|
12
2
|
require 'bit-struct/fields'
|
13
3
|
require 'bit-struct/yaml'
|
14
|
-
|
@@ -9,100 +9,11 @@
|
|
9
9
|
# The String#replace method is useful.
|
10
10
|
#
|
11
11
|
class BitStruct < String
|
12
|
-
VERSION = "0.
|
13
|
-
|
14
|
-
class Field
|
15
|
-
# Offset of field in bits.
|
16
|
-
attr_reader :offset
|
17
|
-
|
18
|
-
# Length of field in bits.
|
19
|
-
attr_reader :length
|
20
|
-
alias size length
|
21
|
-
|
22
|
-
# Name of field (used for its accessors).
|
23
|
-
attr_reader :name
|
24
|
-
|
25
|
-
# Options, such as :default (varies for each field subclass).
|
26
|
-
# In general, options can be provided as strings or as symbols.
|
27
|
-
attr_reader :options
|
28
|
-
|
29
|
-
# Display name of field (used for printing).
|
30
|
-
attr_reader :display_name
|
31
|
-
|
32
|
-
# Default value.
|
33
|
-
attr_reader :default
|
34
|
-
|
35
|
-
# Format for printed value of field.
|
36
|
-
attr_reader :format
|
37
|
-
|
38
|
-
# Subclasses can override this to define a default for all fields of this
|
39
|
-
# class, not just the one currently being added to a BitStruct class, a
|
40
|
-
# "default default" if you will. The global default, if #default returns
|
41
|
-
# nil, is to fill the field with zero. Most field classes just let this
|
42
|
-
# default stand. The default can be overridden per-field when a BitStruct
|
43
|
-
# class is defined.
|
44
|
-
def self.default; nil; end
|
45
|
-
|
46
|
-
# Used in describe.
|
47
|
-
def self.class_name
|
48
|
-
@class_name ||= name[/\w+$/]
|
49
|
-
end
|
50
|
-
|
51
|
-
# Used in describe. Can be overridden per-subclass, as in NestedField.
|
52
|
-
def class_name
|
53
|
-
self.class.class_name
|
54
|
-
end
|
55
|
-
|
56
|
-
# Yield the description of this field, as an array of 5 strings: byte
|
57
|
-
# offset, type, name, size, and description. The opts hash may have:
|
58
|
-
#
|
59
|
-
# :expand :: if the value is true, expand complex fields
|
60
|
-
#
|
61
|
-
# (Subclass implementations may yield more than once for complex fields.)
|
62
|
-
#
|
63
|
-
def describe opts
|
64
|
-
bits = size
|
65
|
-
if bits > 32 and bits % 8 == 0
|
66
|
-
len_str = "%dB" % (bits/8)
|
67
|
-
else
|
68
|
-
len_str = "%db" % bits
|
69
|
-
end
|
70
|
-
|
71
|
-
byte_offset = offset / 8 + (opts[:byte_offset] || 0)
|
12
|
+
VERSION = "0.17"
|
72
13
|
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
# Options are _display_name_, _default_, and _format_ (subclasses of Field
|
77
|
-
# may add other options).
|
78
|
-
def initialize(offset, length, name, opts = {})
|
79
|
-
@offset, @length, @name, @options =
|
80
|
-
offset, length, name, opts
|
81
|
-
|
82
|
-
@display_name = opts[:display_name] || opts["display_name"]
|
83
|
-
@default = opts[:default] || opts["default"] || self.class.default
|
84
|
-
@format = opts[:format] || opts["format"]
|
85
|
-
end
|
86
|
-
|
87
|
-
# Inspect the value of this field in the specified _obj_.
|
88
|
-
def inspect_in_object(obj, opts)
|
89
|
-
val = obj.send(name)
|
90
|
-
str =
|
91
|
-
begin
|
92
|
-
val.inspect(opts)
|
93
|
-
rescue ArgumentError # assume: "wrong number of arguments (1 for 0)"
|
94
|
-
val.inspect
|
95
|
-
end
|
96
|
-
(f=@format) ? (f % str) : str
|
97
|
-
end
|
98
|
-
|
99
|
-
# Normally, all fields show up in inspect, but some, such as padding,
|
100
|
-
# should not.
|
101
|
-
def inspectable?; true; end
|
102
|
-
end
|
103
|
-
|
14
|
+
require 'bit-struct/field'
|
104
15
|
NULL_FIELD = Field.new(0, 0, :null, :display_name => "null field")
|
105
|
-
|
16
|
+
|
106
17
|
# Raised when a field is added after an instance has been created. Fields
|
107
18
|
# cannot be added after this point.
|
108
19
|
class ClosedClassError < StandardError; end
|
@@ -110,9 +21,9 @@ class BitStruct < String
|
|
110
21
|
# Raised if the chosen field name is not allowed, either because another
|
111
22
|
# field by that name exists, or because a method by that name exists.
|
112
23
|
class FieldNameError < StandardError; end
|
113
|
-
|
24
|
+
|
114
25
|
@default_options = {}
|
115
|
-
|
26
|
+
|
116
27
|
@initial_value = nil
|
117
28
|
@closed = nil
|
118
29
|
@rest_field = nil
|
@@ -127,7 +38,7 @@ class BitStruct < String
|
|
127
38
|
@note = nil
|
128
39
|
end
|
129
40
|
end
|
130
|
-
|
41
|
+
|
131
42
|
# ------------------------
|
132
43
|
# :section: field access methods
|
133
44
|
#
|
@@ -139,7 +50,7 @@ class BitStruct < String
|
|
139
50
|
def fields
|
140
51
|
@fields ||= self == BitStruct ? [] : superclass.fields.dup
|
141
52
|
end
|
142
|
-
|
53
|
+
|
143
54
|
# Return the list of fields defined by this class, not inherited
|
144
55
|
# from the superclass.
|
145
56
|
def own_fields
|
@@ -150,9 +61,9 @@ class BitStruct < String
|
|
150
61
|
def add_field(name, length, opts = {})
|
151
62
|
round_byte_length ## just to make sure this has been calculated
|
152
63
|
## before adding anything
|
153
|
-
|
64
|
+
|
154
65
|
name = name.to_sym
|
155
|
-
|
66
|
+
|
156
67
|
if @closed
|
157
68
|
raise ClosedClassError, "Cannot add field #{name}: " +
|
158
69
|
"The definition of the #{self.inspect} BitStruct class is closed."
|
@@ -169,9 +80,9 @@ class BitStruct < String
|
|
169
80
|
raise FieldNameError,"Field #{name} is already defined as a method."
|
170
81
|
end
|
171
82
|
end
|
172
|
-
|
83
|
+
|
173
84
|
field_class = opts[:field_class]
|
174
|
-
|
85
|
+
|
175
86
|
prev = fields[-1] || NULL_FIELD
|
176
87
|
offset = prev.offset + prev.length
|
177
88
|
field = field_class.new(offset, length, name, opts)
|
@@ -194,13 +105,13 @@ class BitStruct < String
|
|
194
105
|
def parse_options(ary, default_name, default_field_class) # :nodoc:
|
195
106
|
opts = ary.grep(Hash).first || {}
|
196
107
|
opts = default_options.merge(opts)
|
197
|
-
|
108
|
+
|
198
109
|
opts[:display_name] = ary.grep(String).first || default_name
|
199
110
|
opts[:field_class] = ary.grep(Class).first || default_field_class
|
200
|
-
|
111
|
+
|
201
112
|
opts
|
202
113
|
end
|
203
|
-
|
114
|
+
|
204
115
|
# Get or set the hash of default options for the class, which apply to all
|
205
116
|
# fields. Changes take effect immediately, so can be used alternatingly with
|
206
117
|
# blocks of field declarations. If +h+ is provided, update the default
|
@@ -214,17 +125,17 @@ class BitStruct < String
|
|
214
125
|
end
|
215
126
|
@default_options
|
216
127
|
end
|
217
|
-
|
128
|
+
|
218
129
|
# Length, in bits, of this object.
|
219
130
|
def bit_length
|
220
131
|
@bit_length ||= fields.inject(0) {|a, f| a + f.length}
|
221
132
|
end
|
222
|
-
|
133
|
+
|
223
134
|
# Length, in bytes (rounded up), of this object.
|
224
135
|
def round_byte_length
|
225
136
|
@round_byte_length ||= (bit_length/8.0).ceil
|
226
137
|
end
|
227
|
-
|
138
|
+
|
228
139
|
def closed! # :nodoc:
|
229
140
|
@closed = true
|
230
141
|
end
|
@@ -239,12 +150,17 @@ class BitStruct < String
|
|
239
150
|
field
|
240
151
|
end
|
241
152
|
end
|
242
|
-
|
153
|
+
|
243
154
|
# Return the list of fields for this class.
|
244
155
|
def fields
|
245
156
|
self.class.fields
|
246
157
|
end
|
247
|
-
|
158
|
+
|
159
|
+
# Return the rest field for this class.
|
160
|
+
def rest_field
|
161
|
+
self.class.rest_field
|
162
|
+
end
|
163
|
+
|
248
164
|
# Return the field with the given name.
|
249
165
|
def field_by_name name
|
250
166
|
self.class.field_by_name name
|
@@ -261,7 +177,7 @@ class BitStruct < String
|
|
261
177
|
# Default format for describe. Fields are byte, type, name, size,
|
262
178
|
# and description.
|
263
179
|
DESCRIBE_FORMAT = "%8s: %-12s %-14s[%4s] %s"
|
264
|
-
|
180
|
+
|
265
181
|
# Can be overridden to use a different format.
|
266
182
|
def describe_format
|
267
183
|
DESCRIBE_FORMAT
|
@@ -274,7 +190,7 @@ class BitStruct < String
|
|
274
190
|
if fmt.kind_of? Hash
|
275
191
|
opts = fmt; fmt = nil
|
276
192
|
end
|
277
|
-
|
193
|
+
|
278
194
|
if block_given?
|
279
195
|
fields.each do |field|
|
280
196
|
field.describe(opts) do |desc|
|
@@ -282,7 +198,7 @@ class BitStruct < String
|
|
282
198
|
end
|
283
199
|
end
|
284
200
|
nil
|
285
|
-
|
201
|
+
|
286
202
|
else
|
287
203
|
fmt ||= describe_format
|
288
204
|
|
@@ -306,7 +222,7 @@ class BitStruct < String
|
|
306
222
|
result
|
307
223
|
end
|
308
224
|
end
|
309
|
-
|
225
|
+
|
310
226
|
# Subclasses can use this to append a string (or several) to the #describe
|
311
227
|
# output. Notes are not cumulative with inheritance. When used with no
|
312
228
|
# arguments simply returns the note string
|
@@ -315,7 +231,7 @@ class BitStruct < String
|
|
315
231
|
@note
|
316
232
|
end
|
317
233
|
end
|
318
|
-
|
234
|
+
|
319
235
|
# ------------------------
|
320
236
|
# :section: initialization and conversion methods
|
321
237
|
#
|
@@ -334,9 +250,9 @@ class BitStruct < String
|
|
334
250
|
value.each do |k, v|
|
335
251
|
send "#{k}=", v
|
336
252
|
end
|
337
|
-
|
253
|
+
|
338
254
|
when nil
|
339
|
-
|
255
|
+
|
340
256
|
else
|
341
257
|
if value.respond_to?(:read)
|
342
258
|
value = value.read(self.class.round_byte_length)
|
@@ -344,16 +260,16 @@ class BitStruct < String
|
|
344
260
|
|
345
261
|
self[0, value.length] = value
|
346
262
|
end
|
347
|
-
|
263
|
+
|
348
264
|
self.class.closed!
|
349
265
|
yield self if block_given?
|
350
266
|
end
|
351
|
-
|
267
|
+
|
352
268
|
DEFAULT_TO_H_OPTS = {
|
353
269
|
:convert_keys => :to_sym,
|
354
270
|
:include_rest => true
|
355
271
|
}
|
356
|
-
|
272
|
+
|
357
273
|
# Returns a hash of {name=>value,...} for each field. By default, include
|
358
274
|
# the rest field.
|
359
275
|
# Keys are symbols derived from field names using +to_sym+, unless
|
@@ -365,13 +281,13 @@ class BitStruct < String
|
|
365
281
|
if opts[:include_rest] and (rest_field = self.class.rest_field)
|
366
282
|
fields_for_to_h += [rest_field]
|
367
283
|
end
|
368
|
-
|
284
|
+
|
369
285
|
fields_for_to_h.inject({}) do |h,f|
|
370
286
|
h[f.name.send(converter)] = send(f.name)
|
371
287
|
h
|
372
288
|
end
|
373
289
|
end
|
374
|
-
|
290
|
+
|
375
291
|
# Returns an array of values of the fields of the BitStruct. By default,
|
376
292
|
# include the rest field.
|
377
293
|
def to_a(include_rest = true)
|
@@ -379,16 +295,16 @@ class BitStruct < String
|
|
379
295
|
fields.map do |f|
|
380
296
|
send(f.name)
|
381
297
|
end
|
382
|
-
|
298
|
+
|
383
299
|
if include_rest and (rest_field = self.class.rest_field)
|
384
300
|
ary << send(rest_field.name)
|
385
301
|
end
|
302
|
+
ary
|
386
303
|
end
|
387
|
-
|
388
|
-
## temporary hack for 1.9
|
304
|
+
|
389
305
|
if "a"[0].kind_of? String
|
390
306
|
def [](*args)
|
391
|
-
if args.size == 1 and args[0].kind_of?(
|
307
|
+
if args.size == 1 and args[0].kind_of?(Integer)
|
392
308
|
super.ord
|
393
309
|
else
|
394
310
|
super
|
@@ -396,14 +312,14 @@ class BitStruct < String
|
|
396
312
|
end
|
397
313
|
|
398
314
|
def []=(*args)
|
399
|
-
if args.size == 2 and (i=args[0]).kind_of?(
|
315
|
+
if args.size == 2 and (i=args[0]).kind_of?(Integer)
|
400
316
|
super(i, args[1].chr)
|
401
317
|
else
|
402
318
|
super
|
403
319
|
end
|
404
320
|
end
|
405
321
|
end
|
406
|
-
|
322
|
+
|
407
323
|
class << self
|
408
324
|
# The unique "prototype" object from which new instances are copied.
|
409
325
|
# The fields of this instance can be modified in the class definition
|
@@ -417,7 +333,7 @@ class BitStruct < String
|
|
417
333
|
#
|
418
334
|
def initial_value # :yields: the initial value
|
419
335
|
unless @initial_value
|
420
|
-
iv = defined?(superclass.initial_value) ?
|
336
|
+
iv = defined?(superclass.initial_value) ?
|
421
337
|
superclass.initial_value.dup : ""
|
422
338
|
if iv.length < round_byte_length
|
423
339
|
iv << "\0" * (round_byte_length - iv.length)
|
@@ -426,7 +342,7 @@ class BitStruct < String
|
|
426
342
|
@initial_value = "" # Serves as initval while the real initval is inited
|
427
343
|
@initial_value = new(iv)
|
428
344
|
@closed = false # only creating the first _real_ instance closes.
|
429
|
-
|
345
|
+
|
430
346
|
fields.each do |field|
|
431
347
|
@initial_value.send("#{field.name}=", field.default) if field.default
|
432
348
|
end
|
@@ -434,7 +350,7 @@ class BitStruct < String
|
|
434
350
|
yield @initial_value if block_given?
|
435
351
|
@initial_value
|
436
352
|
end
|
437
|
-
|
353
|
+
|
438
354
|
# Take +data+ (a string or BitStruct) and parse it into instances of
|
439
355
|
# the +classes+, returning them in an array. The classes can be given
|
440
356
|
# as an array or a separate arguments. (For parsing a string into a _single_
|
@@ -444,7 +360,7 @@ class BitStruct < String
|
|
444
360
|
c.new(data.slice!(0...c.round_byte_length))
|
445
361
|
end
|
446
362
|
end
|
447
|
-
|
363
|
+
|
448
364
|
# Join the given structs (array or multiple args) as a string.
|
449
365
|
# Actually, the inherited String#+ instance method is the same, as is using
|
450
366
|
# Array#join.
|
@@ -468,7 +384,7 @@ class BitStruct < String
|
|
468
384
|
:include_class => true,
|
469
385
|
:simple_format => "<%s>"
|
470
386
|
}
|
471
|
-
|
387
|
+
|
472
388
|
DETAILED_INSPECT_OPTS = {
|
473
389
|
:format => "%s:\n%s",
|
474
390
|
:field_format => "%30s = %s",
|
@@ -479,32 +395,34 @@ class BitStruct < String
|
|
479
395
|
:include_class => true,
|
480
396
|
:simple_format => "\n%s"
|
481
397
|
}
|
482
|
-
|
398
|
+
|
483
399
|
# A standard inspect method which does not add newlines.
|
484
|
-
def
|
400
|
+
def inspect_with_options(opts = DEFAULT_INSPECT_OPTS)
|
485
401
|
field_format = opts[:field_format]
|
486
402
|
field_name_meth = opts[:field_name_meth]
|
487
|
-
|
403
|
+
|
488
404
|
fields_for_inspect = fields.select {|field| field.inspectable?}
|
489
405
|
if opts[:include_rest] and (rest_field = self.class.rest_field)
|
490
406
|
fields_for_inspect << rest_field
|
491
407
|
end
|
492
|
-
|
408
|
+
|
493
409
|
ary = fields_for_inspect.map do |field|
|
494
410
|
field_format %
|
495
411
|
[field.send(field_name_meth),
|
496
412
|
field.inspect_in_object(self, opts)]
|
497
413
|
end
|
498
|
-
|
414
|
+
|
499
415
|
body = ary.join(opts[:separator])
|
500
|
-
|
416
|
+
|
501
417
|
if opts[:include_class]
|
502
418
|
opts[:format] % [self.class, body]
|
503
419
|
else
|
504
420
|
opts[:simple_format] % body
|
505
421
|
end
|
506
422
|
end
|
507
|
-
|
423
|
+
|
424
|
+
alias inspect inspect_with_options
|
425
|
+
|
508
426
|
# A more visually appealing inspect method that puts each field/value on
|
509
427
|
# a separate line. Very useful when output is scrolling by on a screen.
|
510
428
|
#
|
@@ -518,7 +436,7 @@ class BitStruct < String
|
|
518
436
|
# :section: field declaration methods
|
519
437
|
#
|
520
438
|
# ------------------------
|
521
|
-
|
439
|
+
|
522
440
|
# Define accessors for a variable length substring from the end of
|
523
441
|
# the defined fields to the end of the BitStruct. The _rest_ may behave as
|
524
442
|
# a String or as some other String or BitStruct subclass.
|
@@ -536,13 +454,13 @@ class BitStruct < String
|
|
536
454
|
# If a hash is provided, use it for options.
|
537
455
|
#
|
538
456
|
# *Warning*: the rest reader method returns a copy of the field, so
|
539
|
-
# accessors on that returned value do not affect the original rest field.
|
457
|
+
# accessors on that returned value do not affect the original rest field.
|
540
458
|
#
|
541
459
|
def self.rest(name, *ary)
|
542
460
|
if @rest_field
|
543
461
|
raise ArgumentError, "Duplicate rest field: #{name.inspect}."
|
544
462
|
end
|
545
|
-
|
463
|
+
|
546
464
|
opts = parse_options(ary, name, String)
|
547
465
|
offset = round_byte_length
|
548
466
|
byte_range = offset..-1
|
@@ -555,14 +473,14 @@ class BitStruct < String
|
|
555
473
|
define_method "#{name}=" do |val|
|
556
474
|
self[byte_range] = val
|
557
475
|
end
|
558
|
-
|
476
|
+
|
559
477
|
@rest_field = Field.new(offset, -1, name, {
|
560
478
|
:display_name => opts[:display_name],
|
561
479
|
:rest_class => field_class
|
562
480
|
})
|
563
481
|
end
|
564
482
|
end
|
565
|
-
|
483
|
+
|
566
484
|
# Not included with the other fields, but accessible separately.
|
567
485
|
def self.rest_field; @rest_field; end
|
568
486
|
end
|