bindata 2.4.10 → 2.5.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 +39 -0
- data/LICENSE +25 -0
- data/NEWS.rdoc +5 -0
- data/README.md +6 -9
- data/bindata.gemspec +9 -4
- data/examples/NBT.txt +1 -1
- data/examples/list.rb +1 -1
- data/lib/bindata/alignment.rb +15 -7
- data/lib/bindata/array.rb +54 -54
- data/lib/bindata/base.rb +14 -25
- data/lib/bindata/base_primitive.rb +24 -20
- data/lib/bindata/bits.rb +15 -15
- data/lib/bindata/buffer.rb +89 -11
- data/lib/bindata/choice.rb +9 -6
- data/lib/bindata/count_bytes_remaining.rb +1 -1
- data/lib/bindata/delayed_io.rb +18 -10
- data/lib/bindata/dsl.rb +37 -35
- data/lib/bindata/float.rb +3 -3
- data/lib/bindata/framework.rb +8 -10
- data/lib/bindata/int.rb +14 -16
- data/lib/bindata/io.rb +276 -253
- data/lib/bindata/name.rb +1 -1
- data/lib/bindata/params.rb +9 -7
- data/lib/bindata/primitive.rb +3 -3
- data/lib/bindata/registry.rb +18 -18
- data/lib/bindata/rest.rb +1 -1
- data/lib/bindata/sanitize.rb +9 -16
- data/lib/bindata/section.rb +97 -0
- data/lib/bindata/skip.rb +140 -51
- data/lib/bindata/string.rb +9 -9
- data/lib/bindata/stringz.rb +12 -10
- data/lib/bindata/struct.rb +92 -68
- data/lib/bindata/trace.rb +35 -42
- data/lib/bindata/transform/brotli.rb +35 -0
- data/lib/bindata/transform/lz4.rb +35 -0
- data/lib/bindata/transform/lzma.rb +35 -0
- data/lib/bindata/transform/xor.rb +19 -0
- data/lib/bindata/transform/xz.rb +35 -0
- data/lib/bindata/transform/zlib.rb +33 -0
- data/lib/bindata/transform/zstd.rb +35 -0
- data/lib/bindata/uint8_array.rb +2 -2
- data/lib/bindata/version.rb +1 -1
- data/lib/bindata/virtual.rb +4 -7
- data/lib/bindata/warnings.rb +1 -1
- data/lib/bindata.rb +1 -0
- data/test/alignment_test.rb +8 -8
- data/test/array_test.rb +98 -96
- data/test/base_primitive_test.rb +47 -47
- data/test/base_test.rb +24 -24
- data/test/bits_test.rb +15 -15
- data/test/buffer_test.rb +31 -22
- data/test/choice_test.rb +32 -32
- data/test/count_bytes_remaining_test.rb +8 -8
- data/test/delayed_io_test.rb +91 -30
- data/test/float_test.rb +8 -8
- data/test/int_test.rb +14 -14
- data/test/io_test.rb +110 -302
- data/test/lazy_test.rb +38 -38
- data/test/params_test.rb +19 -19
- data/test/primitive_test.rb +26 -26
- data/test/record_test.rb +99 -99
- data/test/registry_test.rb +43 -43
- data/test/rest_test.rb +5 -5
- data/test/section_test.rb +111 -0
- data/test/skip_test.rb +71 -26
- data/test/string_test.rb +60 -60
- data/test/stringz_test.rb +34 -26
- data/test/struct_test.rb +167 -92
- data/test/system_test.rb +159 -41
- data/test/test_helper.rb +24 -13
- data/test/uint8_array_test.rb +6 -6
- data/test/virtual_test.rb +7 -7
- data/test/warnings_test.rb +14 -2
- metadata +19 -22
- data/.gitignore +0 -2
- data/.travis.yml +0 -15
- data/BSDL +0 -22
- data/COPYING +0 -52
- data/INSTALL +0 -12
- data/lib/bindata/offset.rb +0 -94
- data/test/offset_test.rb +0 -100
data/test/registry_test.rb
CHANGED
@@ -14,14 +14,14 @@ describe BinData::Registry do
|
|
14
14
|
r.register('ASubClass', A)
|
15
15
|
r.register('AnotherSubClass', B)
|
16
16
|
|
17
|
-
r.lookup('ASubClass').must_equal A
|
18
|
-
r.lookup('a_sub_class').must_equal A
|
19
|
-
r.lookup('AnotherSubClass').must_equal B
|
20
|
-
r.lookup('another_sub_class').must_equal B
|
17
|
+
_(r.lookup('ASubClass')).must_equal A
|
18
|
+
_(r.lookup('a_sub_class')).must_equal A
|
19
|
+
_(r.lookup('AnotherSubClass')).must_equal B
|
20
|
+
_(r.lookup('another_sub_class')).must_equal B
|
21
21
|
end
|
22
22
|
|
23
23
|
it "does not lookup unregistered names" do
|
24
|
-
|
24
|
+
_ {
|
25
25
|
r.lookup('a_non_existent_sub_class')
|
26
26
|
}.must_raise BinData::UnRegisteredTypeError
|
27
27
|
end
|
@@ -30,34 +30,34 @@ describe BinData::Registry do
|
|
30
30
|
r.register('ASubClass', A)
|
31
31
|
r.unregister('ASubClass')
|
32
32
|
|
33
|
-
|
33
|
+
_ {
|
34
34
|
r.lookup('ASubClass')
|
35
35
|
}.must_raise BinData::UnRegisteredTypeError
|
36
36
|
end
|
37
37
|
|
38
38
|
it "allows overriding of registered classes" do
|
39
|
-
w, $-w = $-w,
|
39
|
+
w, $-w = $-w, nil # disable warning
|
40
40
|
|
41
41
|
begin
|
42
42
|
r.register('A', A)
|
43
43
|
r.register('A', B)
|
44
44
|
|
45
|
-
r.lookup('a').must_equal B
|
45
|
+
_(r.lookup('a')).must_equal B
|
46
46
|
ensure
|
47
47
|
$-w = w
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
it "converts CamelCase to underscores" do
|
52
|
-
r.underscore_name('CamelCase').must_equal 'camel_case'
|
52
|
+
_(r.underscore_name('CamelCase')).must_equal 'camel_case'
|
53
53
|
end
|
54
54
|
|
55
55
|
it "converts adjacent caps camelCase to underscores" do
|
56
|
-
r.underscore_name('XYZCamelCase').must_equal 'xyz_camel_case'
|
56
|
+
_(r.underscore_name('XYZCamelCase')).must_equal 'xyz_camel_case'
|
57
57
|
end
|
58
58
|
|
59
59
|
it "ignores the outer nestings of classes" do
|
60
|
-
r.underscore_name('A::B::C').must_equal 'c'
|
60
|
+
_(r.underscore_name('A::B::C')).must_equal 'c'
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -65,14 +65,14 @@ describe BinData::Registry, "with numerics" do
|
|
65
65
|
let(:r) { BinData::RegisteredClasses }
|
66
66
|
|
67
67
|
it "lookup integers with endian" do
|
68
|
-
r.lookup("int24", {endian: :big}).to_s.must_equal "BinData::Int24be"
|
69
|
-
r.lookup("int24", {endian: :little}).to_s.must_equal "BinData::Int24le"
|
70
|
-
r.lookup("uint24", {endian: :big}).to_s.must_equal "BinData::Uint24be"
|
71
|
-
r.lookup("uint24", {endian: :little}).to_s.must_equal "BinData::Uint24le"
|
68
|
+
_(r.lookup("int24", {endian: :big}).to_s).must_equal "BinData::Int24be"
|
69
|
+
_(r.lookup("int24", {endian: :little}).to_s).must_equal "BinData::Int24le"
|
70
|
+
_(r.lookup("uint24", {endian: :big}).to_s).must_equal "BinData::Uint24be"
|
71
|
+
_(r.lookup("uint24", {endian: :little}).to_s).must_equal "BinData::Uint24le"
|
72
72
|
end
|
73
73
|
|
74
74
|
it "does not lookup integers without endian" do
|
75
|
-
|
75
|
+
_ {
|
76
76
|
r.lookup("int24")
|
77
77
|
}.must_raise BinData::UnRegisteredTypeError
|
78
78
|
end
|
@@ -81,47 +81,47 @@ describe BinData::Registry, "with numerics" do
|
|
81
81
|
begin
|
82
82
|
r.lookup("int24")
|
83
83
|
rescue BinData::UnRegisteredTypeError => e
|
84
|
-
e.message.must_equal "int24, do you need to specify endian?"
|
84
|
+
_(e.message).must_equal "int24, do you need to specify endian?"
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
88
|
it "does not lookup non byte based integers" do
|
89
|
-
|
89
|
+
_ {
|
90
90
|
r.lookup("int3")
|
91
91
|
}.must_raise BinData::UnRegisteredTypeError
|
92
|
-
|
92
|
+
_ {
|
93
93
|
r.lookup("int3", {endian: :big})
|
94
94
|
}.must_raise BinData::UnRegisteredTypeError
|
95
|
-
|
95
|
+
_ {
|
96
96
|
r.lookup("int3", {endian: :little})
|
97
97
|
}.must_raise BinData::UnRegisteredTypeError
|
98
98
|
end
|
99
99
|
|
100
100
|
it "lookup floats with endian" do
|
101
|
-
r.lookup("float", {endian: :big}).to_s.must_equal "BinData::FloatBe"
|
102
|
-
r.lookup("float", {endian: :little}).to_s.must_equal "BinData::FloatLe"
|
103
|
-
r.lookup("double", {endian: :big}).to_s.must_equal "BinData::DoubleBe"
|
104
|
-
r.lookup("double", {endian: :little}).to_s.must_equal "BinData::DoubleLe"
|
101
|
+
_(r.lookup("float", {endian: :big}).to_s).must_equal "BinData::FloatBe"
|
102
|
+
_(r.lookup("float", {endian: :little}).to_s).must_equal "BinData::FloatLe"
|
103
|
+
_(r.lookup("double", {endian: :big}).to_s).must_equal "BinData::DoubleBe"
|
104
|
+
_(r.lookup("double", {endian: :little}).to_s).must_equal "BinData::DoubleLe"
|
105
105
|
end
|
106
106
|
|
107
107
|
it "lookup bits" do
|
108
|
-
r.lookup("bit5").to_s.must_equal "BinData::Bit5"
|
109
|
-
r.lookup("sbit5").to_s.must_equal "BinData::Sbit5"
|
110
|
-
r.lookup("bit6le").to_s.must_equal "BinData::Bit6le"
|
108
|
+
_(r.lookup("bit5").to_s).must_equal "BinData::Bit5"
|
109
|
+
_(r.lookup("sbit5").to_s).must_equal "BinData::Sbit5"
|
110
|
+
_(r.lookup("bit6le").to_s).must_equal "BinData::Bit6le"
|
111
111
|
end
|
112
112
|
|
113
113
|
it "lookup bits by ignoring endian" do
|
114
|
-
r.lookup("bit2", {endian: :big}).to_s.must_equal "BinData::Bit2"
|
115
|
-
r.lookup("bit3le", {endian: :big}).to_s.must_equal "BinData::Bit3le"
|
116
|
-
r.lookup("bit2", {endian: :little}).to_s.must_equal "BinData::Bit2"
|
117
|
-
r.lookup("bit3le", {endian: :little}).to_s.must_equal "BinData::Bit3le"
|
114
|
+
_(r.lookup("bit2", {endian: :big}).to_s).must_equal "BinData::Bit2"
|
115
|
+
_(r.lookup("bit3le", {endian: :big}).to_s).must_equal "BinData::Bit3le"
|
116
|
+
_(r.lookup("bit2", {endian: :little}).to_s).must_equal "BinData::Bit2"
|
117
|
+
_(r.lookup("bit3le", {endian: :little}).to_s).must_equal "BinData::Bit3le"
|
118
118
|
end
|
119
119
|
|
120
120
|
it "lookup signed bits by ignoring endian" do
|
121
|
-
r.lookup("sbit2", {endian: :big}).to_s.must_equal "BinData::Sbit2"
|
122
|
-
r.lookup("sbit3le", {endian: :big}).to_s.must_equal "BinData::Sbit3le"
|
123
|
-
r.lookup("sbit2", {endian: :little}).to_s.must_equal "BinData::Sbit2"
|
124
|
-
r.lookup("sbit3le", {endian: :little}).to_s.must_equal "BinData::Sbit3le"
|
121
|
+
_(r.lookup("sbit2", {endian: :big}).to_s).must_equal "BinData::Sbit2"
|
122
|
+
_(r.lookup("sbit3le", {endian: :big}).to_s).must_equal "BinData::Sbit3le"
|
123
|
+
_(r.lookup("sbit2", {endian: :little}).to_s).must_equal "BinData::Sbit2"
|
124
|
+
_(r.lookup("sbit3le", {endian: :little}).to_s).must_equal "BinData::Sbit3le"
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
@@ -134,15 +134,15 @@ describe BinData::Registry, "with endian specific types" do
|
|
134
134
|
end
|
135
135
|
|
136
136
|
it "lookup little endian types" do
|
137
|
-
r.lookup('a', {endian: :little}).must_equal A
|
137
|
+
_(r.lookup('a', {endian: :little})).must_equal A
|
138
138
|
end
|
139
139
|
|
140
140
|
it "lookup big endian types" do
|
141
|
-
r.lookup('b', {endian: :big}).must_equal B
|
141
|
+
_(r.lookup('b', {endian: :big})).must_equal B
|
142
142
|
end
|
143
143
|
|
144
144
|
it "does not lookup types with non existent endian" do
|
145
|
-
|
145
|
+
_ {
|
146
146
|
r.lookup('a', {endian: :big})
|
147
147
|
}.must_raise BinData::UnRegisteredTypeError
|
148
148
|
end
|
@@ -151,7 +151,7 @@ describe BinData::Registry, "with endian specific types" do
|
|
151
151
|
r.register('c', C)
|
152
152
|
r.register('c_le', D)
|
153
153
|
|
154
|
-
r.lookup('c', {endian: :little}).must_equal C
|
154
|
+
_(r.lookup('c', {endian: :little})).must_equal C
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
@@ -164,18 +164,18 @@ describe BinData::Registry, "with search_prefix" do
|
|
164
164
|
end
|
165
165
|
|
166
166
|
it "lookup single search_prefix" do
|
167
|
-
r.lookup('f', {search_prefix: :a}).must_equal A
|
167
|
+
_(r.lookup('f', {search_prefix: :a})).must_equal A
|
168
168
|
end
|
169
169
|
|
170
170
|
it "lookup single search_prefix with endian" do
|
171
|
-
r.lookup('f', {search_prefix: :a, endian: :little}).must_equal A
|
171
|
+
_(r.lookup('f', {search_prefix: :a, endian: :little})).must_equal A
|
172
172
|
end
|
173
173
|
|
174
174
|
it "lookup multiple search_prefix" do
|
175
|
-
r.lookup('f', {search_prefix: [:x, :a]}).must_equal A
|
175
|
+
_(r.lookup('f', {search_prefix: [:x, :a]})).must_equal A
|
176
176
|
end
|
177
177
|
|
178
178
|
it "lookup first match in search_prefix" do
|
179
|
-
r.lookup('f', {search_prefix: [:a, :b]}).must_equal A
|
179
|
+
_(r.lookup('f', {search_prefix: [:a, :b]})).must_equal A
|
180
180
|
end
|
181
181
|
end
|
data/test/rest_test.rb
CHANGED
@@ -6,23 +6,23 @@ describe BinData::Rest do
|
|
6
6
|
let(:obj) { BinData::Rest.new }
|
7
7
|
|
8
8
|
it "initial state" do
|
9
|
-
obj.must_equal ""
|
9
|
+
_(obj).must_equal ""
|
10
10
|
end
|
11
11
|
|
12
12
|
it "reads till end of stream" do
|
13
13
|
data = "abcdefghij"
|
14
|
-
obj.read(data).must_equal data
|
14
|
+
_(obj.read(data)).must_equal data
|
15
15
|
end
|
16
16
|
|
17
17
|
it "allows setting value for completeness" do
|
18
18
|
obj.assign("123")
|
19
|
-
obj.must_equal "123"
|
20
|
-
obj.to_binary_s.must_equal_binary "123"
|
19
|
+
_(obj).must_equal "123"
|
20
|
+
_(obj.to_binary_s).must_equal_binary "123"
|
21
21
|
end
|
22
22
|
|
23
23
|
it "accepts BinData::BasePrimitive parameters" do
|
24
24
|
rest = BinData::Rest.new(assert: "abc")
|
25
|
-
|
25
|
+
_ {
|
26
26
|
rest.read("xyz")
|
27
27
|
}.must_raise BinData::ValidityError
|
28
28
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
4
|
+
|
5
|
+
describe BinData::Section do
|
6
|
+
it "transforms data byte at a time" do
|
7
|
+
require 'bindata/transform/xor'
|
8
|
+
|
9
|
+
obj = BinData::Section.new(transform: -> { BinData::Transform::Xor.new(0xff) },
|
10
|
+
type: [:string, read_length: 5])
|
11
|
+
|
12
|
+
_(obj.read("\x97\x9A\x93\x93\x90")).must_equal "hello"
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
require 'brotli'
|
17
|
+
it "transform brotli" do
|
18
|
+
require 'bindata/transform/brotli'
|
19
|
+
|
20
|
+
class BrotliRecord < BinData::Record
|
21
|
+
int32le :len, value: -> { s.num_bytes }
|
22
|
+
section :s, transform: -> { BinData::Transform::Brotli.new(len) } do
|
23
|
+
int32le :str_len, value: -> { str.length }
|
24
|
+
string :str, read_length: :str_len
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
obj = BrotliRecord.new
|
30
|
+
data = "highly compressible" * 100
|
31
|
+
obj.s.str = data
|
32
|
+
_(obj.len).must_be :<, (data.length / 10)
|
33
|
+
|
34
|
+
str = obj.to_binary_s
|
35
|
+
obj = BrotliRecord.read(str)
|
36
|
+
_(obj.s.str).must_equal data
|
37
|
+
end
|
38
|
+
rescue LoadError; end
|
39
|
+
|
40
|
+
begin
|
41
|
+
require 'extlz4'
|
42
|
+
it "transform lz4" do
|
43
|
+
require 'bindata/transform/lz4'
|
44
|
+
|
45
|
+
class LZ4Record < BinData::Record
|
46
|
+
int32le :len, value: -> { s.num_bytes }
|
47
|
+
section :s, transform: -> { BinData::Transform::LZ4.new(len) } do
|
48
|
+
int32le :str_len, value: -> { str.length }
|
49
|
+
string :str, read_length: :str_len
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
obj = LZ4Record.new
|
55
|
+
data = "highly compressible" * 100
|
56
|
+
obj.s.str = data
|
57
|
+
_(obj.len).must_be :<, (data.length / 10)
|
58
|
+
|
59
|
+
str = obj.to_binary_s
|
60
|
+
obj = LZ4Record.read(str)
|
61
|
+
_(obj.s.str).must_equal data
|
62
|
+
end
|
63
|
+
rescue LoadError; end
|
64
|
+
|
65
|
+
it "transform zlib" do
|
66
|
+
require 'bindata/transform/zlib'
|
67
|
+
|
68
|
+
class ZlibRecord < BinData::Record
|
69
|
+
int32le :len, value: -> { s.num_bytes }
|
70
|
+
section :s, transform: -> { BinData::Transform::Zlib.new(len) } do
|
71
|
+
int32le :str_len, value: -> { str.length }
|
72
|
+
string :str, read_length: :str_len
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
obj = ZlibRecord.new
|
78
|
+
data = "highly compressible" * 100
|
79
|
+
obj.s.str = data
|
80
|
+
_(obj.len).must_be :<, (data.length / 10)
|
81
|
+
|
82
|
+
str = obj.to_binary_s
|
83
|
+
obj = ZlibRecord.read(str)
|
84
|
+
_(obj.s.str).must_equal data
|
85
|
+
end
|
86
|
+
|
87
|
+
begin
|
88
|
+
require 'zstd-ruby'
|
89
|
+
it "transform zstd" do
|
90
|
+
require 'bindata/transform/zstd'
|
91
|
+
|
92
|
+
class ZstdRecord < BinData::Record
|
93
|
+
int32le :len, value: -> { s.num_bytes }
|
94
|
+
section :s, transform: -> { BinData::Transform::Zstd.new(len) } do
|
95
|
+
int32le :str_len, value: -> { str.length }
|
96
|
+
string :str, read_length: :str_len
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
obj = ZstdRecord.new
|
102
|
+
data = "highly compressible" * 100
|
103
|
+
obj.s.str = data
|
104
|
+
_(obj.len).must_be :<, (data.length / 10)
|
105
|
+
|
106
|
+
str = obj.to_binary_s
|
107
|
+
obj = ZstdRecord.read(str)
|
108
|
+
_(obj.s.str).must_equal data
|
109
|
+
end
|
110
|
+
rescue LoadError; end
|
111
|
+
end
|
data/test/skip_test.rb
CHANGED
@@ -6,7 +6,7 @@ describe BinData::Skip, "when instantiating" do
|
|
6
6
|
describe "with no mandatory parameters supplied" do
|
7
7
|
it "raises an error" do
|
8
8
|
args = {}
|
9
|
-
|
9
|
+
_ { BinData::Skip.new(args) }.must_raise ArgumentError
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -16,23 +16,23 @@ describe BinData::Skip, "with :length" do
|
|
16
16
|
let(:io) { StringIO.new("abcdefghij") }
|
17
17
|
|
18
18
|
it "initial state" do
|
19
|
-
obj.must_equal ""
|
20
|
-
obj.to_binary_s.must_equal_binary "\000" * 5
|
19
|
+
_(obj).must_equal ""
|
20
|
+
_(obj.to_binary_s).must_equal_binary "\000" * 5
|
21
21
|
end
|
22
22
|
|
23
23
|
it "skips bytes" do
|
24
24
|
obj.read(io)
|
25
|
-
io.pos.must_equal 5
|
25
|
+
_(io.pos).must_equal 5
|
26
26
|
end
|
27
27
|
|
28
28
|
it "has expected binary representation after setting value" do
|
29
29
|
obj.assign("123")
|
30
|
-
obj.to_binary_s.must_equal_binary "\000" * 5
|
30
|
+
_(obj.to_binary_s).must_equal_binary "\000" * 5
|
31
31
|
end
|
32
32
|
|
33
33
|
it "has expected binary representation after reading" do
|
34
34
|
obj.read(io)
|
35
|
-
obj.to_binary_s.must_equal_binary "\000" * 5
|
35
|
+
_(obj.to_binary_s).must_equal_binary "\000" * 5
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -46,55 +46,75 @@ describe BinData::Skip, "with :to_abs_offset" do
|
|
46
46
|
fields = [ skip_obj ]
|
47
47
|
obj = BinData::Struct.new(fields: fields)
|
48
48
|
obj.read(io)
|
49
|
-
io.pos.must_equal 5
|
49
|
+
_(io.pos).must_equal 5
|
50
50
|
end
|
51
51
|
|
52
52
|
it "reads skipping in place" do
|
53
53
|
fields = [ [:string, :a, { read_length: 5 }], skip_obj ]
|
54
54
|
obj = BinData::Struct.new(fields: fields)
|
55
55
|
obj.read(io)
|
56
|
-
io.pos.must_equal 5
|
56
|
+
_(io.pos).must_equal 5
|
57
57
|
end
|
58
58
|
|
59
59
|
it "does not read skipping backwards" do
|
60
60
|
fields = [ [:string, :a, { read_length: 10 }], skip_obj ]
|
61
61
|
obj = BinData::Struct.new(fields: fields)
|
62
62
|
|
63
|
-
|
63
|
+
_ {
|
64
64
|
obj.read(io)
|
65
|
-
}.must_raise
|
65
|
+
}.must_raise ArgumentError
|
66
66
|
end
|
67
67
|
|
68
68
|
it "writes skipping forward" do
|
69
69
|
fields = [ skip_obj ]
|
70
70
|
obj = BinData::Struct.new(fields: fields)
|
71
|
-
obj.to_binary_s.must_equal "\000\000\000\000\000"
|
71
|
+
_(obj.to_binary_s).must_equal "\000\000\000\000\000"
|
72
72
|
end
|
73
73
|
|
74
74
|
it "reads skipping in place" do
|
75
75
|
fields = [ [:string, :a, { value: "abcde" }], skip_obj ]
|
76
76
|
obj = BinData::Struct.new(fields: fields)
|
77
|
-
obj.to_binary_s.must_equal "abcde"
|
77
|
+
_(obj.to_binary_s).must_equal "abcde"
|
78
78
|
end
|
79
79
|
|
80
80
|
it "does not write skipping backwards" do
|
81
81
|
fields = [ [:string, :a, { value: "abcdefghij" }], skip_obj ]
|
82
82
|
obj = BinData::Struct.new(fields: fields)
|
83
|
-
|
83
|
+
_ {
|
84
84
|
obj.to_binary_s
|
85
|
-
}.must_raise
|
85
|
+
}.must_raise ArgumentError
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
89
|
describe BinData::Skip, "with :until_valid" do
|
90
90
|
let(:io) { StringIO.new("abcdefghij") }
|
91
91
|
|
92
|
+
it "doesn't skip when writing" do
|
93
|
+
skip_obj = [:string, { read_length: 1, assert: "f" }]
|
94
|
+
args = { until_valid: skip_obj }
|
95
|
+
obj = BinData::Skip.new(args)
|
96
|
+
_(obj.to_binary_s).must_equal ""
|
97
|
+
end
|
98
|
+
|
92
99
|
it "skips to valid match" do
|
93
100
|
skip_obj = [:string, { read_length: 1, assert: "f" }]
|
94
101
|
fields = [ [:skip, :s, { until_valid: skip_obj }] ]
|
95
102
|
obj = BinData::Struct.new(fields: fields)
|
96
103
|
obj.read(io)
|
97
|
-
io.pos.must_equal 5
|
104
|
+
_(io.pos).must_equal 5
|
105
|
+
end
|
106
|
+
|
107
|
+
it "won't skip on unseekable stream" do
|
108
|
+
rd, wr = IO::pipe
|
109
|
+
unseekable_io = BinData::IO::Read.new(rd)
|
110
|
+
wr.write io
|
111
|
+
wr.close
|
112
|
+
|
113
|
+
skip_obj = [:string, { read_length: 1, assert: "f" }]
|
114
|
+
fields = [ [:skip, :s, { until_valid: skip_obj }] ]
|
115
|
+
obj = BinData::Struct.new(fields: fields)
|
116
|
+
_ {obj.read(unseekable_io)}.must_raise IOError
|
117
|
+
rd.close
|
98
118
|
end
|
99
119
|
|
100
120
|
it "doesn't skip when validator doesn't assert" do
|
@@ -102,36 +122,61 @@ describe BinData::Skip, "with :until_valid" do
|
|
102
122
|
fields = [ [:skip, :s, { until_valid: skip_obj }] ]
|
103
123
|
obj = BinData::Struct.new(fields: fields)
|
104
124
|
obj.read(io)
|
105
|
-
io.pos.must_equal 0
|
125
|
+
_(io.pos).must_equal 0
|
106
126
|
end
|
107
127
|
|
108
|
-
it "raises
|
128
|
+
it "raises IOError when no match" do
|
109
129
|
skip_obj = [:string, { read_length: 1, assert: "X" }]
|
110
130
|
fields = [ [:skip, :s, { until_valid: skip_obj }] ]
|
111
131
|
obj = BinData::Struct.new(fields: fields)
|
112
|
-
|
132
|
+
_ {
|
113
133
|
obj.read(io)
|
114
|
-
}.must_raise
|
134
|
+
}.must_raise IOError
|
115
135
|
end
|
116
136
|
|
117
137
|
it "raises IOError when validator reads beyond stream" do
|
118
138
|
skip_obj = [:string, { read_length: 30 }]
|
119
139
|
fields = [ [:skip, :s, { until_valid: skip_obj }] ]
|
120
140
|
obj = BinData::Struct.new(fields: fields)
|
121
|
-
|
141
|
+
_ {
|
122
142
|
obj.read(io)
|
123
143
|
}.must_raise IOError
|
124
144
|
end
|
125
145
|
|
126
|
-
|
146
|
+
it "uses block form" do
|
147
|
+
class DSLSkip < BinData::Record
|
148
|
+
skip :s do
|
149
|
+
string read_length: 1, assert: "f"
|
150
|
+
end
|
151
|
+
string :a, read_length: 1
|
152
|
+
end
|
153
|
+
|
154
|
+
obj = DSLSkip.read(io)
|
155
|
+
_(obj.a).must_equal "f"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe BinData::Skip, "with :until_valid" do
|
160
|
+
class SkipSearch < BinData::Record
|
127
161
|
skip :s do
|
128
|
-
|
162
|
+
uint8
|
163
|
+
uint8 asserted_value: 1
|
164
|
+
uint8 :a
|
165
|
+
uint8 :b
|
166
|
+
virtual assert: -> { a == b }
|
129
167
|
end
|
130
|
-
|
168
|
+
array :data, type: :uint8, initial_length: 4
|
131
169
|
end
|
132
170
|
|
133
|
-
|
134
|
-
|
135
|
-
|
171
|
+
let(:io) { BinData::IO.create_string_io("\x0f" * 10 + "\x00\x01\x02\x03\x00" + "\x02\x01\x03\x03" + "\x06") }
|
172
|
+
|
173
|
+
it "finds valid match" do
|
174
|
+
obj = SkipSearch.read(io)
|
175
|
+
_(obj.data).must_equal [2, 1, 3, 3]
|
176
|
+
end
|
177
|
+
|
178
|
+
it "match is at expected offset" do
|
179
|
+
obj = SkipSearch.read(io)
|
180
|
+
_(obj.data.rel_offset).must_equal 15
|
136
181
|
end
|
137
182
|
end
|