bindata 2.5.1 → 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 +7 -0
- data/LICENSE +1 -1
- data/NEWS.rdoc +53 -2
- data/README.md +1 -1
- data/bindata.gemspec +1 -1
- 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/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 +72 -24
- 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
- metadata +6 -9
data/lib/bindata/registry.rb
CHANGED
|
@@ -7,36 +7,43 @@ 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
|
-
search_names(name, hints).each do |search|
|
|
45
|
+
def lookup(namespace, name, hints = {})
|
|
46
|
+
search_names(namespace, name, hints).each do |search|
|
|
40
47
|
register_dynamic_class(search)
|
|
41
48
|
if @registry.has_key?(search)
|
|
42
49
|
return @registry[search]
|
|
@@ -44,7 +51,7 @@ module BinData
|
|
|
44
51
|
end
|
|
45
52
|
|
|
46
53
|
# give the user a hint if the endian keyword is missing
|
|
47
|
-
search_names(name, hints.merge(endian: :big)).each do |search|
|
|
54
|
+
search_names(namespace, name, hints.merge(endian: :big)).each do |search|
|
|
48
55
|
register_dynamic_class(search)
|
|
49
56
|
if @registry.has_key?(search)
|
|
50
57
|
raise(UnRegisteredTypeError, "#{name}, do you need to specify endian?")
|
|
@@ -58,7 +65,7 @@ module BinData
|
|
|
58
65
|
def underscore_name(name)
|
|
59
66
|
name
|
|
60
67
|
.to_s
|
|
61
|
-
.
|
|
68
|
+
.gsub(/::/, "_")
|
|
62
69
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
|
63
70
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
64
71
|
.tr('-', '_')
|
|
@@ -68,24 +75,62 @@ module BinData
|
|
|
68
75
|
#---------------
|
|
69
76
|
private
|
|
70
77
|
|
|
71
|
-
def search_names(name, hints)
|
|
72
|
-
|
|
78
|
+
def search_names(namespace, name, hints)
|
|
79
|
+
searches = backwards_compatible_search_names(name, hints)
|
|
80
|
+
return searches unless searches.empty?
|
|
81
|
+
|
|
73
82
|
searches = []
|
|
74
83
|
|
|
75
|
-
|
|
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
|
|
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))
|
|
95
|
+
nwe = name_with_endian(nwp, hints[:endian])
|
|
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])
|
|
76
115
|
search_prefix.each do |prefix|
|
|
77
|
-
nwp = name_with_prefix(
|
|
116
|
+
nwp = name_with_prefix(name, prefix)
|
|
78
117
|
nwe = name_with_endian(nwp, hints[:endian])
|
|
79
118
|
|
|
80
|
-
|
|
81
|
-
searches <<
|
|
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
|
|
125
|
+
end
|
|
82
126
|
end
|
|
83
127
|
|
|
84
128
|
searches
|
|
85
129
|
end
|
|
86
130
|
|
|
87
131
|
def name_with_prefix(name, prefix)
|
|
88
|
-
|
|
132
|
+
name = underscore_name(name)
|
|
133
|
+
prefix = underscore_name(prefix).chomp('_')
|
|
89
134
|
if prefix == ""
|
|
90
135
|
name
|
|
91
136
|
else
|
|
@@ -97,7 +142,7 @@ module BinData
|
|
|
97
142
|
return nil if endian.nil?
|
|
98
143
|
|
|
99
144
|
suffix = (endian == :little) ? 'le' : 'be'
|
|
100
|
-
if /^
|
|
145
|
+
if /^bin_data_u?int\d+$/.match?(name)
|
|
101
146
|
name + suffix
|
|
102
147
|
else
|
|
103
148
|
name + '_' + suffix
|
|
@@ -105,8 +150,11 @@ module BinData
|
|
|
105
150
|
end
|
|
106
151
|
|
|
107
152
|
def register_dynamic_class(name)
|
|
108
|
-
|
|
109
|
-
|
|
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 }
|
|
110
158
|
begin
|
|
111
159
|
# call const_get for side effect of creating class
|
|
112
160
|
BinData.const_get(class_name)
|
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
|
data/test/record_test.rb
CHANGED
|
@@ -5,7 +5,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
|
|
5
5
|
describe BinData::Record do
|
|
6
6
|
it "is not registered" do
|
|
7
7
|
_ {
|
|
8
|
-
BinData::RegisteredClasses.lookup("Record")
|
|
8
|
+
BinData::RegisteredClasses.lookup("BinData", "Record")
|
|
9
9
|
}.must_raise BinData::UnRegisteredTypeError
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -101,6 +101,15 @@ describe BinData::Record, "when defining with errors" do
|
|
|
101
101
|
}.must_raise_on_line SyntaxError, 3, "endian must be called before defining fields in BadEndianPosRecord"
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
it "fails when search_namespace is after a field" do
|
|
105
|
+
_ {
|
|
106
|
+
class BadSearchNamespacePosRecord < BinData::Record
|
|
107
|
+
string :a
|
|
108
|
+
search_namespace :ns
|
|
109
|
+
end
|
|
110
|
+
}.must_raise_on_line SyntaxError, 3, "search_namespace must be called before defining fields in BadSearchNamespacePosRecord"
|
|
111
|
+
end
|
|
112
|
+
|
|
104
113
|
it "fails when search_prefix is after a field" do
|
|
105
114
|
_ {
|
|
106
115
|
class BadSearchPrefixPosRecord < BinData::Record
|
|
@@ -396,6 +405,88 @@ describe BinData::Record, "with an endian defined" do
|
|
|
396
405
|
end
|
|
397
406
|
end
|
|
398
407
|
|
|
408
|
+
describe BinData::Record, "with namespaces" do
|
|
409
|
+
module ModA
|
|
410
|
+
class MyInt < BinData::Int8; end
|
|
411
|
+
class ARecord < BinData::Record
|
|
412
|
+
my_int :a
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
module ModB
|
|
417
|
+
class BRecord < BinData::Record
|
|
418
|
+
mod_a_my_int :a
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
it "looks up with relative name" do
|
|
423
|
+
obj = ModA::ARecord.new
|
|
424
|
+
_(obj.a.class.name).must_equal "ModA::MyInt"
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
it "looks up with absolute name" do
|
|
428
|
+
obj = ModB::BRecord.new
|
|
429
|
+
_(obj.a.class.name).must_equal "ModA::MyInt"
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
describe BinData::Record, "with search_namespace" do
|
|
434
|
+
module ModA
|
|
435
|
+
class Snamespace < BinData::Int8; end
|
|
436
|
+
end
|
|
437
|
+
module ModB
|
|
438
|
+
class Snamespace < BinData::Int8; end
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
class RecordWithSearchNamespace < BinData::Record
|
|
442
|
+
search_namespace :ModA
|
|
443
|
+
snamespace :f
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
class RecordWithParentSearchNamespace < BinData::Record
|
|
447
|
+
search_namespace :ModA
|
|
448
|
+
struct :s do
|
|
449
|
+
snamespace :f
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
class RecordWithNestedSearchNamespace < BinData::Record
|
|
454
|
+
search_namespace :ModA
|
|
455
|
+
struct :s do
|
|
456
|
+
search_namespace :x
|
|
457
|
+
snamespace :f
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
class RecordWithPrioritisedNestedSearchNamespace < BinData::Record
|
|
462
|
+
search_namespace :ModB
|
|
463
|
+
struct :s do
|
|
464
|
+
search_namespace :ModA
|
|
465
|
+
snamespace :f
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it "uses search_prefix" do
|
|
470
|
+
obj = RecordWithSearchNamespace.new
|
|
471
|
+
_(obj.f.class.name).must_equal "ModA::Snamespace"
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
it "uses parent search_prefix" do
|
|
475
|
+
obj = RecordWithParentSearchNamespace.new
|
|
476
|
+
_(obj.s.f.class.name).must_equal "ModA::Snamespace"
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
it "uses nested search_prefix" do
|
|
480
|
+
obj = RecordWithNestedSearchNamespace.new
|
|
481
|
+
_(obj.s.f.class.name).must_equal "ModA::Snamespace"
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
it "uses prioritised nested search_prefix" do
|
|
485
|
+
obj = RecordWithPrioritisedNestedSearchNamespace.new
|
|
486
|
+
_(obj.s.f.class.name).must_equal "ModA::Snamespace"
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
399
490
|
describe BinData::Record, "with search_prefix" do
|
|
400
491
|
class ASprefix < BinData::Int8; end
|
|
401
492
|
class BSprefix < BinData::Int8; end
|
|
@@ -449,6 +540,29 @@ describe BinData::Record, "with search_prefix" do
|
|
|
449
540
|
end
|
|
450
541
|
end
|
|
451
542
|
|
|
543
|
+
describe BinData::Record, "with endian :big_and_little and search_namespace" do
|
|
544
|
+
module Ns1
|
|
545
|
+
class BNLIntBe < BinData::Int16be; end
|
|
546
|
+
class BNLIntLe < BinData::Int16le; end
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
class RecordWithBnLEndianAndSearchNamespace < BinData::Record
|
|
550
|
+
endian :big_and_little
|
|
551
|
+
search_namespace :ns1
|
|
552
|
+
bnl_int :a, value: 1
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
it "creates big endian version" do
|
|
556
|
+
obj = RecordWithBnLEndianAndSearchNamespaceBe.new
|
|
557
|
+
_(obj.to_binary_s).must_equal_binary "\x00\x01"
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
it "creates little endian version" do
|
|
561
|
+
obj = RecordWithBnLEndianAndSearchNamespaceLe.new
|
|
562
|
+
_(obj.to_binary_s).must_equal_binary "\x01\x00"
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
|
|
452
566
|
describe BinData::Record, "with endian :big_and_little" do
|
|
453
567
|
class RecordWithBnLEndian < BinData::Record
|
|
454
568
|
endian :big_and_little
|
|
@@ -457,7 +571,7 @@ describe BinData::Record, "with endian :big_and_little" do
|
|
|
457
571
|
|
|
458
572
|
it "is not registered" do
|
|
459
573
|
_ {
|
|
460
|
-
BinData::RegisteredClasses.lookup("RecordWithBnLEndian")
|
|
574
|
+
BinData::RegisteredClasses.lookup("", "RecordWithBnLEndian")
|
|
461
575
|
}.must_raise BinData::UnRegisteredTypeError
|
|
462
576
|
end
|
|
463
577
|
|
|
@@ -515,7 +629,7 @@ describe BinData::Record, "with endian :big_and_little when subclassed" do
|
|
|
515
629
|
|
|
516
630
|
it "is not registered" do
|
|
517
631
|
_ {
|
|
518
|
-
BinData::RegisteredClasses.lookup("BRecordWithBnLEndian")
|
|
632
|
+
BinData::RegisteredClasses.lookup("", "BRecordWithBnLEndian")
|
|
519
633
|
}.must_raise BinData::UnRegisteredTypeError
|
|
520
634
|
end
|
|
521
635
|
|