bindata 2.0.0 → 2.1.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.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/ChangeLog.rdoc +13 -0
- data/NEWS.rdoc +16 -0
- data/README.md +5 -0
- data/bindata.gemspec +1 -0
- data/examples/gzip.rb +1 -1
- data/lib/bindata.rb +1 -1
- data/lib/bindata/array.rb +23 -22
- data/lib/bindata/base.rb +75 -49
- data/lib/bindata/base_primitive.rb +3 -32
- data/lib/bindata/bits.rb +84 -15
- data/lib/bindata/buffer.rb +19 -18
- data/lib/bindata/choice.rb +51 -67
- data/lib/bindata/dsl.rb +268 -161
- data/lib/bindata/framework.rb +0 -11
- data/lib/bindata/int.rb +67 -42
- data/lib/bindata/io.rb +13 -4
- data/lib/bindata/lazy.rb +1 -1
- data/lib/bindata/primitive.rb +9 -8
- data/lib/bindata/record.rb +9 -60
- data/lib/bindata/sanitize.rb +35 -5
- data/lib/bindata/string.rb +33 -34
- data/lib/bindata/struct.rb +166 -109
- data/lib/bindata/version.rb +1 -1
- data/lib/bindata/{deprecated.rb → warnings.rb} +9 -3
- data/test/array_test.rb +3 -3
- data/test/base_primitive_test.rb +0 -34
- data/test/bits_test.rb +38 -34
- data/test/common.rb +4 -0
- data/test/io_test.rb +15 -0
- data/test/lazy_test.rb +11 -3
- data/test/record_test.rb +83 -6
- data/test/struct_test.rb +40 -9
- data/test/system_test.rb +1 -1
- data/test/{deprecated_test.rb → warnings_test.rb} +0 -0
- metadata +18 -4
data/lib/bindata/version.rb
CHANGED
@@ -3,12 +3,12 @@ module BinData
|
|
3
3
|
|
4
4
|
# Don't override initialize. If you are defining a new kind of datatype
|
5
5
|
# (list, array, choice etc) then put your initialization code in
|
6
|
-
# #initialize_instance.
|
7
|
-
#
|
6
|
+
# #initialize_instance. BinData objects might be initialized as prototypes
|
7
|
+
# and your initialization code may not be called.
|
8
8
|
#
|
9
9
|
# If you're subclassing BinData::Record, you are definitely doing the wrong
|
10
10
|
# thing. Read the documentation on how to use BinData.
|
11
|
-
# http://
|
11
|
+
# http://github.com/dmendel/bindata/wiki/Records
|
12
12
|
alias_method :initialize_without_warning, :initialize
|
13
13
|
def initialize_with_warning(*args)
|
14
14
|
owner = method(:initialize).owner
|
@@ -29,5 +29,11 @@ module BinData
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
# #offset has been renamed to #abs_offset.
|
33
|
+
# Eventually #rel_offset will be renamed to #offset.
|
34
|
+
def offset
|
35
|
+
warn "#offset is deprecated in #{debug_name}. Use #abs_offset instead"
|
36
|
+
abs_offset
|
37
|
+
end
|
32
38
|
end
|
33
39
|
end
|
data/test/array_test.rb
CHANGED
@@ -168,7 +168,7 @@ describe BinData::Array, "with several elements" do
|
|
168
168
|
end
|
169
169
|
|
170
170
|
it "has correct offset" do
|
171
|
-
obj[2].
|
171
|
+
obj[2].rel_offset.must_equal ExampleSingle.new.num_bytes * 2
|
172
172
|
end
|
173
173
|
|
174
174
|
it "has correct num_bytes" do
|
@@ -364,8 +364,8 @@ describe BinData::Array, "of bits" do
|
|
364
364
|
end
|
365
365
|
|
366
366
|
it "has correct offset" do
|
367
|
-
obj[7].
|
368
|
-
obj[8].
|
367
|
+
obj[7].rel_offset.must_equal 0
|
368
|
+
obj[8].rel_offset.must_equal 1
|
369
369
|
end
|
370
370
|
end
|
371
371
|
|
data/test/base_primitive_test.rb
CHANGED
@@ -170,40 +170,6 @@ describe BinData::BasePrimitive, "with :value" do
|
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
173
|
-
describe BinData::BasePrimitive, "checking read value" do
|
174
|
-
let(:io) { ExampleSingle.io_with_value(12) }
|
175
|
-
|
176
|
-
describe ":check_value is non boolean" do
|
177
|
-
it "succeeds when check_value is correct" do
|
178
|
-
skip "deprecated"
|
179
|
-
data = ExampleSingle.new(:check_value => 12)
|
180
|
-
data.read(io)
|
181
|
-
data.value.must_equal 12
|
182
|
-
end
|
183
|
-
|
184
|
-
it "fails when check_value is incorrect" do
|
185
|
-
skip "deprecated"
|
186
|
-
data = ExampleSingle.new(:check_value => lambda { 99 })
|
187
|
-
lambda { data.read(io) }.must_raise BinData::ValidityError
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
describe ":check_value is boolean" do
|
192
|
-
it "succeeds when check_value is true" do
|
193
|
-
skip "deprecated"
|
194
|
-
data = ExampleSingle.new(:check_value => lambda { value < 20 })
|
195
|
-
data.read(io)
|
196
|
-
data.value.must_equal 12
|
197
|
-
end
|
198
|
-
|
199
|
-
it "fails when check_value is false" do
|
200
|
-
skip "deprecated"
|
201
|
-
data = ExampleSingle.new(:check_value => lambda { value > 20 })
|
202
|
-
lambda { data.read(io) }.must_raise BinData::ValidityError
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
173
|
describe BinData::BasePrimitive, "asserting value" do
|
208
174
|
let(:io) { ExampleSingle.io_with_value(12) }
|
209
175
|
|
data/test/bits_test.rb
CHANGED
@@ -5,66 +5,58 @@ require File.expand_path(File.join(File.dirname(__FILE__), "common"))
|
|
5
5
|
module AllBitfields
|
6
6
|
|
7
7
|
def test_has_a_sensible_value_of_zero
|
8
|
-
|
9
|
-
|
8
|
+
all_objects do |obj, nbits|
|
9
|
+
obj.must_equal 0
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_avoids_underflow
|
14
|
-
|
15
|
-
obj = bit_class.new
|
16
|
-
|
14
|
+
all_objects do |obj, nbits|
|
17
15
|
obj.assign(min_value - 1)
|
18
16
|
obj.must_equal min_value
|
19
17
|
end
|
20
18
|
end
|
21
19
|
|
22
20
|
def test_avoids_overflow
|
23
|
-
|
24
|
-
obj = bit_class.new
|
25
|
-
|
21
|
+
all_objects do |obj, nbits|
|
26
22
|
obj.assign(max_value + 1)
|
27
23
|
obj.must_equal max_value
|
28
24
|
end
|
29
25
|
end
|
30
26
|
|
31
27
|
def test_assign_values
|
32
|
-
|
28
|
+
all_objects do |obj, nbits|
|
33
29
|
some_values_within_range.each do |val|
|
34
|
-
obj = bit_class.new
|
35
30
|
obj.assign(val)
|
36
|
-
|
37
31
|
obj.must_equal val
|
38
32
|
end
|
39
33
|
end
|
40
34
|
end
|
41
35
|
|
42
36
|
def test_assign_values_from_other_bit_objects
|
43
|
-
|
37
|
+
all_objects do |obj, nbits|
|
44
38
|
some_values_within_range.each do |val|
|
45
|
-
obj
|
46
|
-
obj.assign(bit_class.new(val))
|
47
|
-
|
39
|
+
obj.assign(obj.new(val))
|
48
40
|
obj.must_equal val
|
49
41
|
end
|
50
42
|
end
|
51
43
|
end
|
52
44
|
|
53
45
|
def test_symmetrically_read_and_write
|
54
|
-
|
46
|
+
all_objects do |obj, nbits|
|
55
47
|
some_values_within_range.each do |val|
|
56
|
-
obj = bit_class.new
|
57
48
|
obj.assign(val)
|
58
|
-
|
59
|
-
obj.
|
49
|
+
other = obj.new
|
50
|
+
other.read(obj.to_binary_s)
|
51
|
+
other.must_equal obj
|
60
52
|
end
|
61
53
|
end
|
62
54
|
end
|
63
55
|
|
64
|
-
def
|
65
|
-
@bits.
|
56
|
+
def all_objects(&block)
|
57
|
+
@bits.each do |obj, nbits|
|
66
58
|
@nbits = nbits
|
67
|
-
yield
|
59
|
+
yield obj, nbits
|
68
60
|
end
|
69
61
|
end
|
70
62
|
|
@@ -98,7 +90,7 @@ module AllBitfields
|
|
98
90
|
end
|
99
91
|
|
100
92
|
def generate_bit_classes_to_test(endian, signed)
|
101
|
-
bits =
|
93
|
+
bits = []
|
102
94
|
if signed
|
103
95
|
base = "Sbit"
|
104
96
|
start = 2
|
@@ -107,12 +99,20 @@ def generate_bit_classes_to_test(endian, signed)
|
|
107
99
|
start = 1
|
108
100
|
end
|
109
101
|
|
110
|
-
(start ..
|
102
|
+
(start .. 64).each do |nbits|
|
111
103
|
name = "#{base}#{nbits}"
|
112
104
|
name << "le" if endian == :little
|
113
|
-
|
114
|
-
bits[
|
105
|
+
obj = BinData.const_get(name).new
|
106
|
+
bits << [obj, nbits]
|
107
|
+
end
|
108
|
+
|
109
|
+
(start .. 64).each do |nbits|
|
110
|
+
name = "#{base}"
|
111
|
+
name << "Le" if endian == :little
|
112
|
+
obj = BinData.const_get(name).new(:nbits => nbits)
|
113
|
+
bits << [obj, nbits]
|
115
114
|
end
|
115
|
+
|
116
116
|
bits
|
117
117
|
end
|
118
118
|
|
@@ -125,11 +125,12 @@ describe "Unsigned big endian bitfields" do
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it "read big endian values" do
|
128
|
-
|
128
|
+
all_objects do |obj, nbits|
|
129
129
|
nbytes = (nbits + 7) / 8
|
130
130
|
str = [0b1000_0000].pack("C") + "\000" * (nbytes - 1)
|
131
131
|
|
132
|
-
|
132
|
+
obj.read(str)
|
133
|
+
obj.must_equal 1 << (nbits - 1)
|
133
134
|
end
|
134
135
|
end
|
135
136
|
end
|
@@ -143,11 +144,12 @@ describe "Signed big endian bitfields" do
|
|
143
144
|
end
|
144
145
|
|
145
146
|
it "read big endian values" do
|
146
|
-
|
147
|
+
all_objects do |obj, nbits|
|
147
148
|
nbytes = (nbits + 7) / 8
|
148
149
|
str = [0b0100_0000].pack("C") + "\000" * (nbytes - 1)
|
149
150
|
|
150
|
-
|
151
|
+
obj.read(str)
|
152
|
+
obj.must_equal 1 << (nbits - 2)
|
151
153
|
end
|
152
154
|
end
|
153
155
|
end
|
@@ -161,11 +163,12 @@ describe "Unsigned little endian bitfields" do
|
|
161
163
|
end
|
162
164
|
|
163
165
|
it "read little endian values" do
|
164
|
-
|
166
|
+
all_objects do |obj, nbits|
|
165
167
|
nbytes = (nbits + 7) / 8
|
166
168
|
str = [0b0000_0001].pack("C") + "\000" * (nbytes - 1)
|
167
169
|
|
168
|
-
|
170
|
+
obj.read(str)
|
171
|
+
obj.must_equal 1
|
169
172
|
end
|
170
173
|
end
|
171
174
|
end
|
@@ -179,11 +182,12 @@ describe "Signed little endian bitfields" do
|
|
179
182
|
end
|
180
183
|
|
181
184
|
it "read little endian values" do
|
182
|
-
|
185
|
+
all_objects do |obj, nbits|
|
183
186
|
nbytes = (nbits + 7) / 8
|
184
187
|
str = [0b0000_0001].pack("C") + "\000" * (nbytes - 1)
|
185
188
|
|
186
|
-
|
189
|
+
obj.read(str)
|
190
|
+
obj.must_equal 1
|
187
191
|
end
|
188
192
|
end
|
189
193
|
end
|
data/test/common.rb
CHANGED
data/test/io_test.rb
CHANGED
@@ -152,6 +152,21 @@ describe BinData::IO::Write, "when writing" do
|
|
152
152
|
stream.value.must_equal "abcd"
|
153
153
|
end
|
154
154
|
|
155
|
+
it "has #offset" do
|
156
|
+
io.offset.must_equal 0
|
157
|
+
|
158
|
+
io.writebytes("abcd")
|
159
|
+
io.offset.must_equal 4
|
160
|
+
|
161
|
+
io.writebytes("ABCD")
|
162
|
+
io.offset.must_equal 8
|
163
|
+
end
|
164
|
+
|
165
|
+
it "rounds up #offset when writing bits" do
|
166
|
+
io.writebits(123, 9, :little)
|
167
|
+
io.offset.must_equal 2
|
168
|
+
end
|
169
|
+
|
155
170
|
it "flushes" do
|
156
171
|
io.writebytes("abcd")
|
157
172
|
io.flush
|
data/test/lazy_test.rb
CHANGED
@@ -73,12 +73,16 @@ end
|
|
73
73
|
|
74
74
|
describe BinData::LazyEvaluator, "with one parent" do
|
75
75
|
subject {
|
76
|
-
parent_methods = {:m1 => 'Pm1', :com1 => 'PmC', :mm => 3}
|
76
|
+
parent_methods = {:m1 => 'Pm1', :m2 => 'Pm2', :com1 => 'PmC', :mm => 3}
|
77
77
|
parent_params = {:p1 => 'Pp1', :com1 => 'PpC'}
|
78
78
|
parent_obj = MockBinDataObject.new(parent_methods, parent_params)
|
79
79
|
|
80
|
-
|
81
|
-
|
80
|
+
class << parent_obj
|
81
|
+
def echo(a1, a2)
|
82
|
+
[a1, a2]
|
83
|
+
end
|
84
|
+
|
85
|
+
private :m2
|
82
86
|
end
|
83
87
|
|
84
88
|
methods = {:m1 => 'm1', :com1 => 'mC'}
|
@@ -118,6 +122,10 @@ describe BinData::LazyEvaluator, "with one parent" do
|
|
118
122
|
lazy_eval(lambda { echo(p1, m1) }).must_equal ['Pp1', 'Pm1']
|
119
123
|
end
|
120
124
|
|
125
|
+
it "invokes private methods in the parent" do
|
126
|
+
lazy_eval(lambda { m2 }).must_equal 'Pm2'
|
127
|
+
end
|
128
|
+
|
121
129
|
it "resolves parameters in preference to methods in the parent" do
|
122
130
|
lazy_eval(lambda { com1 }).must_equal 'PpC'
|
123
131
|
end
|
data/test/record_test.rb
CHANGED
@@ -241,12 +241,12 @@ describe BinData::Record, "with nested structs" do
|
|
241
241
|
obj.c.y.must_equal 3
|
242
242
|
end
|
243
243
|
|
244
|
-
it "returns correct
|
245
|
-
obj.
|
246
|
-
obj.b.
|
247
|
-
obj.b.w.
|
248
|
-
obj.c.
|
249
|
-
obj.c.z.
|
244
|
+
it "returns correct abs_offset" do
|
245
|
+
obj.abs_offset.must_equal 0
|
246
|
+
obj.b.abs_offset.must_equal 1
|
247
|
+
obj.b.w.abs_offset.must_equal 1
|
248
|
+
obj.c.abs_offset.must_equal 3
|
249
|
+
obj.c.z.abs_offset.must_equal 4
|
250
250
|
end
|
251
251
|
|
252
252
|
it "returns correct rel_offset" do
|
@@ -378,6 +378,77 @@ describe BinData::Record, "with an endian defined" do
|
|
378
378
|
end
|
379
379
|
end
|
380
380
|
|
381
|
+
describe BinData::Record, "with endian :big_and_little" do
|
382
|
+
class RecordWithBnLEndian < BinData::Record
|
383
|
+
endian :big_and_little
|
384
|
+
int16 :a, :value => 1
|
385
|
+
end
|
386
|
+
|
387
|
+
it "is not registered" do
|
388
|
+
lambda {
|
389
|
+
BinData::RegisteredClasses.lookup("RecordWithBnLEndian")
|
390
|
+
}.must_raise BinData::UnRegisteredTypeError
|
391
|
+
end
|
392
|
+
|
393
|
+
it "creates big endian version" do
|
394
|
+
obj = RecordWithBnLEndianBe.new
|
395
|
+
obj.to_binary_s.must_equal binary("\x00\x01")
|
396
|
+
end
|
397
|
+
|
398
|
+
it "creates little endian version" do
|
399
|
+
obj = RecordWithBnLEndianLe.new
|
400
|
+
obj.to_binary_s.must_equal binary("\x01\x00")
|
401
|
+
end
|
402
|
+
|
403
|
+
it "requires :endian as argument" do
|
404
|
+
lambda {
|
405
|
+
RecordWithBnLEndian.new
|
406
|
+
}.must_raise ArgumentError
|
407
|
+
end
|
408
|
+
|
409
|
+
it "accepts :endian as argument" do
|
410
|
+
obj = RecordWithBnLEndian.new(:endian => :little)
|
411
|
+
obj.to_binary_s.must_equal binary("\x01\x00")
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe BinData::Record, "with endian :big_and_little when subclassed" do
|
416
|
+
class ARecordWithBnLEndian < BinData::Record
|
417
|
+
endian :big_and_little
|
418
|
+
int16 :a, :value => 1
|
419
|
+
end
|
420
|
+
class BRecordWithBnLEndian < ARecordWithBnLEndian
|
421
|
+
int16 :b, :value => 2
|
422
|
+
end
|
423
|
+
|
424
|
+
it "is not registered" do
|
425
|
+
lambda {
|
426
|
+
BinData::RegisteredClasses.lookup("BRecordWithBnLEndian")
|
427
|
+
}.must_raise BinData::UnRegisteredTypeError
|
428
|
+
end
|
429
|
+
|
430
|
+
it "creates big endian version" do
|
431
|
+
obj = BRecordWithBnLEndianBe.new
|
432
|
+
obj.to_binary_s.must_equal binary("\x00\x01\x00\x02")
|
433
|
+
end
|
434
|
+
|
435
|
+
it "creates little endian version" do
|
436
|
+
obj = BRecordWithBnLEndianLe.new
|
437
|
+
obj.to_binary_s.must_equal binary("\x01\x00\x02\x00")
|
438
|
+
end
|
439
|
+
|
440
|
+
it "requires :endian as argument" do
|
441
|
+
lambda {
|
442
|
+
BRecordWithBnLEndian.new
|
443
|
+
}.must_raise ArgumentError
|
444
|
+
end
|
445
|
+
|
446
|
+
it "accepts :endian as argument" do
|
447
|
+
obj = BRecordWithBnLEndian.new(:endian => :little)
|
448
|
+
obj.to_binary_s.must_equal binary("\x01\x00\x02\x00")
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
381
452
|
describe BinData::Record, "defined recursively" do
|
382
453
|
class RecursiveRecord < BinData::Record
|
383
454
|
endian :big
|
@@ -476,6 +547,12 @@ describe BinData::Record, "with :onlyif" do
|
|
476
547
|
obj.to_binary_s.must_equal "\x03\x05"
|
477
548
|
end
|
478
549
|
|
550
|
+
it "identifies if fields are included" do
|
551
|
+
obj.a?.must_equal true
|
552
|
+
obj.b?.must_equal true
|
553
|
+
obj.c?.must_equal false
|
554
|
+
end
|
555
|
+
|
479
556
|
it "reads as lambdaed" do
|
480
557
|
obj.read("\x01\x02")
|
481
558
|
obj.snapshot.must_equal({:a => 1, :c => 2})
|
data/test/struct_test.rb
CHANGED
@@ -250,11 +250,11 @@ describe BinData::Struct, "with nested structs" do
|
|
250
250
|
obj.c.z.must_equal 0
|
251
251
|
end
|
252
252
|
|
253
|
-
it "returns correct
|
254
|
-
obj.b.
|
255
|
-
obj.b.w.
|
256
|
-
obj.c.
|
257
|
-
obj.c.z.
|
253
|
+
it "returns correct abs_offset" do
|
254
|
+
obj.b.abs_offset.must_equal 1
|
255
|
+
obj.b.w.abs_offset.must_equal 1
|
256
|
+
obj.c.abs_offset.must_equal 3
|
257
|
+
obj.c.z.abs_offset.must_equal 4
|
258
258
|
end
|
259
259
|
end
|
260
260
|
|
@@ -313,10 +313,10 @@ describe BinData::Struct, "with bit fields" do
|
|
313
313
|
end
|
314
314
|
|
315
315
|
it "has correct offsets" do
|
316
|
-
obj.a.
|
317
|
-
obj.b.
|
318
|
-
obj.c.
|
319
|
-
obj.d.
|
316
|
+
obj.a.rel_offset.must_equal 0
|
317
|
+
obj.b.rel_offset.must_equal 0
|
318
|
+
obj.c.rel_offset.must_equal 1
|
319
|
+
obj.d.rel_offset.must_equal 2
|
320
320
|
end
|
321
321
|
end
|
322
322
|
|
@@ -338,6 +338,37 @@ describe BinData::Struct, "with nested endian" do
|
|
338
338
|
end
|
339
339
|
end
|
340
340
|
|
341
|
+
describe BinData::Struct, "with byte_align" do
|
342
|
+
let(:obj) {
|
343
|
+
params = { :fields => [[:int8, :a],
|
344
|
+
[:int8, :b, :byte_align => 5],
|
345
|
+
[:bit2, :c],
|
346
|
+
[:int8, :d, :byte_align => 3]] }
|
347
|
+
BinData::Struct.new(params)
|
348
|
+
}
|
349
|
+
|
350
|
+
it "has #num_bytes" do
|
351
|
+
obj.num_bytes.must_equal 10
|
352
|
+
end
|
353
|
+
|
354
|
+
it "reads" do
|
355
|
+
obj.read("\x01\x00\x00\x00\x00\x02\xc0\x00\x00\x04")
|
356
|
+
obj.snapshot.must_equal({ :a => 1, :b => 2, :c => 3, :d => 4 })
|
357
|
+
end
|
358
|
+
|
359
|
+
it "writes" do
|
360
|
+
obj.assign(:a => 1, :b => 2, :c => 3, :d => 4)
|
361
|
+
obj.to_binary_s.must_equal binary("\x01\x00\x00\x00\x00\x02\xc0\x00\x00\x04")
|
362
|
+
end
|
363
|
+
|
364
|
+
it "has correct offsets" do
|
365
|
+
obj.a.rel_offset.must_equal 0
|
366
|
+
obj.b.rel_offset.must_equal 5
|
367
|
+
obj.c.rel_offset.must_equal 6
|
368
|
+
obj.d.rel_offset.must_equal 9
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
341
372
|
describe BinData::Struct, "with dynamically named types" do
|
342
373
|
it "instantiates" do
|
343
374
|
dyn = BinData::Struct.new(:name => :my_struct, :fields => [[:int8, :a, {:initial_value => 3}]])
|