bindata 2.3.3 → 2.3.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of bindata might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ChangeLog.rdoc +4 -0
- data/Rakefile +2 -2
- data/examples/gzip.rb +24 -24
- data/examples/ip_address.rb +3 -4
- data/examples/list.rb +20 -20
- data/examples/nbt.rb +14 -14
- data/examples/tcp_ip.rb +12 -14
- data/lib/bindata/alignment.rb +2 -2
- data/lib/bindata/array.rb +22 -23
- data/lib/bindata/base.rb +13 -12
- data/lib/bindata/base_primitive.rb +20 -17
- data/lib/bindata/bits.rb +4 -4
- data/lib/bindata/buffer.rb +5 -5
- data/lib/bindata/choice.rb +11 -13
- data/lib/bindata/count_bytes_remaining.rb +1 -2
- data/lib/bindata/delayed_io.rb +11 -11
- data/lib/bindata/dsl.rb +57 -64
- data/lib/bindata/float.rb +16 -13
- data/lib/bindata/int.rb +6 -6
- data/lib/bindata/io.rb +16 -16
- data/lib/bindata/lazy.rb +3 -3
- data/lib/bindata/name.rb +2 -2
- data/lib/bindata/offset.rb +3 -3
- data/lib/bindata/params.rb +13 -15
- data/lib/bindata/primitive.rb +3 -3
- data/lib/bindata/registry.rb +12 -12
- data/lib/bindata/rest.rb +1 -2
- data/lib/bindata/sanitize.rb +17 -18
- data/lib/bindata/skip.rb +7 -8
- data/lib/bindata/string.rb +6 -6
- data/lib/bindata/stringz.rb +3 -3
- data/lib/bindata/struct.rb +16 -16
- data/lib/bindata/trace.rb +9 -8
- data/lib/bindata/version.rb +1 -1
- data/lib/bindata/virtual.rb +3 -3
- data/lib/bindata/warnings.rb +6 -2
- data/test/alignment_test.rb +4 -4
- data/test/array_test.rb +29 -29
- data/test/base_primitive_test.rb +17 -17
- data/test/base_test.rb +6 -6
- data/test/bits_test.rb +1 -1
- data/test/buffer_test.rb +19 -19
- data/test/choice_test.rb +20 -20
- data/test/count_bytes_remaining_test.rb +1 -1
- data/test/delayed_io_test.rb +26 -26
- data/test/lazy_test.rb +16 -16
- data/test/offset_test.rb +8 -8
- data/test/params_test.rb +11 -11
- data/test/primitive_test.rb +11 -11
- data/test/record_test.rb +50 -50
- data/test/registry_test.rb +26 -26
- data/test/rest_test.rb +1 -1
- data/test/skip_test.rb +27 -27
- data/test/string_test.rb +24 -24
- data/test/stringz_test.rb +1 -1
- data/test/struct_test.rb +76 -75
- data/test/system_test.rb +51 -51
- data/test/virtual_test.rb +3 -3
- metadata +2 -2
data/lib/bindata/base.rb
CHANGED
@@ -29,7 +29,7 @@ module BinData
|
|
29
29
|
if name
|
30
30
|
@arg_processor = "#{name}_arg_processor".gsub(/(?:^|_)(.)/) { $1.upcase }.to_sym
|
31
31
|
elsif @arg_processor.is_a? Symbol
|
32
|
-
@arg_processor = BinData
|
32
|
+
@arg_processor = BinData.const_get(@arg_processor).new
|
33
33
|
elsif @arg_processor.nil?
|
34
34
|
@arg_processor = superclass.arg_processor
|
35
35
|
else
|
@@ -39,7 +39,7 @@ module BinData
|
|
39
39
|
|
40
40
|
# The name of this class as used by Records, Arrays etc.
|
41
41
|
def bindata_name
|
42
|
-
RegisteredClasses.underscore_name(
|
42
|
+
RegisteredClasses.underscore_name(name)
|
43
43
|
end
|
44
44
|
|
45
45
|
# Call this method if this class is abstract and not to be used.
|
@@ -109,7 +109,7 @@ module BinData
|
|
109
109
|
# Returns nil if +key+ does not refer to any parameter.
|
110
110
|
def eval_parameter(key, overrides = nil)
|
111
111
|
value = get_parameter(key)
|
112
|
-
if value.is_a?(Symbol)
|
112
|
+
if value.is_a?(Symbol) || value.respond_to?(:arity)
|
113
113
|
lazy_evaluator.lazy_eval(value, overrides)
|
114
114
|
else
|
115
115
|
value
|
@@ -239,7 +239,8 @@ module BinData
|
|
239
239
|
def safe_respond_to?(symbol, include_private = false) #:nodoc:
|
240
240
|
base_respond_to?(symbol, include_private)
|
241
241
|
end
|
242
|
-
|
242
|
+
|
243
|
+
alias base_respond_to? respond_to?
|
243
244
|
|
244
245
|
#---------------
|
245
246
|
private
|
@@ -248,9 +249,9 @@ module BinData
|
|
248
249
|
self.class.arg_processor.extract_args(self.class, args)
|
249
250
|
end
|
250
251
|
|
251
|
-
def start_read
|
252
|
+
def start_read
|
252
253
|
top_level_set(:in_read, true)
|
253
|
-
|
254
|
+
yield
|
254
255
|
ensure
|
255
256
|
top_level_set(:in_read, false)
|
256
257
|
end
|
@@ -266,7 +267,7 @@ module BinData
|
|
266
267
|
|
267
268
|
def top_level_get(sym)
|
268
269
|
tl = top_level
|
269
|
-
tl.instance_variable_defined?("@tl_#{sym}")
|
270
|
+
tl.instance_variable_defined?("@tl_#{sym}") &&
|
270
271
|
tl.instance_variable_get("@tl_#{sym}")
|
271
272
|
end
|
272
273
|
|
@@ -305,15 +306,15 @@ module BinData
|
|
305
306
|
|
306
307
|
# Separates the arguments passed to BinData::Base.new into
|
307
308
|
# [value, parameters, parent]. Called by #extract_args.
|
308
|
-
def separate_args(
|
309
|
+
def separate_args(_obj_class, obj_args)
|
309
310
|
args = obj_args.dup
|
310
311
|
value = parameters = parent = nil
|
311
312
|
|
312
|
-
if args.length > 1
|
313
|
+
if args.length > 1 && args.last.is_a?(BinData::Base)
|
313
314
|
parent = args.pop
|
314
315
|
end
|
315
316
|
|
316
|
-
if args.length > 0
|
317
|
+
if args.length > 0 && args.last.is_a?(Hash)
|
317
318
|
parameters = args.pop
|
318
319
|
end
|
319
320
|
|
@@ -323,13 +324,13 @@ module BinData
|
|
323
324
|
|
324
325
|
parameters ||= @@empty_hash
|
325
326
|
|
326
|
-
|
327
|
+
[value, parameters, parent]
|
327
328
|
end
|
328
329
|
|
329
330
|
# Performs sanity checks on the given parameters.
|
330
331
|
# This method converts the parameters to the form expected
|
331
332
|
# by the data object.
|
332
|
-
def sanitize_parameters!(obj_class, obj_params)
|
333
|
+
def sanitize_parameters!(obj_class, obj_params)
|
333
334
|
end
|
334
335
|
end
|
335
336
|
end
|
@@ -8,22 +8,22 @@ module BinData
|
|
8
8
|
#
|
9
9
|
# require 'bindata'
|
10
10
|
#
|
11
|
-
# obj = BinData::Uint8.new(:
|
11
|
+
# obj = BinData::Uint8.new(initial_value: 42)
|
12
12
|
# obj #=> 42
|
13
13
|
# obj.assign(5)
|
14
14
|
# obj #=> 5
|
15
15
|
# obj.clear
|
16
16
|
# obj #=> 42
|
17
17
|
#
|
18
|
-
# obj = BinData::Uint8.new(:
|
18
|
+
# obj = BinData::Uint8.new(value: 42)
|
19
19
|
# obj #=> 42
|
20
20
|
# obj.assign(5)
|
21
21
|
# obj #=> 42
|
22
22
|
#
|
23
|
-
# obj = BinData::Uint8.new(:
|
23
|
+
# obj = BinData::Uint8.new(assert: 3)
|
24
24
|
# obj.read("\005") #=> BinData::ValidityError: value is '5' but expected '3'
|
25
25
|
#
|
26
|
-
# obj = BinData::Uint8.new(:
|
26
|
+
# obj = BinData::Uint8.new(assert: -> { value < 5 })
|
27
27
|
# obj.read("\007") #=> BinData::ValidityError: value not as expected
|
28
28
|
#
|
29
29
|
# == Parameters
|
@@ -44,7 +44,7 @@ module BinData
|
|
44
44
|
# parameter. A boolean return indicates success
|
45
45
|
# or failure. Any other return is compared to
|
46
46
|
# the value just read in.
|
47
|
-
# [<tt>:asserted_value</tt>]
|
47
|
+
# [<tt>:asserted_value</tt>] Equivalent to <tt>:assert</tt> and <tt>:value</tt>.
|
48
48
|
#
|
49
49
|
class BasePrimitive < BinData::Base
|
50
50
|
unregister_self
|
@@ -101,6 +101,9 @@ module BinData
|
|
101
101
|
def method_missing(symbol, *args, &block) #:nodoc:
|
102
102
|
child = snapshot
|
103
103
|
if child.respond_to?(symbol)
|
104
|
+
self.class.class_eval "def #{symbol}(*args, &block);" \
|
105
|
+
" snapshot.#{symbol}(*args, &block);" \
|
106
|
+
"end"
|
104
107
|
child.__send__(symbol, *args, &block)
|
105
108
|
else
|
106
109
|
super
|
@@ -139,7 +142,7 @@ module BinData
|
|
139
142
|
# method. This indirection is so that #snapshot can be overridden in
|
140
143
|
# subclasses to modify the presentation value.
|
141
144
|
def _value
|
142
|
-
@value != nil ? @value : sensible_default
|
145
|
+
@value != nil ? @value : sensible_default
|
143
146
|
end
|
144
147
|
|
145
148
|
# Logic for the :value parameter
|
@@ -174,15 +177,15 @@ module BinData
|
|
174
177
|
|
175
178
|
def assert!
|
176
179
|
current_value = snapshot
|
177
|
-
expected = eval_parameter(:assert, :
|
178
|
-
|
179
|
-
msg = if
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
180
|
+
expected = eval_parameter(:assert, value: current_value)
|
181
|
+
|
182
|
+
msg = if !expected
|
183
|
+
"value '#{current_value}' not as expected"
|
184
|
+
elsif expected != true && current_value != expected
|
185
|
+
"value is '#{current_value}' but expected '#{expected}'"
|
186
|
+
else
|
187
|
+
nil
|
188
|
+
end
|
186
189
|
|
187
190
|
raise ValidityError, "#{msg} for #{debug_name}" if msg
|
188
191
|
end
|
@@ -209,10 +212,10 @@ module BinData
|
|
209
212
|
end
|
210
213
|
|
211
214
|
def assert_value(current_value)
|
212
|
-
expected = eval_parameter(:asserted_value, :
|
215
|
+
expected = eval_parameter(:asserted_value, value: current_value)
|
213
216
|
if current_value != expected
|
214
217
|
raise ValidityError,
|
215
|
-
"value is '#{current_value}' but "
|
218
|
+
"value is '#{current_value}' but " \
|
216
219
|
"expected '#{expected}' for #{debug_name}"
|
217
220
|
end
|
218
221
|
end
|
data/lib/bindata/bits.rb
CHANGED
@@ -86,13 +86,13 @@ module BinData
|
|
86
86
|
|
87
87
|
def create_clamp_code(nbits, signed)
|
88
88
|
if nbits == :nbits
|
89
|
-
create_dynamic_clamp_code(
|
89
|
+
create_dynamic_clamp_code(signed)
|
90
90
|
else
|
91
91
|
create_fixed_clamp_code(nbits, signed)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
-
def create_dynamic_clamp_code(
|
95
|
+
def create_dynamic_clamp_code(signed)
|
96
96
|
if signed == :signed
|
97
97
|
max = "max = (1 << (nbits - 1)) - 1"
|
98
98
|
min = "min = -(max + 1)"
|
@@ -105,8 +105,8 @@ module BinData
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def create_fixed_clamp_code(nbits, signed)
|
108
|
-
if nbits == 1
|
109
|
-
raise "signed bitfield must have more than one bit"
|
108
|
+
if nbits == 1 && signed == :signed
|
109
|
+
raise "signed bitfield must have more than one bit"
|
110
110
|
end
|
111
111
|
|
112
112
|
if signed == :signed
|
data/lib/bindata/buffer.rb
CHANGED
@@ -9,12 +9,12 @@ module BinData
|
|
9
9
|
#
|
10
10
|
# require 'bindata'
|
11
11
|
#
|
12
|
-
# obj = BinData::Buffer.new(:
|
12
|
+
# obj = BinData::Buffer.new(length: 5, type: [:string, {value: "abc"}])
|
13
13
|
# obj.to_binary_s #=> "abc\000\000"
|
14
14
|
#
|
15
15
|
#
|
16
16
|
# class MyBuffer < BinData::Buffer
|
17
|
-
# default_parameter :
|
17
|
+
# default_parameter length: 8
|
18
18
|
#
|
19
19
|
# endian :little
|
20
20
|
#
|
@@ -34,10 +34,10 @@ module BinData
|
|
34
34
|
# endian :little
|
35
35
|
#
|
36
36
|
# uint16 :table_size_in_bytes
|
37
|
-
# buffer :strings, :
|
38
|
-
# array :
|
37
|
+
# buffer :strings, length: :table_size_in_bytes do
|
38
|
+
# array read_until: :eof do
|
39
39
|
# uint8 :len
|
40
|
-
# string :str, :
|
40
|
+
# string :str, length: :len
|
41
41
|
# end
|
42
42
|
# end
|
43
43
|
# end
|
data/lib/bindata/choice.rb
CHANGED
@@ -8,19 +8,19 @@ module BinData
|
|
8
8
|
#
|
9
9
|
# require 'bindata'
|
10
10
|
#
|
11
|
-
# type1 = [:string, {:
|
12
|
-
# type2 = [:string, {:
|
11
|
+
# type1 = [:string, {value: "Type1"}]
|
12
|
+
# type2 = [:string, {value: "Type2"}]
|
13
13
|
#
|
14
14
|
# choices = {5 => type1, 17 => type2}
|
15
|
-
# a = BinData::Choice.new(:
|
15
|
+
# a = BinData::Choice.new(choices: choices, selection: 5)
|
16
16
|
# a # => "Type1"
|
17
17
|
#
|
18
18
|
# choices = [ type1, type2 ]
|
19
|
-
# a = BinData::Choice.new(:
|
19
|
+
# a = BinData::Choice.new(choices: choices, selection: 1)
|
20
20
|
# a # => "Type2"
|
21
21
|
#
|
22
22
|
# choices = [ nil, nil, nil, type1, nil, type2 ]
|
23
|
-
# a = BinData::Choice.new(:
|
23
|
+
# a = BinData::Choice.new(choices: choices, selection: 3)
|
24
24
|
# a # => "Type1"
|
25
25
|
#
|
26
26
|
#
|
@@ -29,8 +29,8 @@ module BinData
|
|
29
29
|
# mychoice.choice = 'big'
|
30
30
|
#
|
31
31
|
# choices = {'big' => :uint16be, 'little' => :uint16le}
|
32
|
-
# a = BinData::Choice.new(:
|
33
|
-
# :
|
32
|
+
# a = BinData::Choice.new(choices: choices, copy_on_change: true,
|
33
|
+
# selection: -> { mychoice.choice })
|
34
34
|
# a.assign(256)
|
35
35
|
# a.to_binary_s #=> "\001\000"
|
36
36
|
#
|
@@ -94,7 +94,7 @@ module BinData
|
|
94
94
|
end
|
95
95
|
|
96
96
|
%w(clear? assign snapshot do_read do_write do_num_bytes).each do |m|
|
97
|
-
|
97
|
+
module_eval <<-END
|
98
98
|
def #{m}(*args)
|
99
99
|
current_choice.#{m}(*args)
|
100
100
|
end
|
@@ -149,10 +149,10 @@ module BinData
|
|
149
149
|
end
|
150
150
|
|
151
151
|
def ensure_valid_keys(choices)
|
152
|
-
if choices.
|
152
|
+
if choices.key?(nil)
|
153
153
|
raise ArgumentError, ":choices hash may not have nil key"
|
154
154
|
end
|
155
|
-
if choices.keys.detect { |key| key.is_a?(Symbol)
|
155
|
+
if choices.keys.detect { |key| key.is_a?(Symbol) && key != :default }
|
156
156
|
raise ArgumentError, ":choices hash may not have symbols for keys"
|
157
157
|
end
|
158
158
|
end
|
@@ -174,10 +174,8 @@ module BinData
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def get_previous_choice(selection)
|
177
|
-
if
|
177
|
+
if @last_selection && selection != @last_selection
|
178
178
|
@choices[@last_selection]
|
179
|
-
else
|
180
|
-
nil
|
181
179
|
end
|
182
180
|
end
|
183
181
|
|
@@ -9,14 +9,13 @@ module BinData
|
|
9
9
|
#
|
10
10
|
# class A < BinData::Record
|
11
11
|
# count_bytes_remaining :bytes_remaining
|
12
|
-
# string :all_data, :
|
12
|
+
# string :all_data, read_length: :bytes_remaining
|
13
13
|
# end
|
14
14
|
#
|
15
15
|
# obj = A.read("abcdefghij")
|
16
16
|
# obj.all_data #=> "abcdefghij"
|
17
17
|
#
|
18
18
|
class CountBytesRemaining < BinData::BasePrimitive
|
19
|
-
|
20
19
|
#---------------
|
21
20
|
private
|
22
21
|
|
data/lib/bindata/delayed_io.rb
CHANGED
@@ -13,7 +13,7 @@ module BinData
|
|
13
13
|
#
|
14
14
|
# require 'bindata'
|
15
15
|
#
|
16
|
-
# obj = BinData::DelayedIO.new(:
|
16
|
+
# obj = BinData::DelayedIO.new(read_abs_offset: 3, type: :uint16be)
|
17
17
|
# obj.read("\x00\x00\x00\x11\x12")
|
18
18
|
# obj #=> 0
|
19
19
|
#
|
@@ -32,12 +32,12 @@ module BinData
|
|
32
32
|
# class ReversePascalString < BinData::Record
|
33
33
|
# auto_call_delayed_io
|
34
34
|
#
|
35
|
-
# delayed_io :str, :
|
36
|
-
# string :
|
35
|
+
# delayed_io :str, read_abs_offset: 0 do
|
36
|
+
# string read_length: :len
|
37
37
|
# end
|
38
38
|
# count_bytes_remaining :total_size
|
39
|
-
# skip :
|
40
|
-
# uint8 :len, :
|
39
|
+
# skip to_abs_offset: -> { total_size - 1 }
|
40
|
+
# uint8 :len, value: -> { str.length }
|
41
41
|
# end
|
42
42
|
#
|
43
43
|
# s = ReversePascalString.read("hello\x05")
|
@@ -119,7 +119,7 @@ module BinData
|
|
119
119
|
# DelayedIO objects aren't read when #read is called.
|
120
120
|
# The reading is delayed until this method is called.
|
121
121
|
def read_now!
|
122
|
-
raise IOError
|
122
|
+
raise IOError, "read from where?" unless @read_io
|
123
123
|
|
124
124
|
@read_io.seekbytes(abs_offset - @read_io.offset)
|
125
125
|
start_read do
|
@@ -130,7 +130,7 @@ module BinData
|
|
130
130
|
# DelayedIO objects aren't written when #write is called.
|
131
131
|
# The writing is delayed until this method is called.
|
132
132
|
def write_now!
|
133
|
-
raise IOError
|
133
|
+
raise IOError, "write to where?" unless @write_io
|
134
134
|
@write_io.seekbytes(abs_offset - @write_io.offset)
|
135
135
|
@type.do_write(@write_io)
|
136
136
|
end
|
@@ -161,7 +161,7 @@ module BinData
|
|
161
161
|
|
162
162
|
DelayedIO.send(:alias_method, :initialize_instance_without_record_io, :initialize_instance)
|
163
163
|
DelayedIO.send(:define_method, :initialize_instance) do
|
164
|
-
if @parent
|
164
|
+
if @parent && !defined? @delayed_io_recorded
|
165
165
|
@delayed_io_recorded = true
|
166
166
|
list = top_level_get(:delayed_ios)
|
167
167
|
list << self if list
|
@@ -179,11 +179,11 @@ module BinData
|
|
179
179
|
end
|
180
180
|
|
181
181
|
def read(io)
|
182
|
-
super(io) { top_level_get(:delayed_ios).each
|
182
|
+
super(io) { top_level_get(:delayed_ios).each(&:read_now!) }
|
183
183
|
end
|
184
184
|
|
185
|
-
def write(io, *
|
186
|
-
super(io) { top_level_get(:delayed_ios).each
|
185
|
+
def write(io, *_)
|
186
|
+
super(io) { top_level_get(:delayed_ios).each(&:write_now!) }
|
187
187
|
end
|
188
188
|
|
189
189
|
def num_bytes
|
data/lib/bindata/dsl.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module BinData
|
2
2
|
# Extracts args for Records and Buffers.
|
3
3
|
#
|
4
|
-
# Foo.new(:
|
4
|
+
# Foo.new(bar: "baz) is ambiguous as to whether :bar is a value or parameter.
|
5
5
|
#
|
6
6
|
# BaseArgExtractor always assumes :bar is parameter. This extractor correctly
|
7
7
|
# identifies it as value or parameter.
|
@@ -18,7 +18,7 @@ module BinData
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def parameters_is_value?(obj_class, value, parameters)
|
21
|
-
if value.nil?
|
21
|
+
if value.nil? && !parameters.empty?
|
22
22
|
field_names_in_parameters?(obj_class, parameters)
|
23
23
|
else
|
24
24
|
false
|
@@ -29,18 +29,17 @@ module BinData
|
|
29
29
|
field_names = obj_class.fields.field_names
|
30
30
|
param_keys = parameters.keys
|
31
31
|
|
32
|
-
(field_names & param_keys).
|
32
|
+
!(field_names & param_keys).empty?
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
# BinData classes that are part of the DSL must be extended by this.
|
37
37
|
module DSLMixin
|
38
38
|
def dsl_parser(parser_type = nil)
|
39
|
-
|
40
|
-
parser_type
|
41
|
-
|
39
|
+
@dsl_parser ||= begin
|
40
|
+
parser_type ||= superclass.dsl_parser.parser_type
|
41
|
+
DSLParser.new(self, parser_type)
|
42
42
|
end
|
43
|
-
@dsl_parser
|
44
43
|
end
|
45
44
|
|
46
45
|
def method_missing(symbol, *args, &block) #:nodoc:
|
@@ -82,13 +81,11 @@ module BinData
|
|
82
81
|
end
|
83
82
|
|
84
83
|
def search_prefix(*args)
|
85
|
-
|
86
|
-
@search_prefix = parent_attribute(:search_prefix, []).dup
|
87
|
-
end
|
84
|
+
@search_prefix ||= parent_attribute(:search_prefix, []).dup
|
88
85
|
|
89
|
-
prefix = args.collect
|
90
|
-
|
91
|
-
if
|
86
|
+
prefix = args.collect(&:to_sym).compact
|
87
|
+
unless prefix.empty?
|
88
|
+
if fields?
|
92
89
|
dsl_raise SyntaxError, "search_prefix must be called before defining fields"
|
93
90
|
end
|
94
91
|
|
@@ -100,25 +97,21 @@ module BinData
|
|
100
97
|
|
101
98
|
def hide(*args)
|
102
99
|
if option?(:hidden_fields)
|
103
|
-
|
100
|
+
@hide ||= parent_attribute(:hide, []).dup
|
104
101
|
|
105
|
-
|
106
|
-
|
107
|
-
end
|
102
|
+
hidden = args.collect(&:to_sym).compact
|
103
|
+
@hide.concat(hidden)
|
108
104
|
|
109
|
-
@hide.concat(hidden.compact)
|
110
105
|
@hide
|
111
106
|
end
|
112
107
|
end
|
113
108
|
|
114
109
|
def fields
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
110
|
+
@fields ||= begin
|
111
|
+
SanitizedFields.new(hints).tap do |san_fields|
|
112
|
+
san_fields.copy_fields(parent_fields) if parent_fields
|
113
|
+
end
|
119
114
|
end
|
120
|
-
|
121
|
-
@fields
|
122
115
|
end
|
123
116
|
|
124
117
|
def dsl_params
|
@@ -136,13 +129,13 @@ module BinData
|
|
136
129
|
|
137
130
|
def parser_abilities
|
138
131
|
@abilities ||= {
|
139
|
-
:
|
140
|
-
:
|
141
|
-
:
|
142
|
-
:
|
143
|
-
:
|
144
|
-
:
|
145
|
-
:
|
132
|
+
struct: [:to_struct_params, :struct, [:multiple_fields, :optional_fieldnames, :hidden_fields]],
|
133
|
+
array: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames]],
|
134
|
+
buffer: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames, :hidden_fields]],
|
135
|
+
choice: [:to_choice_params, :choices, [:multiple_fields, :all_or_none_fieldnames, :fieldnames_are_values]],
|
136
|
+
delayed_io: [:to_object_params, :type, [:multiple_fields, :optional_fieldnames, :hidden_fields]],
|
137
|
+
primitive: [:to_struct_params, :struct, [:multiple_fields, :optional_fieldnames]],
|
138
|
+
skip: [:to_object_params, :until_valid, [:multiple_fields, :optional_fieldnames]],
|
146
139
|
}
|
147
140
|
end
|
148
141
|
|
@@ -156,15 +149,15 @@ module BinData
|
|
156
149
|
end
|
157
150
|
|
158
151
|
def hints
|
159
|
-
{ :
|
152
|
+
{ endian: endian, search_prefix: search_prefix }
|
160
153
|
end
|
161
154
|
|
162
155
|
def set_endian(endian)
|
163
156
|
if endian
|
164
|
-
if
|
157
|
+
if fields?
|
165
158
|
dsl_raise SyntaxError, "endian must be called before defining fields"
|
166
159
|
end
|
167
|
-
if
|
160
|
+
if !valid_endian?(endian)
|
168
161
|
dsl_raise ArgumentError, "unknown value for endian '#{endian}'"
|
169
162
|
end
|
170
163
|
|
@@ -184,8 +177,8 @@ module BinData
|
|
184
177
|
parent_attribute(:fields)
|
185
178
|
end
|
186
179
|
|
187
|
-
def
|
188
|
-
defined?
|
180
|
+
def fields?
|
181
|
+
defined?(@fields) && !@fields.empty?
|
189
182
|
end
|
190
183
|
|
191
184
|
def parse_and_append_field(*args, &block)
|
@@ -207,18 +200,18 @@ module BinData
|
|
207
200
|
def parent_attribute(attr, default = nil)
|
208
201
|
parent = @the_class.superclass
|
209
202
|
parser = parent.respond_to?(:dsl_parser) ? parent.dsl_parser : nil
|
210
|
-
if parser
|
203
|
+
if parser && parser.respond_to?(attr)
|
211
204
|
parser.send(attr)
|
212
205
|
else
|
213
206
|
default
|
214
207
|
end
|
215
208
|
end
|
216
209
|
|
217
|
-
def dsl_raise(exception,
|
210
|
+
def dsl_raise(exception, msg)
|
218
211
|
backtrace = caller
|
219
212
|
backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
|
220
213
|
|
221
|
-
raise exception,
|
214
|
+
raise exception, "#{msg} in #{@the_class}", backtrace
|
222
215
|
end
|
223
216
|
|
224
217
|
def to_object_params(key)
|
@@ -233,10 +226,10 @@ module BinData
|
|
233
226
|
end
|
234
227
|
|
235
228
|
def to_choice_params(key)
|
236
|
-
if fields.
|
229
|
+
if fields.empty?
|
237
230
|
{}
|
238
231
|
elsif fields.all_field_names_blank?
|
239
|
-
{key => fields.collect
|
232
|
+
{key => fields.collect(&:prototype)}
|
240
233
|
else
|
241
234
|
choices = {}
|
242
235
|
fields.each { |f| choices[f.name] = f.prototype }
|
@@ -245,14 +238,14 @@ module BinData
|
|
245
238
|
end
|
246
239
|
|
247
240
|
def to_struct_params(*unused)
|
248
|
-
result = {:
|
249
|
-
if
|
241
|
+
result = {fields: fields}
|
242
|
+
if !endian.nil?
|
250
243
|
result[:endian] = endian
|
251
244
|
end
|
252
|
-
if
|
245
|
+
if !search_prefix.empty?
|
253
246
|
result[:search_prefix] = search_prefix
|
254
247
|
end
|
255
|
-
if option?(:hidden_fields)
|
248
|
+
if option?(:hidden_fields) && !hide.empty?
|
256
249
|
result[:hide] = hide
|
257
250
|
end
|
258
251
|
|
@@ -284,8 +277,8 @@ module BinData
|
|
284
277
|
|
285
278
|
def override_new_in_class(bnl_class)
|
286
279
|
endian_classes = {
|
287
|
-
:
|
288
|
-
:
|
280
|
+
big: class_with_endian(bnl_class, :big),
|
281
|
+
little: class_with_endian(bnl_class, :little),
|
289
282
|
}
|
290
283
|
bnl_class.define_singleton_method(:new) do |*args|
|
291
284
|
if self == bnl_class
|
@@ -300,8 +293,8 @@ module BinData
|
|
300
293
|
|
301
294
|
def delegate_field_creation(bnl_class)
|
302
295
|
endian_classes = {
|
303
|
-
:
|
304
|
-
:
|
296
|
+
big: class_with_endian(bnl_class, :big),
|
297
|
+
little: class_with_endian(bnl_class, :little),
|
305
298
|
}
|
306
299
|
|
307
300
|
parser = bnl_class.dsl_parser
|
@@ -333,8 +326,8 @@ module BinData
|
|
333
326
|
|
334
327
|
def class_with_endian(class_name, endian)
|
335
328
|
hints = {
|
336
|
-
:
|
337
|
-
:
|
329
|
+
endian: endian,
|
330
|
+
search_prefix: class_name.dsl_parser.search_prefix,
|
338
331
|
}
|
339
332
|
RegisteredClasses.lookup(class_name, hints)
|
340
333
|
end
|
@@ -358,7 +351,7 @@ module BinData
|
|
358
351
|
|
359
352
|
def name_from_field_declaration(args)
|
360
353
|
name, _ = args
|
361
|
-
if name == ""
|
354
|
+
if name == "" || name.is_a?(Hash)
|
362
355
|
nil
|
363
356
|
else
|
364
357
|
name
|
@@ -384,12 +377,12 @@ module BinData
|
|
384
377
|
|
385
378
|
def params_from_block(&block)
|
386
379
|
bindata_classes = {
|
387
|
-
:
|
388
|
-
:
|
389
|
-
:
|
390
|
-
:
|
391
|
-
:
|
392
|
-
:
|
380
|
+
array: BinData::Array,
|
381
|
+
buffer: BinData::Buffer,
|
382
|
+
choice: BinData::Choice,
|
383
|
+
delayed_io: BinData::DelayedIO,
|
384
|
+
skip: BinData::Skip,
|
385
|
+
struct: BinData::Struct,
|
393
386
|
}
|
394
387
|
|
395
388
|
if bindata_classes.include?(@type)
|
@@ -429,7 +422,7 @@ module BinData
|
|
429
422
|
end
|
430
423
|
|
431
424
|
def ensure_valid_name(name)
|
432
|
-
if name
|
425
|
+
if name && !option?(:fieldnames_are_values)
|
433
426
|
if malformed_name?(name)
|
434
427
|
raise NameError.new("", name), "field '#{name}' is an illegal fieldname"
|
435
428
|
end
|
@@ -449,19 +442,19 @@ module BinData
|
|
449
442
|
end
|
450
443
|
|
451
444
|
def must_not_have_a_name_failed?(name)
|
452
|
-
option?(:no_fieldnames)
|
445
|
+
option?(:no_fieldnames) && !name.nil?
|
453
446
|
end
|
454
447
|
|
455
448
|
def must_have_a_name_failed?(name)
|
456
|
-
option?(:mandatory_fieldnames)
|
449
|
+
option?(:mandatory_fieldnames) && name.nil?
|
457
450
|
end
|
458
451
|
|
459
452
|
def all_or_none_names_failed?(name)
|
460
|
-
if option?(:all_or_none_fieldnames)
|
453
|
+
if option?(:all_or_none_fieldnames) && !fields.empty?
|
461
454
|
all_names_blank = fields.all_field_names_blank?
|
462
455
|
no_names_blank = fields.no_field_names_blank?
|
463
456
|
|
464
|
-
(name
|
457
|
+
(!name.nil? && all_names_blank) || (name.nil? && no_names_blank)
|
465
458
|
else
|
466
459
|
false
|
467
460
|
end
|
@@ -472,7 +465,7 @@ module BinData
|
|
472
465
|
end
|
473
466
|
|
474
467
|
def duplicate_name?(name)
|
475
|
-
fields.
|
468
|
+
fields.field_name?(name)
|
476
469
|
end
|
477
470
|
|
478
471
|
def name_shadows_method?(name)
|