bindata 1.1.0 → 1.2.0
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.
- data/ChangeLog +7 -0
- data/README +32 -1167
- data/lib/bindata.rb +3 -3
- data/lib/bindata/array.rb +5 -6
- data/lib/bindata/base.rb +40 -58
- data/lib/bindata/base_primitive.rb +7 -11
- data/lib/bindata/bits.rb +47 -44
- data/lib/bindata/choice.rb +7 -11
- data/lib/bindata/deprecated.rb +17 -2
- data/lib/bindata/dsl.rb +332 -0
- data/lib/bindata/float.rb +48 -50
- data/lib/bindata/int.rb +66 -88
- data/lib/bindata/params.rb +112 -59
- data/lib/bindata/primitive.rb +8 -88
- data/lib/bindata/record.rb +11 -99
- data/lib/bindata/registry.rb +16 -3
- data/lib/bindata/rest.rb +1 -1
- data/lib/bindata/sanitize.rb +71 -53
- data/lib/bindata/skip.rb +2 -1
- data/lib/bindata/string.rb +3 -3
- data/lib/bindata/stringz.rb +1 -1
- data/lib/bindata/struct.rb +21 -20
- data/lib/bindata/trace.rb +8 -0
- data/lib/bindata/wrapper.rb +13 -69
- data/manual.haml +2 -2
- data/spec/array_spec.rb +1 -1
- data/spec/base_primitive_spec.rb +4 -4
- data/spec/base_spec.rb +19 -6
- data/spec/bits_spec.rb +5 -1
- data/spec/choice_spec.rb +13 -2
- data/spec/deprecated_spec.rb +31 -0
- data/spec/example.rb +5 -1
- data/spec/io_spec.rb +2 -4
- data/spec/lazy_spec.rb +10 -5
- data/spec/primitive_spec.rb +13 -5
- data/spec/record_spec.rb +149 -45
- data/spec/registry_spec.rb +18 -6
- data/spec/spec_common.rb +31 -6
- data/spec/string_spec.rb +0 -1
- data/spec/stringz_spec.rb +4 -4
- data/spec/struct_spec.rb +2 -2
- data/spec/system_spec.rb +26 -19
- data/spec/wrapper_spec.rb +52 -4
- data/tasks/manual.rake +1 -1
- data/tasks/pkg.rake +13 -0
- metadata +121 -46
- data/TODO +0 -3
data/spec/lazy_spec.rb
CHANGED
@@ -6,8 +6,8 @@ require 'bindata/lazy'
|
|
6
6
|
# A mock data object with customizable fields.
|
7
7
|
class MockDataObject
|
8
8
|
def initialize(methods = {}, params = {}, parent = nil)
|
9
|
+
meta = class << self ; self; end
|
9
10
|
methods.each do |k,v|
|
10
|
-
meta = class << self ; self; end
|
11
11
|
meta.send(:define_method, k.to_sym) { v }
|
12
12
|
end
|
13
13
|
@parameters = params
|
@@ -15,12 +15,12 @@ class MockDataObject
|
|
15
15
|
end
|
16
16
|
attr_accessor :parent
|
17
17
|
|
18
|
-
def has_parameter?(
|
19
|
-
@parameters.has_key?(
|
18
|
+
def has_parameter?(key)
|
19
|
+
@parameters.has_key?(key)
|
20
20
|
end
|
21
21
|
|
22
|
-
def get_parameter(
|
23
|
-
@parameters[
|
22
|
+
def get_parameter(key)
|
23
|
+
@parameters[key]
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -34,6 +34,11 @@ describe BinData::LazyEvaluator, "with no parents" do
|
|
34
34
|
@obj = MockDataObject.new(methods, params)
|
35
35
|
end
|
36
36
|
|
37
|
+
it "should evaluate raw value when instantiated" do
|
38
|
+
le = LE.new(@obj)
|
39
|
+
le.lazy_eval(5).should == 5
|
40
|
+
end
|
41
|
+
|
37
42
|
it "should evaluate raw value" do
|
38
43
|
LE.eval(@obj, 5).should == 5
|
39
44
|
end
|
data/spec/primitive_spec.rb
CHANGED
@@ -18,13 +18,15 @@ describe BinData::Primitive, "when subclassing" do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
describe BinData::Primitive, "when defining" do
|
21
|
+
describe BinData::Primitive, "when defining with errors" do
|
22
22
|
it "should fail on non registered types" do
|
23
23
|
lambda {
|
24
24
|
class BadTypePrimitive < BinData::Primitive
|
25
25
|
non_registered_type :a
|
26
26
|
end
|
27
|
-
}.should
|
27
|
+
}.should raise_error_on_line(TypeError, 2) { |err|
|
28
|
+
err.message.should == "unknown type 'non_registered_type' in #{BadTypePrimitive}"
|
29
|
+
}
|
28
30
|
end
|
29
31
|
|
30
32
|
it "should fail on duplicate names" do
|
@@ -34,7 +36,9 @@ describe BinData::Primitive, "when defining" do
|
|
34
36
|
int8 :b
|
35
37
|
int8 :a
|
36
38
|
end
|
37
|
-
}.should
|
39
|
+
}.should raise_error_on_line(SyntaxError, 4) { |err|
|
40
|
+
err.message.should == "duplicate field 'a' in #{DuplicateNamePrimitive}"
|
41
|
+
}
|
38
42
|
end
|
39
43
|
|
40
44
|
it "should fail when field name shadows an existing method" do
|
@@ -42,7 +46,9 @@ describe BinData::Primitive, "when defining" do
|
|
42
46
|
class ExistingNamePrimitive < BinData::Primitive
|
43
47
|
int8 :object_id
|
44
48
|
end
|
45
|
-
}.should
|
49
|
+
}.should raise_error_on_line(NameError, 2) { |err|
|
50
|
+
err.message.should == "field 'object_id' shadows an existing method in #{ExistingNamePrimitive}"
|
51
|
+
}
|
46
52
|
end
|
47
53
|
|
48
54
|
it "should fail on unknown endian" do
|
@@ -50,7 +56,9 @@ describe BinData::Primitive, "when defining" do
|
|
50
56
|
class BadEndianPrimitive < BinData::Primitive
|
51
57
|
endian 'a bad value'
|
52
58
|
end
|
53
|
-
}.should
|
59
|
+
}.should raise_error_on_line(ArgumentError, 2) { |err|
|
60
|
+
err.message.should == "unknown value for endian 'a bad value' in #{BadEndianPrimitive}"
|
61
|
+
}
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
data/spec/record_spec.rb
CHANGED
@@ -3,71 +3,93 @@
|
|
3
3
|
require File.expand_path(File.join(File.dirname(__FILE__), "spec_common"))
|
4
4
|
require 'bindata'
|
5
5
|
|
6
|
-
|
7
|
-
block.call
|
8
|
-
rescue Exception => err
|
9
|
-
err.class.should == exception_type
|
10
|
-
return err
|
11
|
-
else
|
12
|
-
lambda {}.should raise_error(exception_type)
|
13
|
-
end
|
14
|
-
|
15
|
-
describe BinData::Record, "when defining" do
|
6
|
+
describe BinData::Record, "when defining with errors" do
|
16
7
|
it "should fail on non registered types" do
|
17
|
-
|
8
|
+
lambda {
|
18
9
|
class BadTypeRecord < BinData::Record
|
19
10
|
non_registered_type :a
|
20
11
|
end
|
12
|
+
}.should raise_error_on_line(TypeError, 2) { |err|
|
13
|
+
err.message.should == "unknown type 'non_registered_type' in #{BadTypeRecord}"
|
21
14
|
}
|
22
|
-
err.message.should == "unknown type 'non_registered_type' for #{BadTypeRecord}"
|
23
15
|
end
|
24
16
|
|
25
17
|
it "should give correct error message for non registered nested types" do
|
26
|
-
|
18
|
+
lambda {
|
27
19
|
class BadNestedTypeRecord < BinData::Record
|
28
20
|
array :a, :type => :non_registered_type
|
29
21
|
end
|
22
|
+
}.should raise_error_on_line(TypeError, 2) { |err|
|
23
|
+
err.message.should == "unknown type 'non_registered_type' in #{BadNestedTypeRecord}"
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should give correct error message for non registered nested types in blocks" do
|
28
|
+
lambda {
|
29
|
+
class BadNestedTypeInBlockRecord < BinData::Record
|
30
|
+
array :a do
|
31
|
+
non_registered_type
|
32
|
+
end
|
33
|
+
end
|
34
|
+
}.should raise_error_on_line(TypeError, 3) { |err|
|
35
|
+
err.message.should == "unknown type 'non_registered_type' in #{BinData::Array}"
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should fail on nested choice when missing names" do
|
40
|
+
lambda {
|
41
|
+
class MissingChoiceNamesRecord < BinData::Record
|
42
|
+
choice do
|
43
|
+
int8 :a
|
44
|
+
int8
|
45
|
+
end
|
46
|
+
end
|
47
|
+
}.should raise_error_on_line(SyntaxError, 4) { |err|
|
48
|
+
err.message.should == "fields must either all have names, or none must have names in BinData::Choice"
|
30
49
|
}
|
31
|
-
err.message.should == "unknown type 'non_registered_type' for #{BadNestedTypeRecord}"
|
32
50
|
end
|
33
51
|
|
34
52
|
it "should fail on duplicate names" do
|
35
|
-
|
53
|
+
lambda {
|
36
54
|
class DuplicateNameRecord < BinData::Record
|
37
55
|
int8 :a
|
38
56
|
int8 :b
|
39
57
|
int8 :a
|
40
58
|
end
|
59
|
+
}.should raise_error_on_line(SyntaxError, 4) { |err|
|
60
|
+
err.message.should == "duplicate field 'a' in #{DuplicateNameRecord}"
|
41
61
|
}
|
42
|
-
err.message.should == "duplicate field 'a' in #{DuplicateNameRecord}"
|
43
62
|
end
|
44
63
|
|
45
64
|
it "should fail on reserved names" do
|
46
|
-
|
65
|
+
lambda {
|
47
66
|
class ReservedNameRecord < BinData::Record
|
48
67
|
int8 :a
|
49
68
|
int8 :invert # from Hash.instance_methods
|
50
69
|
end
|
70
|
+
}.should raise_error_on_line(NameError, 3) { |err|
|
71
|
+
err.message.should == "field 'invert' is a reserved name in #{ReservedNameRecord}"
|
51
72
|
}
|
52
|
-
err.message.should == "field 'invert' is a reserved name in #{ReservedNameRecord}"
|
53
73
|
end
|
54
74
|
|
55
75
|
it "should fail when field name shadows an existing method" do
|
56
|
-
|
76
|
+
lambda {
|
57
77
|
class ExistingNameRecord < BinData::Record
|
58
78
|
int8 :object_id
|
59
79
|
end
|
80
|
+
}.should raise_error_on_line(NameError, 2) { |err|
|
81
|
+
err.message.should == "field 'object_id' shadows an existing method in #{ExistingNameRecord}"
|
60
82
|
}
|
61
|
-
err.message.should == "field 'object_id' shadows an existing method in #{ExistingNameRecord}"
|
62
83
|
end
|
63
84
|
|
64
85
|
it "should fail on unknown endian" do
|
65
|
-
|
86
|
+
lambda {
|
66
87
|
class BadEndianRecord < BinData::Record
|
67
88
|
endian 'a bad value'
|
68
89
|
end
|
90
|
+
}.should raise_error_on_line(ArgumentError, 2) { |err|
|
91
|
+
err.message.should == "unknown value for endian 'a bad value' in #{BadEndianRecord}"
|
69
92
|
}
|
70
|
-
err.message.should == "unknown value for endian 'a bad value' in #{BadEndianRecord}"
|
71
93
|
end
|
72
94
|
end
|
73
95
|
|
@@ -75,6 +97,7 @@ describe BinData::Record, "with anonymous fields" do
|
|
75
97
|
class AnonymousRecord < BinData::Record
|
76
98
|
int8 'a', :initial_value => 10
|
77
99
|
int8 ''
|
100
|
+
int8
|
78
101
|
int8 :value => :a
|
79
102
|
end
|
80
103
|
|
@@ -92,10 +115,10 @@ describe BinData::Record, "with anonymous fields" do
|
|
92
115
|
end
|
93
116
|
|
94
117
|
it "should write anonymous fields" do
|
95
|
-
str = "\001\002\003"
|
118
|
+
str = "\001\002\003\004"
|
96
119
|
@obj.read(str)
|
97
120
|
@obj.a.clear
|
98
|
-
@obj.to_binary_s.should == "\012\002\012"
|
121
|
+
@obj.to_binary_s.should == "\012\002\003\012"
|
99
122
|
end
|
100
123
|
end
|
101
124
|
|
@@ -195,30 +218,31 @@ describe BinData::Record, "with multiple fields" do
|
|
195
218
|
end
|
196
219
|
|
197
220
|
describe BinData::Record, "with nested structs" do
|
198
|
-
class
|
199
|
-
int8
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
int8 :a, :initial_value => 6
|
210
|
-
inner1_record :b, :the_val => :a
|
211
|
-
inner2_record :c
|
221
|
+
class NestedStructRecord < BinData::Record
|
222
|
+
int8 :a, :initial_value => 6
|
223
|
+
struct :b, :the_val => :a do
|
224
|
+
hide :w
|
225
|
+
int8 :w, :initial_value => 3
|
226
|
+
int8 :x, :value => :the_val
|
227
|
+
end
|
228
|
+
struct :c do
|
229
|
+
int8 :y, :value => lambda { b.w }
|
230
|
+
int8 :z
|
231
|
+
end
|
212
232
|
end
|
213
233
|
|
214
234
|
before(:each) do
|
215
|
-
@obj =
|
235
|
+
@obj = NestedStructRecord.new
|
216
236
|
end
|
217
237
|
|
218
238
|
it "should included nested field names" do
|
219
239
|
@obj.field_names.should == ["a", "b", "c"]
|
220
240
|
end
|
221
241
|
|
242
|
+
it "should hide nested field names" do
|
243
|
+
@obj.b.field_names.should == ["x"]
|
244
|
+
end
|
245
|
+
|
222
246
|
it "should access nested fields" do
|
223
247
|
@obj.a.should == 6
|
224
248
|
@obj.b.w.should == 3
|
@@ -243,16 +267,97 @@ describe BinData::Record, "with nested structs" do
|
|
243
267
|
end
|
244
268
|
end
|
245
269
|
|
270
|
+
describe BinData::Record, "with nested array of primitives" do
|
271
|
+
class NestedPrimitiveArrayRecord < BinData::Record
|
272
|
+
array :a, :initial_length => 3 do
|
273
|
+
uint8 :value => lambda { index }
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
before(:each) do
|
278
|
+
@obj = NestedPrimitiveArrayRecord.new
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should use block as :type" do
|
282
|
+
@obj.snapshot.should == {"a" => [0, 1, 2]}
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
describe BinData::Record, "with nested array of structs" do
|
287
|
+
class NestedStructArrayRecord < BinData::Record
|
288
|
+
array :a do
|
289
|
+
uint8 :b
|
290
|
+
uint8 :c
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
before(:each) do
|
295
|
+
@obj = NestedStructArrayRecord.new
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should use block as struct for :type" do
|
299
|
+
@obj.a[0].b = 2
|
300
|
+
@obj.snapshot.should == {"a" => [{"b" => 2, "c" => 0}]}
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
describe BinData::Record, "with nested choice without names" do
|
305
|
+
class NestedChoiceRecord < BinData::Record
|
306
|
+
choice :a, :selection => 1 do
|
307
|
+
uint8 :value => 1
|
308
|
+
uint8 :value => 2
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
before(:each) do
|
313
|
+
@obj = NestedChoiceRecord.new
|
314
|
+
end
|
315
|
+
|
316
|
+
it "should select choices by index" do
|
317
|
+
@obj.a.should == 2
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
describe BinData::Record, "with nested choice with names" do
|
322
|
+
class NestedChoiceWithNamesRecord < BinData::Record
|
323
|
+
choice :a, :selection => "b" do
|
324
|
+
uint8 "b", :value => 1
|
325
|
+
uint8 "c", :value => 2
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
before(:each) do
|
330
|
+
@obj = NestedChoiceWithNamesRecord.new
|
331
|
+
end
|
332
|
+
|
333
|
+
it "should select choices by name" do
|
334
|
+
@obj.a.should == 1
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
246
338
|
describe BinData::Record, "with an endian defined" do
|
247
339
|
class RecordWithEndian < BinData::Record
|
248
340
|
endian :little
|
249
341
|
|
250
342
|
uint16 :a
|
251
343
|
float :b
|
252
|
-
array :c, :
|
253
|
-
|
254
|
-
|
255
|
-
|
344
|
+
array :c, :initial_length => 2 do
|
345
|
+
int8
|
346
|
+
end
|
347
|
+
choice :d, :selection => 1 do
|
348
|
+
uint16
|
349
|
+
uint32
|
350
|
+
end
|
351
|
+
struct :e do
|
352
|
+
uint16 :f
|
353
|
+
uint32be :g
|
354
|
+
end
|
355
|
+
struct :h do
|
356
|
+
endian :big
|
357
|
+
struct :i do
|
358
|
+
uint16 :j
|
359
|
+
end
|
360
|
+
end
|
256
361
|
end
|
257
362
|
|
258
363
|
before(:each) do
|
@@ -269,7 +374,7 @@ describe BinData::Record, "with an endian defined" do
|
|
269
374
|
@obj.e.g = 7
|
270
375
|
@obj.h.i.j = 8
|
271
376
|
|
272
|
-
expected = [1, 2.0, 3, 4, 5, 6, 7, 8].pack('
|
377
|
+
expected = [1, 2.0, 3, 4, 5, 6, 7, 8].pack('veCCVvNn')
|
273
378
|
|
274
379
|
@obj.to_binary_s.should == expected
|
275
380
|
end
|
@@ -398,4 +503,3 @@ describe BinData::Record, "derived classes" do
|
|
398
503
|
child.field_names.should == ["a", "b"]
|
399
504
|
end
|
400
505
|
end
|
401
|
-
|
data/spec/registry_spec.rb
CHANGED
@@ -23,7 +23,9 @@ describe BinData::Registry do
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should determine if a name is not registered" do
|
26
|
-
|
26
|
+
lambda {
|
27
|
+
@r.is_registered?('xyz')
|
28
|
+
}.should raise_error(BinData::UnRegisteredTypeError)
|
27
29
|
end
|
28
30
|
|
29
31
|
it "should lookup registered names" do
|
@@ -35,7 +37,9 @@ describe BinData::Registry do
|
|
35
37
|
end
|
36
38
|
|
37
39
|
it "should not lookup unregistered names" do
|
38
|
-
|
40
|
+
lambda {
|
41
|
+
@r.lookup('a_non_existent_sub_class')
|
42
|
+
}.should raise_error(BinData::UnRegisteredTypeError)
|
39
43
|
end
|
40
44
|
|
41
45
|
it "should allow overriding of registered classes" do
|
@@ -71,13 +75,21 @@ describe BinData::Registry, "with numerics" do
|
|
71
75
|
end
|
72
76
|
|
73
77
|
it "should not lookup integers without endian" do
|
74
|
-
|
78
|
+
lambda {
|
79
|
+
@r.lookup("int24")
|
80
|
+
}.should raise_error(BinData::UnRegisteredTypeError)
|
75
81
|
end
|
76
82
|
|
77
83
|
it "should not lookup non byte based integers" do
|
78
|
-
|
79
|
-
|
80
|
-
|
84
|
+
lambda {
|
85
|
+
@r.lookup("int3")
|
86
|
+
}.should raise_error(BinData::UnRegisteredTypeError)
|
87
|
+
lambda {
|
88
|
+
@r.lookup("int3", :big)
|
89
|
+
}.should raise_error(BinData::UnRegisteredTypeError)
|
90
|
+
lambda {
|
91
|
+
@r.lookup("int3", :little)
|
92
|
+
}.should raise_error(BinData::UnRegisteredTypeError)
|
81
93
|
end
|
82
94
|
|
83
95
|
it "should lookup floats with endian" do
|
data/spec/spec_common.rb
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
2
2
|
|
3
|
-
begin
|
4
|
-
require 'rubygems'
|
5
|
-
gem 'rspec', '> 1.2.2'
|
6
|
-
rescue LoadError
|
7
|
-
end
|
8
|
-
|
9
3
|
require 'spec'
|
10
4
|
require 'spec/autorun'
|
11
5
|
require 'stringio'
|
@@ -20,3 +14,34 @@ class Object
|
|
20
14
|
cls.send(:public, *protected_method_names)
|
21
15
|
end
|
22
16
|
end
|
17
|
+
|
18
|
+
class StringIO
|
19
|
+
# Returns the value that was written to the io
|
20
|
+
def value
|
21
|
+
rewind
|
22
|
+
read
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def exception_line(ex)
|
27
|
+
idx = ex.backtrace.find_index { |bt| /:in `should'$/ =~ bt }
|
28
|
+
|
29
|
+
if idx
|
30
|
+
line_num_regex = /.*:(\d+)$/
|
31
|
+
|
32
|
+
err_line = line_num_regex.match(ex.backtrace[0])[1].to_i
|
33
|
+
ref_line = line_num_regex.match(ex.backtrace[idx + 1])[1].to_i
|
34
|
+
|
35
|
+
err_line - ref_line
|
36
|
+
else
|
37
|
+
raise "Required calling pattern is lambda { xxx }.should raise_error_on_line(...)"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def raise_error_on_line(exception, line, &block)
|
42
|
+
raise_exception(exception) do |err|
|
43
|
+
exception_line(err).should == line
|
44
|
+
block.call(err) if block_given?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|