bindata 2.5.0 → 3.0.0
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 +4 -4
- data/ChangeLog.rdoc +12 -0
- data/LICENSE +1 -1
- data/NEWS.rdoc +53 -2
- data/README.md +2 -2
- data/bindata.gemspec +3 -2
- data/lib/bindata/array.rb +1 -1
- data/lib/bindata/base.rb +9 -2
- data/lib/bindata/base_primitive.rb +5 -5
- data/lib/bindata/bits.rb +41 -47
- data/lib/bindata/buffer.rb +3 -3
- data/lib/bindata/choice.rb +3 -3
- data/lib/bindata/delayed_io.rb +3 -3
- data/lib/bindata/dsl.rb +36 -9
- data/lib/bindata/int.rb +29 -43
- data/lib/bindata/io.rb +1 -1
- data/lib/bindata/lazy.rb +9 -9
- data/lib/bindata/name.rb +13 -3
- data/lib/bindata/primitive.rb +2 -2
- data/lib/bindata/record.rb +1 -1
- data/lib/bindata/registry.rb +90 -47
- data/lib/bindata/sanitize.rb +41 -16
- data/lib/bindata/section.rb +3 -3
- data/lib/bindata/skip.rb +2 -7
- data/lib/bindata/struct.rb +14 -6
- data/lib/bindata/version.rb +1 -1
- data/lib/bindata.rb +3 -3
- data/test/base_primitive_test.rb +1 -1
- data/test/primitive_test.rb +1 -1
- data/test/record_test.rb +117 -3
- data/test/registry_test.rb +113 -60
- data/test/string_test.rb +8 -0
- data/test/struct_test.rb +65 -3
- data/test/system_test.rb +25 -1
- data/test/test_helper.rb +8 -4
- metadata +9 -11
data/lib/bindata/name.rb
CHANGED
|
@@ -11,16 +11,26 @@ module BinData
|
|
|
11
11
|
# BinData::Struct.new(name: :my_struct, fields: ...)
|
|
12
12
|
# array = BinData::Array.new(type: :my_struct)
|
|
13
13
|
# </pre></code>
|
|
14
|
+
# <tt>:namespace</tt>:: The namespace that this object belongs to may be
|
|
15
|
+
# set explicitly. This is only useful when dynamically
|
|
16
|
+
# generating types.
|
|
17
|
+
# <code><pre>
|
|
18
|
+
# BinData::Struct.new(name: :my_struct, namespace: :ns1, fields: ...)
|
|
19
|
+
# BinData::Struct.new(name: :my_struct, namespace: :ns2, fields: ...)
|
|
20
|
+
# array = BinData::Array.new(namespace: :ns1, type: :my_struct)
|
|
21
|
+
# </pre></code>
|
|
14
22
|
module RegisterNamePlugin
|
|
15
23
|
|
|
16
24
|
def self.included(base) # :nodoc:
|
|
17
|
-
#
|
|
18
|
-
base.optional_parameter :name
|
|
25
|
+
# +name+ and +namespace+ may be provided explicitly.
|
|
26
|
+
base.optional_parameter :name, :namespace
|
|
19
27
|
end
|
|
20
28
|
|
|
21
29
|
def initialize_shared_instance
|
|
22
30
|
if has_parameter?(:name)
|
|
23
|
-
|
|
31
|
+
name = get_parameter(:name)
|
|
32
|
+
namespace = get_parameter(:namespace) || ""
|
|
33
|
+
RegisteredClasses.register(namespace, name, self)
|
|
24
34
|
end
|
|
25
35
|
super
|
|
26
36
|
end
|
data/lib/bindata/primitive.rb
CHANGED
|
@@ -77,9 +77,9 @@ module BinData
|
|
|
77
77
|
@struct.respond_to?(symbol, include_private) || super
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
def method_missing(symbol, *args, &block) # :nodoc:
|
|
80
|
+
def method_missing(symbol, *args, **kwargs, &block) # :nodoc:
|
|
81
81
|
if @struct.respond_to?(symbol)
|
|
82
|
-
@struct.__send__(symbol, *args, &block)
|
|
82
|
+
@struct.__send__(symbol, *args, **kwargs, &block)
|
|
83
83
|
else
|
|
84
84
|
super
|
|
85
85
|
end
|
data/lib/bindata/record.rb
CHANGED
data/lib/bindata/registry.rb
CHANGED
|
@@ -7,50 +7,65 @@ module BinData
|
|
|
7
7
|
# Numerics (integers and floating point numbers) have an endian property as
|
|
8
8
|
# part of their name (e.g. int32be, float_le).
|
|
9
9
|
#
|
|
10
|
+
# Classes exist in a namespace that mirrors the Ruby module hierarchy.
|
|
11
|
+
#
|
|
10
12
|
# Classes can be looked up based on their full name or an abbreviated +name+
|
|
11
13
|
# with +hints+.
|
|
12
14
|
#
|
|
13
|
-
# There are two hints supported, :endian and :
|
|
15
|
+
# There are two hints supported, :endian and :search_namespace.
|
|
14
16
|
#
|
|
15
|
-
# #lookup("int32", { endian: :big }) will return Int32Be.
|
|
17
|
+
# #lookup("", "int32", { endian: :big }) will return Int32Be.
|
|
16
18
|
#
|
|
17
|
-
# #lookup("my_type", {
|
|
19
|
+
# #lookup("", "my_type", { search_namespace: :ns }) will return Ns::MyType.
|
|
18
20
|
#
|
|
19
21
|
# Names are stored in under_score_style, not camelCase.
|
|
20
22
|
class Registry
|
|
21
23
|
def initialize
|
|
22
24
|
@registry = {}
|
|
25
|
+
@backwards_compatible_registry = {}
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
def register(name, class_to_register)
|
|
26
|
-
return if name.nil? || class_to_register.nil?
|
|
28
|
+
def register(namespace, name, class_to_register)
|
|
29
|
+
return if namespace.nil? || name.nil? || class_to_register.nil?
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
warn_if_name_is_already_registered(
|
|
31
|
+
search = name_with_prefix(name, namespace)
|
|
32
|
+
warn_if_name_is_already_registered(search, class_to_register)
|
|
30
33
|
|
|
31
|
-
@registry[
|
|
34
|
+
@registry[search] = class_to_register
|
|
35
|
+
@backwards_compatible_registry[underscore_name(name)] = search
|
|
32
36
|
end
|
|
33
37
|
|
|
34
|
-
def unregister(name)
|
|
35
|
-
|
|
38
|
+
def unregister(namespace, name)
|
|
39
|
+
search = name_with_prefix(name, namespace)
|
|
40
|
+
|
|
41
|
+
@registry.delete(search)
|
|
42
|
+
@backwards_compatible_registry.delete(underscore_name(name))
|
|
36
43
|
end
|
|
37
44
|
|
|
38
|
-
def lookup(name, hints = {})
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
def lookup(namespace, name, hints = {})
|
|
46
|
+
search_names(namespace, name, hints).each do |search|
|
|
47
|
+
register_dynamic_class(search)
|
|
48
|
+
if @registry.has_key?(search)
|
|
49
|
+
return @registry[search]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# give the user a hint if the endian keyword is missing
|
|
54
|
+
search_names(namespace, name, hints.merge(endian: :big)).each do |search|
|
|
55
|
+
register_dynamic_class(search)
|
|
56
|
+
if @registry.has_key?(search)
|
|
57
|
+
raise(UnRegisteredTypeError, "#{name}, do you need to specify endian?")
|
|
58
|
+
end
|
|
46
59
|
end
|
|
60
|
+
|
|
61
|
+
raise(UnRegisteredTypeError, name)
|
|
47
62
|
end
|
|
48
63
|
|
|
49
64
|
# Convert CamelCase +name+ to underscore style.
|
|
50
65
|
def underscore_name(name)
|
|
51
66
|
name
|
|
52
67
|
.to_s
|
|
53
|
-
.
|
|
68
|
+
.gsub(/::/, "_")
|
|
54
69
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
55
70
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
56
71
|
.tr('-', '_')
|
|
@@ -60,31 +75,62 @@ module BinData
|
|
|
60
75
|
#---------------
|
|
61
76
|
private
|
|
62
77
|
|
|
63
|
-
def
|
|
64
|
-
|
|
78
|
+
def search_names(namespace, name, hints)
|
|
79
|
+
searches = backwards_compatible_search_names(name, hints)
|
|
80
|
+
return searches unless searches.empty?
|
|
65
81
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
end
|
|
82
|
+
searches = []
|
|
83
|
+
|
|
84
|
+
# prioritise BinData classes
|
|
85
|
+
nwp = name_with_prefix(name, "BinData")
|
|
86
|
+
nwe = name_with_endian(nwp, hints[:endian])
|
|
87
|
+
searches << nwp
|
|
88
|
+
searches << nwe if nwe
|
|
74
89
|
|
|
90
|
+
ns = underscore_name(namespace)
|
|
91
|
+
loop do
|
|
92
|
+
search_prefix = [""] + Array(hints[:search_namespace])
|
|
93
|
+
search_prefix.each do |prefix|
|
|
94
|
+
nwp = name_with_prefix(name, name_with_prefix(prefix, ns))
|
|
75
95
|
nwe = name_with_endian(nwp, hints[:endian])
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
96
|
+
|
|
97
|
+
searches << nwp
|
|
98
|
+
searches << nwe if nwe
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
break if ns == ""
|
|
102
|
+
ns.sub!(/(?:^|_)[^_]*$/, "")
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
searches
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# The old way of providing namespaces was to prefix the class name.
|
|
109
|
+
# Here we provide the backward compatibility for existing code.
|
|
110
|
+
def backwards_compatible_search_names(name, hints)
|
|
111
|
+
return [] unless hints.has_key?(:search_prefix)
|
|
112
|
+
|
|
113
|
+
searches = []
|
|
114
|
+
search_prefix = Array(hints[:search_prefix])
|
|
115
|
+
search_prefix.each do |prefix|
|
|
116
|
+
nwp = name_with_prefix(name, prefix)
|
|
117
|
+
nwe = name_with_endian(nwp, hints[:endian])
|
|
118
|
+
|
|
119
|
+
found_search = @backwards_compatible_registry[nwp]
|
|
120
|
+
searches << found_search if found_search
|
|
121
|
+
|
|
122
|
+
if nwe
|
|
123
|
+
found_search = @backwards_compatible_registry[nwe]
|
|
124
|
+
searches << found_search if found_search
|
|
80
125
|
end
|
|
81
126
|
end
|
|
82
127
|
|
|
83
|
-
|
|
128
|
+
searches
|
|
84
129
|
end
|
|
85
130
|
|
|
86
131
|
def name_with_prefix(name, prefix)
|
|
87
|
-
|
|
132
|
+
name = underscore_name(name)
|
|
133
|
+
prefix = underscore_name(prefix).chomp('_')
|
|
88
134
|
if prefix == ""
|
|
89
135
|
name
|
|
90
136
|
else
|
|
@@ -93,27 +139,24 @@ module BinData
|
|
|
93
139
|
end
|
|
94
140
|
|
|
95
141
|
def name_with_endian(name, endian)
|
|
96
|
-
return
|
|
142
|
+
return nil if endian.nil?
|
|
97
143
|
|
|
98
144
|
suffix = (endian == :little) ? 'le' : 'be'
|
|
99
|
-
if /^
|
|
145
|
+
if /^bin_data_u?int\d+$/.match?(name)
|
|
100
146
|
name + suffix
|
|
101
147
|
else
|
|
102
148
|
name + '_' + suffix
|
|
103
149
|
end
|
|
104
150
|
end
|
|
105
151
|
|
|
106
|
-
def registered?(name)
|
|
107
|
-
register_dynamic_class(name) unless @registry.key?(name)
|
|
108
|
-
|
|
109
|
-
@registry.key?(name)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
152
|
def register_dynamic_class(name)
|
|
113
|
-
|
|
114
|
-
|
|
153
|
+
return unless /^bin_data_/ =~ name
|
|
154
|
+
|
|
155
|
+
if /^bin_data_u?int\d+(le|be)$/.match?(name) || /^bin_data_s?bit\d+(le)?$/.match?(name)
|
|
156
|
+
base_name = name.sub(/^bin_data_/, "")
|
|
157
|
+
class_name = base_name.gsub(/(?:^|_)(.)/) { $1.upcase }
|
|
115
158
|
begin
|
|
116
|
-
# call const_get for side
|
|
159
|
+
# call const_get for side effect of creating class
|
|
117
160
|
BinData.const_get(class_name)
|
|
118
161
|
rescue NameError
|
|
119
162
|
end
|
|
@@ -124,7 +167,7 @@ module BinData
|
|
|
124
167
|
prev_class = @registry[name]
|
|
125
168
|
if prev_class && prev_class != class_to_register
|
|
126
169
|
Kernel.warn "warning: replacing registered class #{prev_class} " \
|
|
127
|
-
|
|
170
|
+
"with #{class_to_register}"
|
|
128
171
|
end
|
|
129
172
|
end
|
|
130
173
|
end
|
data/lib/bindata/sanitize.rb
CHANGED
|
@@ -6,7 +6,7 @@ module BinData
|
|
|
6
6
|
class SanitizedParameter; end
|
|
7
7
|
|
|
8
8
|
class SanitizedPrototype < SanitizedParameter
|
|
9
|
-
def initialize(obj_type, obj_params, hints)
|
|
9
|
+
def initialize(obj_type, obj_params, namespace, hints)
|
|
10
10
|
raw_hints = hints.dup
|
|
11
11
|
if raw_hints[:endian].respond_to?(:endian)
|
|
12
12
|
raw_hints[:endian] = raw_hints[:endian].endian
|
|
@@ -16,14 +16,14 @@ module BinData
|
|
|
16
16
|
if BinData::Base === obj_type
|
|
17
17
|
obj_class = obj_type
|
|
18
18
|
else
|
|
19
|
-
obj_class = RegisteredClasses.lookup(obj_type, raw_hints)
|
|
19
|
+
obj_class = RegisteredClasses.lookup(namespace, obj_type, raw_hints)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
if BinData::Base === obj_class
|
|
23
23
|
@factory = obj_class
|
|
24
24
|
else
|
|
25
25
|
@obj_class = obj_class
|
|
26
|
-
@obj_params = SanitizedParameters.new(obj_params, @obj_class, hints)
|
|
26
|
+
@obj_params = SanitizedParameters.new(obj_params, @obj_class, namespace, hints)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -44,9 +44,9 @@ module BinData
|
|
|
44
44
|
#----------------------------------------------------------------------------
|
|
45
45
|
|
|
46
46
|
class SanitizedField < SanitizedParameter
|
|
47
|
-
def initialize(name, field_type, field_params, hints)
|
|
47
|
+
def initialize(name, field_type, field_params, namespace, hints)
|
|
48
48
|
@name = name
|
|
49
|
-
@prototype = SanitizedPrototype.new(field_type, field_params, hints)
|
|
49
|
+
@prototype = SanitizedPrototype.new(field_type, field_params, namespace, hints)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
attr_reader :prototype, :name
|
|
@@ -68,7 +68,8 @@ module BinData
|
|
|
68
68
|
class SanitizedFields < SanitizedParameter
|
|
69
69
|
include Enumerable
|
|
70
70
|
|
|
71
|
-
def initialize(hints, base_fields = nil)
|
|
71
|
+
def initialize(namespace, hints, base_fields = nil)
|
|
72
|
+
@namespace = namespace
|
|
72
73
|
@hints = hints
|
|
73
74
|
@fields = base_fields ? base_fields.raw_fields : []
|
|
74
75
|
end
|
|
@@ -76,7 +77,7 @@ module BinData
|
|
|
76
77
|
def add_field(type, name, params)
|
|
77
78
|
name = nil if name == ""
|
|
78
79
|
|
|
79
|
-
@fields << SanitizedField.new(name, type, params, @hints)
|
|
80
|
+
@fields << SanitizedField.new(name, type, params, @namespace, @hints)
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
def raw_fields
|
|
@@ -122,14 +123,14 @@ module BinData
|
|
|
122
123
|
#----------------------------------------------------------------------------
|
|
123
124
|
|
|
124
125
|
class SanitizedChoices < SanitizedParameter
|
|
125
|
-
def initialize(choices, hints)
|
|
126
|
+
def initialize(choices, namespace, hints)
|
|
126
127
|
@choices = {}
|
|
127
128
|
choices.each_pair do |key, val|
|
|
128
129
|
if SanitizedParameter === val
|
|
129
130
|
prototype = val
|
|
130
131
|
else
|
|
131
132
|
type, param = val
|
|
132
|
-
prototype = SanitizedPrototype.new(type, param, hints)
|
|
133
|
+
prototype = SanitizedPrototype.new(type, param, namespace, hints)
|
|
133
134
|
end
|
|
134
135
|
|
|
135
136
|
if key == :default
|
|
@@ -180,20 +181,30 @@ module BinData
|
|
|
180
181
|
if SanitizedParameters === parameters
|
|
181
182
|
parameters
|
|
182
183
|
else
|
|
183
|
-
|
|
184
|
+
namespace = parameters[:namespace]
|
|
185
|
+
unless namespace
|
|
186
|
+
m = /(.*)::[^:].*/.match(the_class.name)
|
|
187
|
+
namespace = m ? m[1] : ""
|
|
188
|
+
end
|
|
189
|
+
SanitizedParameters.new(parameters, the_class, namespace, {})
|
|
184
190
|
end
|
|
185
191
|
end
|
|
186
192
|
end
|
|
187
193
|
|
|
188
|
-
def initialize(parameters, the_class, hints)
|
|
194
|
+
def initialize(parameters, the_class, namespace, hints)
|
|
189
195
|
parameters.each_pair { |key, value| self[key.to_sym] = value }
|
|
190
196
|
|
|
191
197
|
@the_class = the_class
|
|
198
|
+
@namespace = namespace
|
|
192
199
|
|
|
193
200
|
if hints[:endian]
|
|
194
201
|
self[:endian] ||= hints[:endian]
|
|
195
202
|
end
|
|
196
203
|
|
|
204
|
+
if hints[:search_namespace] && !hints[:search_namespace].empty?
|
|
205
|
+
self[:search_namespace] = Array(self[:search_namespace]).concat(Array(hints[:search_namespace]))
|
|
206
|
+
end
|
|
207
|
+
|
|
197
208
|
if hints[:search_prefix] && !hints[:search_prefix].empty?
|
|
198
209
|
self[:search_prefix] = Array(self[:search_prefix]).concat(Array(hints[:search_prefix]))
|
|
199
210
|
end
|
|
@@ -211,6 +222,12 @@ module BinData
|
|
|
211
222
|
false
|
|
212
223
|
end
|
|
213
224
|
|
|
225
|
+
def must_have_at_least_one_of(*keys)
|
|
226
|
+
unless has_at_least_one_of?(*keys)
|
|
227
|
+
raise ArgumentError, "#{@the_class} requires one of #{keys}"
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
214
231
|
def warn_replacement_parameter(bad_key, suggested_key)
|
|
215
232
|
if has_parameter?(bad_key)
|
|
216
233
|
Kernel.warn ":#{bad_key} is not used with #{@the_class}. " \
|
|
@@ -247,6 +264,10 @@ module BinData
|
|
|
247
264
|
end
|
|
248
265
|
end
|
|
249
266
|
|
|
267
|
+
def merge_dsl_params
|
|
268
|
+
self.merge!(@the_class.dsl_params)
|
|
269
|
+
end
|
|
270
|
+
|
|
250
271
|
def sanitize_object_prototype(key)
|
|
251
272
|
sanitize(key) do |obj_type, obj_params|
|
|
252
273
|
create_sanitized_object_prototype(obj_type, obj_params)
|
|
@@ -278,11 +299,15 @@ module BinData
|
|
|
278
299
|
end
|
|
279
300
|
|
|
280
301
|
def create_sanitized_params(params, the_class)
|
|
281
|
-
SanitizedParameters.new(params, the_class, hints)
|
|
302
|
+
SanitizedParameters.new(params, the_class, @namespace, hints)
|
|
282
303
|
end
|
|
283
304
|
|
|
284
305
|
def hints
|
|
285
|
-
{
|
|
306
|
+
{
|
|
307
|
+
endian: self[:endian],
|
|
308
|
+
search_namespace: self[:search_namespace],
|
|
309
|
+
search_prefix: self[:search_prefix]
|
|
310
|
+
}
|
|
286
311
|
end
|
|
287
312
|
|
|
288
313
|
#---------------
|
|
@@ -350,15 +375,15 @@ module BinData
|
|
|
350
375
|
end
|
|
351
376
|
|
|
352
377
|
def create_sanitized_choices(choices)
|
|
353
|
-
SanitizedChoices.new(choices, hints)
|
|
378
|
+
SanitizedChoices.new(choices, @namespace, hints)
|
|
354
379
|
end
|
|
355
380
|
|
|
356
381
|
def create_sanitized_fields
|
|
357
|
-
SanitizedFields.new(hints)
|
|
382
|
+
SanitizedFields.new(@namespace, hints)
|
|
358
383
|
end
|
|
359
384
|
|
|
360
385
|
def create_sanitized_object_prototype(obj_type, obj_params)
|
|
361
|
-
SanitizedPrototype.new(obj_type, obj_params, hints)
|
|
386
|
+
SanitizedPrototype.new(obj_type, obj_params, @namespace, hints)
|
|
362
387
|
end
|
|
363
388
|
end
|
|
364
389
|
#----------------------------------------------------------------------------
|
data/lib/bindata/section.rb
CHANGED
|
@@ -65,8 +65,8 @@ module BinData
|
|
|
65
65
|
@type.respond_to?(symbol, include_all) || super
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
def method_missing(symbol, *args, &block) # :nodoc:
|
|
69
|
-
@type.__send__(symbol, *args, &block)
|
|
68
|
+
def method_missing(symbol, *args, **kwargs, &block) # :nodoc:
|
|
69
|
+
@type.__send__(symbol, *args, **kwargs, &block)
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
def do_read(io) # :nodoc:
|
|
@@ -90,7 +90,7 @@ module BinData
|
|
|
90
90
|
include MultiFieldArgSeparator
|
|
91
91
|
|
|
92
92
|
def sanitize_parameters!(obj_class, params)
|
|
93
|
-
params.
|
|
93
|
+
params.merge_dsl_params
|
|
94
94
|
params.sanitize_object_prototype(:type)
|
|
95
95
|
end
|
|
96
96
|
end
|
data/lib/bindata/skip.rb
CHANGED
|
@@ -208,13 +208,8 @@ module BinData
|
|
|
208
208
|
|
|
209
209
|
class SkipArgProcessor < BaseArgProcessor
|
|
210
210
|
def sanitize_parameters!(obj_class, params)
|
|
211
|
-
params.
|
|
212
|
-
|
|
213
|
-
unless params.has_at_least_one_of?(:length, :to_abs_offset, :until_valid)
|
|
214
|
-
raise ArgumentError,
|
|
215
|
-
"#{obj_class} requires :length, :to_abs_offset or :until_valid"
|
|
216
|
-
end
|
|
217
|
-
|
|
211
|
+
params.merge_dsl_params
|
|
212
|
+
params.must_have_at_least_one_of(:length, :to_abs_offset, :until_valid)
|
|
218
213
|
params.must_be_integer(:to_abs_offset, :length)
|
|
219
214
|
params.sanitize_object_prototype(:until_valid)
|
|
220
215
|
end
|
data/lib/bindata/struct.rb
CHANGED
|
@@ -42,9 +42,9 @@ module BinData
|
|
|
42
42
|
# <tt>:endian</tt>:: Either :little or :big. This specifies the default
|
|
43
43
|
# endian of any numerics in this struct, or in any
|
|
44
44
|
# nested data objects.
|
|
45
|
-
# <tt>:
|
|
46
|
-
#
|
|
47
|
-
#
|
|
45
|
+
# <tt>:search_namespace</tt>:: Allows namespaced type names. If a type is
|
|
46
|
+
# unrecognised, then each namespace is searched
|
|
47
|
+
# until a match is found.
|
|
48
48
|
#
|
|
49
49
|
# == Field Parameters
|
|
50
50
|
#
|
|
@@ -59,7 +59,8 @@ module BinData
|
|
|
59
59
|
arg_processor :struct
|
|
60
60
|
|
|
61
61
|
mandatory_parameter :fields
|
|
62
|
-
optional_parameters :endian, :search_prefix, :hide
|
|
62
|
+
optional_parameters :endian, :search_namespace, :search_prefix, :hide
|
|
63
|
+
mutually_exclusive_parameters :search_namespace, :search_prefix
|
|
63
64
|
|
|
64
65
|
# These reserved words may not be used as field names
|
|
65
66
|
RESERVED =
|
|
@@ -71,7 +72,7 @@ module BinData
|
|
|
71
72
|
when while yield] +
|
|
72
73
|
%w[array element index value] +
|
|
73
74
|
%w[type initial_length read_until] +
|
|
74
|
-
%w[fields endian search_prefix hide onlyif byte_align] +
|
|
75
|
+
%w[fields endian search_namespace search_prefix hide onlyif byte_align] +
|
|
75
76
|
%w[choices selection copy_on_change] +
|
|
76
77
|
%w[read_abs_offset struct_params])
|
|
77
78
|
.collect(&:to_sym)
|
|
@@ -292,7 +293,7 @@ module BinData
|
|
|
292
293
|
key?(symbol) || super
|
|
293
294
|
end
|
|
294
295
|
|
|
295
|
-
def method_missing(symbol, *args)
|
|
296
|
+
def method_missing(symbol, *args, **kwargs)
|
|
296
297
|
key?(symbol) ? self[symbol] : super
|
|
297
298
|
end
|
|
298
299
|
end
|
|
@@ -367,6 +368,7 @@ module BinData
|
|
|
367
368
|
class StructArgProcessor < BaseArgProcessor
|
|
368
369
|
def sanitize_parameters!(obj_class, params)
|
|
369
370
|
sanitize_endian(params)
|
|
371
|
+
sanitize_search_namespace(params)
|
|
370
372
|
sanitize_search_prefix(params)
|
|
371
373
|
sanitize_fields(obj_class, params)
|
|
372
374
|
sanitize_hide(params)
|
|
@@ -379,6 +381,12 @@ module BinData
|
|
|
379
381
|
params.sanitize_endian(:endian)
|
|
380
382
|
end
|
|
381
383
|
|
|
384
|
+
def sanitize_search_namespace(params)
|
|
385
|
+
params.sanitize(:search_namespace) do |snamespace|
|
|
386
|
+
Array(snamespace).collect &:to_s
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
382
390
|
def sanitize_search_prefix(params)
|
|
383
391
|
params.sanitize(:search_prefix) do |sprefix|
|
|
384
392
|
search_prefix = Array(sprefix).collect do |prefix|
|
data/lib/bindata/version.rb
CHANGED
data/lib/bindata.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# BinData -- Binary data manipulator.
|
|
2
|
-
# Copyright (c) 2007 -
|
|
2
|
+
# Copyright (c) 2007 - 2026 Dion Mendel.
|
|
3
3
|
|
|
4
4
|
require 'bindata/version'
|
|
5
5
|
require 'bindata/array'
|
|
@@ -33,6 +33,6 @@ require 'bindata/warnings'
|
|
|
33
33
|
#
|
|
34
34
|
# == License
|
|
35
35
|
#
|
|
36
|
-
# BinData is released under the
|
|
36
|
+
# BinData is released under the BSD 2-Clause License.
|
|
37
37
|
#
|
|
38
|
-
# Copyright (c) 2007 -
|
|
38
|
+
# Copyright (c) 2007 - 2026 Dion Mendel.
|
data/test/base_primitive_test.rb
CHANGED
data/test/primitive_test.rb
CHANGED
|
@@ -5,7 +5,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
|
|
5
5
|
describe BinData::Primitive do
|
|
6
6
|
it "is not registered" do
|
|
7
7
|
_ {
|
|
8
|
-
BinData::RegisteredClasses.lookup("Primitive")
|
|
8
|
+
BinData::RegisteredClasses.lookup("BinData", "Primitive")
|
|
9
9
|
}.must_raise BinData::UnRegisteredTypeError
|
|
10
10
|
end
|
|
11
11
|
end
|