bindata 1.3.1 → 1.4.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.
Potentially problematic release.
This version of bindata might be problematic. Click here for more details.
- data/BSDL +22 -0
- data/COPYING +2 -2
- data/ChangeLog +12 -0
- data/NEWS +28 -0
- data/examples/list.rb +7 -7
- data/examples/nbt.rb +21 -38
- data/lib/bindata.rb +1 -1
- data/lib/bindata/alignment.rb +1 -4
- data/lib/bindata/array.rb +8 -4
- data/lib/bindata/base.rb +20 -17
- data/lib/bindata/base_primitive.rb +1 -0
- data/lib/bindata/bits.rb +0 -1
- data/lib/bindata/choice.rb +20 -42
- data/lib/bindata/deprecated.rb +5 -8
- data/lib/bindata/dsl.rb +167 -170
- data/lib/bindata/float.rb +0 -4
- data/lib/bindata/int.rb +1 -6
- data/lib/bindata/lazy.rb +8 -9
- data/lib/bindata/primitive.rb +4 -4
- data/lib/bindata/record.rb +36 -42
- data/lib/bindata/registry.rb +5 -4
- data/lib/bindata/rest.rb +0 -2
- data/lib/bindata/sanitize.rb +180 -194
- data/lib/bindata/skip.rb +0 -2
- data/lib/bindata/string.rb +3 -3
- data/lib/bindata/stringz.rb +2 -2
- data/lib/bindata/struct.rb +104 -47
- data/lib/bindata/wrapper.rb +22 -9
- data/manual.haml +74 -41
- data/manual.md +223 -123
- data/spec/array_spec.rb +20 -0
- data/spec/base_primitive_spec.rb +10 -0
- data/spec/choice_spec.rb +20 -6
- data/spec/deprecated_spec.rb +8 -0
- data/spec/example.rb +0 -2
- data/spec/primitive_spec.rb +19 -3
- data/spec/record_spec.rb +23 -7
- data/spec/registry_spec.rb +12 -13
- data/spec/string_spec.rb +39 -0
- data/spec/struct_spec.rb +35 -0
- data/spec/wrapper_spec.rb +10 -0
- data/tasks/rspec.rake +1 -1
- metadata +6 -6
- data/GPL +0 -339
data/lib/bindata/deprecated.rb
CHANGED
@@ -35,15 +35,12 @@ module BinData
|
|
35
35
|
end
|
36
36
|
|
37
37
|
class << self
|
38
|
+
def register_self
|
39
|
+
warn "#{caller[0]} `register_self' is no longer needed as of BinData 1.3.2. You can delete this line"
|
40
|
+
end
|
41
|
+
|
38
42
|
def register(name, class_to_register)
|
39
|
-
|
40
|
-
warn "#{caller[0]} `register(name, class_to_register)' is deprecated as of BinData 1.2.0. Replace with `register_self'"
|
41
|
-
elsif /inherited/ =~ caller[0]
|
42
|
-
warn "#{caller[0]} `def self.inherited(subclass); register(subclass.name, subclass); end' is deprecated as of BinData 1.2.0. Replace with `register_subclasses'"
|
43
|
-
else
|
44
|
-
warn "#{caller[0]} `register(name, class_to_register)' is deprecated as of BinData 1.2.0. Replace with `register_class(class_to_register)'"
|
45
|
-
end
|
46
|
-
register_class(class_to_register)
|
43
|
+
warn "#{caller[0]} `register' is no longer needed as of BinData 1.3.2. You can delete this line"
|
47
44
|
end
|
48
45
|
end
|
49
46
|
|
data/lib/bindata/dsl.rb
CHANGED
@@ -5,20 +5,13 @@ module BinData
|
|
5
5
|
end
|
6
6
|
|
7
7
|
module ClassMethods
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# [<tt>:optional_fieldnames</tt>] Fieldnames are optional.
|
16
|
-
# [<tt>:fieldnames_for_choices</tt>] Fieldnames are choice keys.
|
17
|
-
# [<tt>:no_fieldnames</tt>] Fieldnames are prohibited.
|
18
|
-
# [<tt>:all_or_none_fieldnames</tt>] All fields must have names, or
|
19
|
-
# none may have names.
|
20
|
-
def dsl_parser(*args)
|
21
|
-
@dsl_parser ||= DSLParser.new(self, *args)
|
8
|
+
|
9
|
+
def dsl_parser(parser_type = nil)
|
10
|
+
unless defined? @dsl_parser
|
11
|
+
parser_type = superclass.dsl_parser.parser_type if parser_type.nil?
|
12
|
+
@dsl_parser = DSLParser.new(self, parser_type)
|
13
|
+
end
|
14
|
+
@dsl_parser
|
22
15
|
end
|
23
16
|
|
24
17
|
def method_missing(symbol, *args, &block) #:nodoc:
|
@@ -30,39 +23,6 @@ module BinData
|
|
30
23
|
def to_str; nil; end
|
31
24
|
end
|
32
25
|
|
33
|
-
# An array containing a field definition of the form
|
34
|
-
# expected by BinData::Struct.
|
35
|
-
class UnSanitizedField < ::Array
|
36
|
-
def initialize(type, name, params)
|
37
|
-
super()
|
38
|
-
self << type << name << params
|
39
|
-
end
|
40
|
-
def type
|
41
|
-
self[0]
|
42
|
-
end
|
43
|
-
def name
|
44
|
-
self[1]
|
45
|
-
end
|
46
|
-
def params
|
47
|
-
self[2]
|
48
|
-
end
|
49
|
-
def to_type_params
|
50
|
-
[self.type, self.params]
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class UnSanitizedFields < ::Array
|
55
|
-
def field_names
|
56
|
-
collect { |f| f.name }
|
57
|
-
end
|
58
|
-
|
59
|
-
def add_field(type, name, params, endian)
|
60
|
-
normalized_endian = endian.respond_to?(:endian) ? endian.endian : endian
|
61
|
-
normalized_type = RegisteredClasses.normalize_name(type, normalized_endian)
|
62
|
-
self << UnSanitizedField.new(normalized_type, name, params)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
26
|
# A DSLParser parses and accumulates field definitions of the form
|
67
27
|
#
|
68
28
|
# type name, params
|
@@ -73,35 +33,19 @@ module BinData
|
|
73
33
|
# * +params+ is a hash containing any parameters
|
74
34
|
#
|
75
35
|
class DSLParser
|
76
|
-
def initialize(the_class,
|
77
|
-
@the_class
|
78
|
-
|
79
|
-
@
|
80
|
-
|
81
|
-
@endian = parent_attribute(:endian, nil)
|
82
|
-
|
83
|
-
if option?(:hidden_fields)
|
84
|
-
@hide = parent_attribute(:hide, []).dup
|
85
|
-
end
|
86
|
-
|
87
|
-
if option?(:sanitize_fields)
|
88
|
-
fields = parent_attribute(:fields, nil)
|
89
|
-
@fields = Sanitizer.new.create_sanitized_fields(fields)
|
90
|
-
else
|
91
|
-
fields = parent_attribute(:fields, UnSanitizedFields.new)
|
92
|
-
@fields = fields.dup
|
93
|
-
end
|
36
|
+
def initialize(the_class, parser_type)
|
37
|
+
@the_class = the_class
|
38
|
+
@parser_type = parser_type
|
39
|
+
@endian = parent_attribute(:endian, nil)
|
94
40
|
end
|
95
41
|
|
96
|
-
attr_reader :
|
42
|
+
attr_reader :parser_type
|
97
43
|
|
98
44
|
def endian(endian = nil)
|
99
45
|
if endian.nil?
|
100
46
|
@endian
|
101
|
-
elsif endian
|
47
|
+
elsif endian == :big or endian == :little
|
102
48
|
@endian = endian
|
103
|
-
elsif [:little, :big].include?(endian)
|
104
|
-
@endian = Sanitizer.new.create_sanitized_endian(endian)
|
105
49
|
else
|
106
50
|
dsl_raise ArgumentError, "unknown value for endian '#{endian}'"
|
107
51
|
end
|
@@ -115,29 +59,42 @@ module BinData
|
|
115
59
|
end
|
116
60
|
name.to_sym
|
117
61
|
end
|
62
|
+
|
63
|
+
unless defined? @hide
|
64
|
+
@hide = parent_attribute(:hide, []).dup
|
65
|
+
end
|
66
|
+
|
118
67
|
@hide.concat(hidden.compact)
|
119
68
|
@hide
|
120
69
|
end
|
121
70
|
end
|
122
71
|
|
123
72
|
def fields
|
124
|
-
@fields
|
125
|
-
|
73
|
+
unless defined? @fields
|
74
|
+
fields = parent_attribute(:fields, nil)
|
75
|
+
klass = option?(:sanitize_fields) ? SanitizedFields : UnSanitizedFields
|
76
|
+
@fields = klass.new(endian)
|
77
|
+
@fields.copy_fields(fields) if fields
|
78
|
+
end
|
126
79
|
|
127
|
-
|
128
|
-
@fields[0]
|
80
|
+
@fields
|
129
81
|
end
|
130
82
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
83
|
+
def dsl_params
|
84
|
+
case @parser_type
|
85
|
+
when :struct
|
86
|
+
to_struct_params
|
87
|
+
when :array
|
88
|
+
to_array_params
|
89
|
+
when :choice
|
90
|
+
to_choice_params
|
91
|
+
when :primitive
|
92
|
+
to_struct_params
|
93
|
+
when :wrapper
|
94
|
+
raise "Wrapper is deprecated"
|
95
|
+
else
|
96
|
+
raise "unknown parser type #{@parser_type}"
|
138
97
|
end
|
139
|
-
|
140
|
-
result
|
141
98
|
end
|
142
99
|
|
143
100
|
def method_missing(symbol, *args, &block) #:nodoc:
|
@@ -151,15 +108,25 @@ module BinData
|
|
151
108
|
#-------------
|
152
109
|
private
|
153
110
|
|
154
|
-
def dsl_raise(exception, message)
|
155
|
-
backtrace = caller
|
156
|
-
backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
|
157
|
-
|
158
|
-
raise exception, message + " in #{@the_class}", backtrace
|
159
|
-
end
|
160
|
-
|
161
111
|
def option?(opt)
|
162
|
-
|
112
|
+
options.include?(opt)
|
113
|
+
end
|
114
|
+
|
115
|
+
def options
|
116
|
+
case @parser_type
|
117
|
+
when :struct
|
118
|
+
[:multiple_fields, :optional_fieldnames, :sanitize_fields, :hidden_fields]
|
119
|
+
when :array
|
120
|
+
[:multiple_fields, :optional_fieldnames, :sanitize_fields]
|
121
|
+
when :choice
|
122
|
+
[:multiple_fields, :all_or_none_fieldnames, :sanitize_fields, :fieldnames_are_values]
|
123
|
+
when :primitive
|
124
|
+
[:multiple_fields, :optional_fieldnames, :sanitize_fields]
|
125
|
+
when :wrapper
|
126
|
+
[:only_one_field, :no_fieldnames]
|
127
|
+
else
|
128
|
+
raise "unknown parser type #{parser_type}"
|
129
|
+
end
|
163
130
|
end
|
164
131
|
|
165
132
|
def parent_attribute(attr, default = nil)
|
@@ -171,40 +138,20 @@ module BinData
|
|
171
138
|
end
|
172
139
|
end
|
173
140
|
|
174
|
-
def parent_options_plus_these(options)
|
175
|
-
result = parent_attribute(:options, []).dup
|
176
|
-
|
177
|
-
mutexes = [
|
178
|
-
[:only_one_field, :multiple_fields],
|
179
|
-
[:mandatory_fieldnames, :optional_fieldnames, :no_fieldnames, :all_or_none_fieldnames]
|
180
|
-
]
|
181
|
-
|
182
|
-
options.each do |opt|
|
183
|
-
mutexes.each do |mutex|
|
184
|
-
if mutex.include?(opt)
|
185
|
-
result -= mutex
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
result << opt
|
190
|
-
end
|
191
|
-
|
192
|
-
result
|
193
|
-
end
|
194
|
-
|
195
141
|
def name_from_field_declaration(args)
|
196
142
|
name, params = args
|
197
|
-
name
|
198
|
-
|
199
|
-
|
200
|
-
|
143
|
+
if name == "" or name.is_a?(Hash)
|
144
|
+
nil
|
145
|
+
else
|
146
|
+
name
|
147
|
+
end
|
201
148
|
end
|
202
149
|
|
203
150
|
def params_from_field_declaration(type, args, &block)
|
204
151
|
params = params_from_args(args)
|
205
152
|
|
206
|
-
if block_given?
|
207
|
-
params.merge(
|
153
|
+
if block_given?
|
154
|
+
params.merge(params_from_block(type, &block))
|
208
155
|
else
|
209
156
|
params
|
210
157
|
end
|
@@ -217,32 +164,56 @@ module BinData
|
|
217
164
|
params || {}
|
218
165
|
end
|
219
166
|
|
220
|
-
def
|
221
|
-
|
222
|
-
|
167
|
+
def params_from_block(type, &block)
|
168
|
+
bindata_classes = {
|
169
|
+
:array => BinData::Array,
|
170
|
+
:choice => BinData::Choice,
|
171
|
+
:struct => BinData::Struct
|
172
|
+
}
|
173
|
+
|
174
|
+
if bindata_classes.include?(type)
|
175
|
+
parser = DSLParser.new(bindata_classes[type], type)
|
176
|
+
parser.endian(endian)
|
177
|
+
parser.instance_eval(&block)
|
178
|
+
|
179
|
+
parser.dsl_params
|
180
|
+
else
|
181
|
+
{}
|
223
182
|
end
|
183
|
+
end
|
224
184
|
|
225
|
-
|
185
|
+
def append_field(type, name, params)
|
186
|
+
ensure_valid_field(name)
|
226
187
|
|
227
|
-
fields.add_field(type, name, params
|
188
|
+
fields.add_field(type, name, params)
|
189
|
+
rescue ArgumentError => err
|
190
|
+
dsl_raise ArgumentError, err.message
|
228
191
|
rescue UnRegisteredTypeError => err
|
229
192
|
dsl_raise TypeError, "unknown type '#{err.message}'"
|
230
193
|
end
|
231
194
|
|
232
|
-
def
|
233
|
-
if
|
195
|
+
def ensure_valid_field(field_name)
|
196
|
+
if too_many_fields?
|
197
|
+
dsl_raise SyntaxError, "attempting to wrap more than one type"
|
198
|
+
end
|
199
|
+
|
200
|
+
if must_not_have_a_name_failed?(field_name)
|
234
201
|
dsl_raise SyntaxError, "field must not have a name"
|
235
202
|
end
|
236
203
|
|
237
|
-
if all_or_none_names_failed?(
|
204
|
+
if all_or_none_names_failed?(field_name)
|
238
205
|
dsl_raise SyntaxError, "fields must either all have names, or none must have names"
|
239
206
|
end
|
240
207
|
|
241
|
-
if must_have_a_name_failed?(
|
208
|
+
if must_have_a_name_failed?(field_name)
|
242
209
|
dsl_raise SyntaxError, "field must have a name"
|
243
210
|
end
|
244
211
|
|
245
|
-
|
212
|
+
ensure_valid_name(field_name)
|
213
|
+
end
|
214
|
+
|
215
|
+
def ensure_valid_name(name)
|
216
|
+
if name and not option?(:fieldnames_are_values)
|
246
217
|
if malformed_name?(name)
|
247
218
|
dsl_raise NameError.new("", name), "field '#{name}' is an illegal fieldname"
|
248
219
|
end
|
@@ -266,89 +237,115 @@ module BinData
|
|
266
237
|
end
|
267
238
|
|
268
239
|
def must_not_have_a_name_failed?(name)
|
269
|
-
option?(:no_fieldnames) and name !=
|
240
|
+
option?(:no_fieldnames) and name != nil
|
270
241
|
end
|
271
242
|
|
272
243
|
def must_have_a_name_failed?(name)
|
273
|
-
option?(:mandatory_fieldnames) and name
|
244
|
+
option?(:mandatory_fieldnames) and name.nil?
|
274
245
|
end
|
275
246
|
|
276
247
|
def all_or_none_names_failed?(name)
|
277
248
|
if option?(:all_or_none_fieldnames) and not fields.empty?
|
278
|
-
all_names_blank = fields.
|
279
|
-
no_names_blank = fields.
|
249
|
+
all_names_blank = fields.all_field_names_blank?
|
250
|
+
no_names_blank = fields.no_field_names_blank?
|
280
251
|
|
281
|
-
(name !=
|
252
|
+
(name != nil and all_names_blank) or (name == nil and no_names_blank)
|
282
253
|
else
|
283
254
|
false
|
284
255
|
end
|
285
256
|
end
|
286
257
|
|
287
258
|
def malformed_name?(name)
|
288
|
-
|
259
|
+
/^[a-z_]\w*$/ !~ name.to_s
|
289
260
|
end
|
290
261
|
|
291
262
|
def duplicate_name?(name)
|
292
|
-
|
263
|
+
fields.has_field_name?(name)
|
293
264
|
end
|
294
265
|
|
295
266
|
def name_shadows_method?(name)
|
296
|
-
|
267
|
+
@the_class.method_defined?(name)
|
297
268
|
end
|
298
269
|
|
299
270
|
def name_is_reserved?(name)
|
300
|
-
|
271
|
+
BinData::Struct::RESERVED.include?(name.to_sym)
|
301
272
|
end
|
302
|
-
end
|
303
273
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
parser.endian endian
|
308
|
-
parser.instance_eval(&block)
|
274
|
+
def dsl_raise(exception, message)
|
275
|
+
backtrace = caller
|
276
|
+
backtrace.shift while %r{bindata/dsl.rb} =~ backtrace.first
|
309
277
|
|
310
|
-
|
278
|
+
raise exception, message + " in #{@the_class}", backtrace
|
311
279
|
end
|
312
|
-
end
|
313
280
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
if parser.fields.length == 1
|
321
|
-
{:type => parser.field.to_type_params}
|
281
|
+
def to_array_params
|
282
|
+
case fields.length
|
283
|
+
when 0
|
284
|
+
{}
|
285
|
+
when 1
|
286
|
+
{:type => fields[0].prototype}
|
322
287
|
else
|
323
|
-
{:type => [:struct,
|
288
|
+
{:type => [:struct, to_struct_params]}
|
324
289
|
end
|
325
290
|
end
|
326
|
-
end
|
327
291
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
if all_blank?(parser.fields.field_names)
|
335
|
-
{:choices => parser.fields.collect { |f| f.to_type_params }}
|
292
|
+
def to_choice_params
|
293
|
+
if fields.length == 0
|
294
|
+
{}
|
295
|
+
elsif fields.all_field_names_blank?
|
296
|
+
{:choices => fields.collect { |f| f.prototype }}
|
336
297
|
else
|
337
298
|
choices = {}
|
338
|
-
|
299
|
+
fields.each { |f| choices[f.name] = f.prototype }
|
339
300
|
{:choices => choices}
|
340
301
|
end
|
341
302
|
end
|
342
303
|
|
343
|
-
def
|
344
|
-
|
304
|
+
def to_struct_params
|
305
|
+
result = {:fields => fields}
|
306
|
+
if not endian.nil?
|
307
|
+
result[:endian] = endian
|
308
|
+
end
|
309
|
+
if option?(:hidden_fields) and not hide.empty?
|
310
|
+
result[:hide] = hide
|
311
|
+
end
|
312
|
+
|
313
|
+
result
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# An array containing a field definition of the form
|
318
|
+
# expected by BinData::Struct.
|
319
|
+
class UnSanitizedField < ::Array
|
320
|
+
def initialize(type, name, params)
|
321
|
+
super()
|
322
|
+
self << type << name << params
|
323
|
+
end
|
324
|
+
def type
|
325
|
+
self[0]
|
326
|
+
end
|
327
|
+
def name
|
328
|
+
self[1]
|
329
|
+
end
|
330
|
+
def params
|
331
|
+
self[2]
|
345
332
|
end
|
346
333
|
end
|
347
334
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
335
|
+
class UnSanitizedFields < ::Array
|
336
|
+
def initialize(endian)
|
337
|
+
@endian = endian
|
338
|
+
end
|
339
|
+
|
340
|
+
def add_field(type, name, params)
|
341
|
+
normalized_endian = @endian.respond_to?(:endian) ? @endian.endian : @endian
|
342
|
+
normalized_type = RegisteredClasses.normalize_name(type, normalized_endian)
|
343
|
+
self << UnSanitizedField.new(normalized_type, name, params)
|
344
|
+
end
|
345
|
+
|
346
|
+
def copy_fields(other)
|
347
|
+
concat(other)
|
348
|
+
end
|
349
|
+
end
|
353
350
|
end
|
354
351
|
end
|