bindata 2.4.15 → 2.5.1
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 +16 -0
- data/README.md +7 -10
- data/bindata.gemspec +5 -4
- 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 +5 -5
- 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 +10 -10
- data/lib/bindata/dsl.rb +34 -32
- data/lib/bindata/float.rb +3 -3
- data/lib/bindata/framework.rb +8 -10
- data/lib/bindata/int.rb +9 -9
- 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 +46 -51
- 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 +83 -66
- 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 +3 -2
- data/test/array_test.rb +10 -8
- data/test/buffer_test.rb +9 -0
- data/test/choice_test.rb +1 -1
- data/test/delayed_io_test.rb +16 -0
- data/test/io_test.rb +54 -246
- data/test/registry_test.rb +1 -1
- data/test/section_test.rb +111 -0
- data/test/skip_test.rb +55 -10
- data/test/string_test.rb +4 -4
- data/test/stringz_test.rb +8 -0
- data/test/struct_test.rb +87 -12
- data/test/system_test.rb +119 -1
- data/test/test_helper.rb +30 -15
- data/test/warnings_test.rb +12 -0
- metadata +20 -18
- data/lib/bindata/offset.rb +0 -94
- data/test/offset_test.rb +0 -100
data/lib/bindata.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# BinData -- Binary data manipulator.
|
2
|
-
# Copyright (c) 2007 -
|
2
|
+
# Copyright (c) 2007 - 2025 Dion Mendel.
|
3
3
|
|
4
4
|
require 'bindata/version'
|
5
5
|
require 'bindata/array'
|
@@ -13,6 +13,7 @@ require 'bindata/int'
|
|
13
13
|
require 'bindata/primitive'
|
14
14
|
require 'bindata/record'
|
15
15
|
require 'bindata/rest'
|
16
|
+
require 'bindata/section'
|
16
17
|
require 'bindata/skip'
|
17
18
|
require 'bindata/string'
|
18
19
|
require 'bindata/stringz'
|
@@ -34,4 +35,4 @@ require 'bindata/warnings'
|
|
34
35
|
#
|
35
36
|
# BinData is released under the same license as Ruby.
|
36
37
|
#
|
37
|
-
# Copyright (c) 2007 -
|
38
|
+
# Copyright (c) 2007 - 2025 Dion Mendel.
|
data/test/array_test.rb
CHANGED
@@ -18,17 +18,15 @@ describe BinData::Array, "when instantiating" do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "warns about :length" do
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
21
|
+
_ {
|
22
|
+
BinData::Array.new(type: :uint8, length: 3)
|
23
|
+
}.must_warn ":length is not used with BinData::Array. You probably want to change this to :initial_length"
|
25
24
|
end
|
26
25
|
|
27
26
|
it "warns about :read_length" do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
27
|
+
_ {
|
28
|
+
BinData::Array.new(type: :uint8, read_length: 3)
|
29
|
+
}.must_warn ":read_length is not used with BinData::Array. You probably want to change this to :initial_length"
|
32
30
|
end
|
33
31
|
|
34
32
|
it "fails if a given type is unknown" do
|
@@ -71,6 +69,10 @@ describe BinData::Array, "with no elements" do
|
|
71
69
|
it "returns [] for the last n elements" do
|
72
70
|
_(obj.last(3)).must_equal []
|
73
71
|
end
|
72
|
+
|
73
|
+
it "won't assign nil" do
|
74
|
+
_ { obj.assign(nil) }.must_raise ArgumentError
|
75
|
+
end
|
74
76
|
end
|
75
77
|
|
76
78
|
describe BinData::Array, "with several elements" do
|
data/test/buffer_test.rb
CHANGED
@@ -144,6 +144,15 @@ describe BinData::Buffer, "nested buffers" do
|
|
144
144
|
_(obj.b).must_equal "klmno"
|
145
145
|
end
|
146
146
|
|
147
|
+
it "pads undersize writes" do
|
148
|
+
obj = NestedBufferRecord.new
|
149
|
+
obj.a.aa = "abc"
|
150
|
+
obj.a.bb = "ABC"
|
151
|
+
obj.b = "123"
|
152
|
+
|
153
|
+
_(obj.to_binary_s).must_equal_binary "abc\000\000ABC\000\000123"
|
154
|
+
end
|
155
|
+
|
147
156
|
it "restricts oversize writes" do
|
148
157
|
obj = NestedBufferRecord.new
|
149
158
|
obj.a.aa = "abcdefghij"
|
data/test/choice_test.rb
CHANGED
@@ -243,7 +243,7 @@ describe BinData::Choice, "subclassed with default parameters" do
|
|
243
243
|
_(obj.num_bytes).must_equal 2
|
244
244
|
end
|
245
245
|
|
246
|
-
it "
|
246
|
+
it "overrides default parameter" do
|
247
247
|
obj = DerivedChoice.new(selection: 'b')
|
248
248
|
_(obj.num_bytes).must_equal 4
|
249
249
|
end
|
data/test/delayed_io_test.rb
CHANGED
@@ -266,3 +266,19 @@ describe BinData::DelayedIO, "with auto_call" do
|
|
266
266
|
_(obj.num_bytes).must_equal 2
|
267
267
|
end
|
268
268
|
end
|
269
|
+
|
270
|
+
describe BinData::DelayedIO, "with multiple auto_call" do
|
271
|
+
class MultipleAutoCallDelayedIORecord < BinData::Record
|
272
|
+
auto_call_delayed_io
|
273
|
+
auto_call_delayed_io
|
274
|
+
uint8 :a
|
275
|
+
delayed_io :b, read_abs_offset: 1 do
|
276
|
+
uint8
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
it "class reads" do
|
281
|
+
obj = MultipleAutoCallDelayedIORecord.read "\x01\x02"
|
282
|
+
_(obj.snapshot).must_equal({a: 1, b: 2})
|
283
|
+
end
|
284
|
+
end
|
data/test/io_test.rb
CHANGED
@@ -15,16 +15,24 @@ describe BinData::IO::Read, "reading from non seekable stream" do
|
|
15
15
|
@rd.close
|
16
16
|
end
|
17
17
|
|
18
|
-
it "
|
19
|
-
@io.
|
20
|
-
_(@io.
|
18
|
+
it "seeks correctly" do
|
19
|
+
@io.skipbytes(1999)
|
20
|
+
_(@io.readbytes(5)).must_equal "abbbb"
|
21
21
|
end
|
22
22
|
|
23
|
-
it "seeks
|
24
|
-
@io.
|
23
|
+
it "seeks to abs_offset" do
|
24
|
+
@io.skipbytes(1000)
|
25
|
+
@io.seek_to_abs_offset(1999)
|
25
26
|
_(@io.readbytes(5)).must_equal "abbbb"
|
26
27
|
end
|
27
28
|
|
29
|
+
it "wont seek backwards" do
|
30
|
+
@io.skipbytes(5)
|
31
|
+
_ {
|
32
|
+
@io.skipbytes(-1)
|
33
|
+
}.must_raise IOError
|
34
|
+
end
|
35
|
+
|
28
36
|
it "#num_bytes_remaining raises IOError" do
|
29
37
|
_ {
|
30
38
|
@io.num_bytes_remaining
|
@@ -32,6 +40,35 @@ describe BinData::IO::Read, "reading from non seekable stream" do
|
|
32
40
|
end
|
33
41
|
end
|
34
42
|
|
43
|
+
describe BinData::IO::Write, "writing to non seekable stream" do
|
44
|
+
before do
|
45
|
+
@rd, @wr = IO::pipe
|
46
|
+
@io = BinData::IO::Write.new(@wr)
|
47
|
+
end
|
48
|
+
|
49
|
+
after do
|
50
|
+
@rd.close
|
51
|
+
@wr.close
|
52
|
+
end
|
53
|
+
|
54
|
+
def written_data
|
55
|
+
@io.flush
|
56
|
+
@wr.close
|
57
|
+
@rd.read
|
58
|
+
end
|
59
|
+
|
60
|
+
it "writes correctly" do
|
61
|
+
@io.writebytes("hello")
|
62
|
+
_(written_data).must_equal "hello"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "must not attempt to seek" do
|
66
|
+
_ {
|
67
|
+
@io.seek_to_abs_offset(5)
|
68
|
+
}.must_raise IOError
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
35
72
|
describe BinData::IO::Read, "when reading" do
|
36
73
|
let(:stream) { StringIO.new "abcdefghij" }
|
37
74
|
let(:io) { BinData::IO::Read.new(stream) }
|
@@ -42,19 +79,19 @@ describe BinData::IO::Read, "when reading" do
|
|
42
79
|
}.must_raise ArgumentError
|
43
80
|
end
|
44
81
|
|
45
|
-
it "returns correct offset" do
|
46
|
-
stream.seek(3, IO::SEEK_CUR)
|
47
|
-
|
48
|
-
_(io.offset).must_equal 0
|
49
|
-
_(io.readbytes(4)).must_equal "defg"
|
50
|
-
_(io.offset).must_equal 4
|
51
|
-
end
|
52
|
-
|
53
82
|
it "seeks correctly" do
|
54
|
-
io.
|
83
|
+
io.skipbytes(2)
|
55
84
|
_(io.readbytes(4)).must_equal "cdef"
|
56
85
|
end
|
57
86
|
|
87
|
+
it "wont seek backwards" do
|
88
|
+
io.skipbytes(5)
|
89
|
+
_ {
|
90
|
+
io.skipbytes(-1)
|
91
|
+
}.must_raise IOError
|
92
|
+
end
|
93
|
+
|
94
|
+
|
58
95
|
it "reads all bytes" do
|
59
96
|
_(io.read_all_bytes).must_equal "abcdefghij"
|
60
97
|
end
|
@@ -67,7 +104,7 @@ describe BinData::IO::Read, "when reading" do
|
|
67
104
|
end
|
68
105
|
|
69
106
|
it "raises error when reading at eof" do
|
70
|
-
io.
|
107
|
+
io.skipbytes(10)
|
71
108
|
_ {
|
72
109
|
io.readbytes(3)
|
73
110
|
}.must_raise EOFError
|
@@ -80,149 +117,6 @@ describe BinData::IO::Read, "when reading" do
|
|
80
117
|
end
|
81
118
|
end
|
82
119
|
|
83
|
-
describe BinData::IO::Read, "#with_buffer" do
|
84
|
-
let(:stream) { StringIO.new "abcdefghijklmnopqrst" }
|
85
|
-
let(:io) { BinData::IO::Read.new(stream) }
|
86
|
-
|
87
|
-
it "consumes entire buffer on short reads" do
|
88
|
-
io.with_buffer(10) do
|
89
|
-
_(io.readbytes(4)).must_equal "abcd"
|
90
|
-
end
|
91
|
-
_(io.offset).must_equal(10)
|
92
|
-
end
|
93
|
-
|
94
|
-
it "consumes entire buffer on read_all_bytes" do
|
95
|
-
io.with_buffer(10) do
|
96
|
-
_(io.read_all_bytes).must_equal "abcdefghij"
|
97
|
-
end
|
98
|
-
_(io.offset).must_equal(10)
|
99
|
-
end
|
100
|
-
|
101
|
-
it "restricts large reads" do
|
102
|
-
io.with_buffer(10) do
|
103
|
-
_ {
|
104
|
-
io.readbytes(15)
|
105
|
-
}.must_raise IOError
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
it "is nestable" do
|
110
|
-
io.with_buffer(10) do
|
111
|
-
_(io.readbytes(2)).must_equal "ab"
|
112
|
-
io.with_buffer(5) do
|
113
|
-
_(io.read_all_bytes).must_equal "cdefg"
|
114
|
-
end
|
115
|
-
_(io.offset).must_equal(2 + 5)
|
116
|
-
end
|
117
|
-
_(io.offset).must_equal(10)
|
118
|
-
end
|
119
|
-
|
120
|
-
it "restricts large nested buffers" do
|
121
|
-
io.with_buffer(10) do
|
122
|
-
_(io.readbytes(2)).must_equal "ab"
|
123
|
-
io.with_buffer(20) do
|
124
|
-
_(io.read_all_bytes).must_equal "cdefghij"
|
125
|
-
_(io.offset).must_equal(10)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
_(io.offset).must_equal(10)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "restricts large seeks" do
|
132
|
-
io.with_buffer(10) do
|
133
|
-
io.seekbytes(15)
|
134
|
-
end
|
135
|
-
_(io.offset).must_equal(10)
|
136
|
-
end
|
137
|
-
|
138
|
-
it "restricts large -ve seeks" do
|
139
|
-
io.readbytes(2)
|
140
|
-
io.with_buffer(10) do
|
141
|
-
io.seekbytes(-1)
|
142
|
-
_(io.offset).must_equal(2)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
it "greater than stream size consumes all bytes" do
|
147
|
-
io.with_buffer(30) do
|
148
|
-
_(io.readbytes(4)).must_equal "abcd"
|
149
|
-
end
|
150
|
-
_(io.offset).must_equal(20)
|
151
|
-
end
|
152
|
-
|
153
|
-
it "restricts #num_bytes_remaining" do
|
154
|
-
io.with_buffer(10) do
|
155
|
-
io.readbytes(2)
|
156
|
-
_(io.num_bytes_remaining).must_equal 8
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
it "greater than stream size doesn't restrict #num_bytes_remaining" do
|
161
|
-
io.with_buffer(30) do
|
162
|
-
io.readbytes(2)
|
163
|
-
_(io.num_bytes_remaining).must_equal 18
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
module IOReadWithReadahead
|
169
|
-
def test_rolls_back_short_reads
|
170
|
-
_(io.readbytes(2)).must_equal "ab"
|
171
|
-
io.with_readahead do
|
172
|
-
_(io.readbytes(4)).must_equal "cdef"
|
173
|
-
end
|
174
|
-
_(io.offset).must_equal 2
|
175
|
-
end
|
176
|
-
|
177
|
-
def test_rolls_back_read_all_bytes
|
178
|
-
_(io.readbytes(3)).must_equal "abc"
|
179
|
-
io.with_readahead do
|
180
|
-
_(io.read_all_bytes).must_equal "defghijklmnopqrst"
|
181
|
-
end
|
182
|
-
_(io.offset).must_equal 3
|
183
|
-
end
|
184
|
-
|
185
|
-
def test_inside_buffer_rolls_back_reads
|
186
|
-
io.with_buffer(10) do
|
187
|
-
io.with_readahead do
|
188
|
-
_(io.readbytes(4)).must_equal "abcd"
|
189
|
-
end
|
190
|
-
_(io.offset).must_equal 0
|
191
|
-
end
|
192
|
-
_(io.offset).must_equal 10
|
193
|
-
end
|
194
|
-
|
195
|
-
def test_outside_buffer_rolls_back_reads
|
196
|
-
io.with_readahead do
|
197
|
-
io.with_buffer(10) do
|
198
|
-
_(io.readbytes(4)).must_equal "abcd"
|
199
|
-
end
|
200
|
-
_(io.offset).must_equal 10
|
201
|
-
end
|
202
|
-
_(io.offset).must_equal 0
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
describe BinData::IO::Read, "#with_readahead" do
|
207
|
-
let(:stream) { StringIO.new "abcdefghijklmnopqrst" }
|
208
|
-
let(:io) { BinData::IO::Read.new(stream) }
|
209
|
-
|
210
|
-
include IOReadWithReadahead
|
211
|
-
end
|
212
|
-
|
213
|
-
describe BinData::IO::Read, "unseekable stream #with_readahead" do
|
214
|
-
let(:stream) {
|
215
|
-
io = StringIO.new "abcdefghijklmnopqrst"
|
216
|
-
def io.pos
|
217
|
-
raise Errno::EPIPE
|
218
|
-
end
|
219
|
-
io
|
220
|
-
}
|
221
|
-
let(:io) { BinData::IO::Read.new(stream) }
|
222
|
-
|
223
|
-
include IOReadWithReadahead
|
224
|
-
end
|
225
|
-
|
226
120
|
describe BinData::IO::Write, "writing to non seekable stream" do
|
227
121
|
before do
|
228
122
|
@rd, @wr = IO::pipe
|
@@ -238,30 +132,6 @@ describe BinData::IO::Write, "writing to non seekable stream" do
|
|
238
132
|
@io.writebytes("1234567890")
|
239
133
|
_(@rd.read(10)).must_equal "1234567890"
|
240
134
|
end
|
241
|
-
|
242
|
-
it "has correct offset" do
|
243
|
-
@io.writebytes("1234567890")
|
244
|
-
_(@io.offset).must_equal 10
|
245
|
-
end
|
246
|
-
|
247
|
-
it "does not seek backwards" do
|
248
|
-
@io.writebytes("1234567890")
|
249
|
-
_ {
|
250
|
-
@io.seekbytes(-5)
|
251
|
-
}.must_raise IOError
|
252
|
-
end
|
253
|
-
|
254
|
-
it "does not seek forwards" do
|
255
|
-
_ {
|
256
|
-
@io.seekbytes(5)
|
257
|
-
}.must_raise IOError
|
258
|
-
end
|
259
|
-
|
260
|
-
it "#num_bytes_remaining raises IOError" do
|
261
|
-
_ {
|
262
|
-
@io.num_bytes_remaining
|
263
|
-
}.must_raise IOError
|
264
|
-
end
|
265
135
|
end
|
266
136
|
|
267
137
|
describe BinData::IO::Write, "when writing" do
|
@@ -280,21 +150,6 @@ describe BinData::IO::Write, "when writing" do
|
|
280
150
|
_(stream.value).must_equal "abcd"
|
281
151
|
end
|
282
152
|
|
283
|
-
it "has #offset" do
|
284
|
-
_(io.offset).must_equal 0
|
285
|
-
|
286
|
-
io.writebytes("abcd")
|
287
|
-
_(io.offset).must_equal 4
|
288
|
-
|
289
|
-
io.writebytes("ABCD")
|
290
|
-
_(io.offset).must_equal 8
|
291
|
-
end
|
292
|
-
|
293
|
-
it "rounds up #offset when writing bits" do
|
294
|
-
io.writebits(123, 9, :little)
|
295
|
-
_(io.offset).must_equal 2
|
296
|
-
end
|
297
|
-
|
298
153
|
it "flushes" do
|
299
154
|
io.writebytes("abcd")
|
300
155
|
io.flush
|
@@ -303,53 +158,6 @@ describe BinData::IO::Write, "when writing" do
|
|
303
158
|
end
|
304
159
|
end
|
305
160
|
|
306
|
-
describe BinData::IO::Write, "#with_buffer" do
|
307
|
-
let(:stream) { StringIO.new }
|
308
|
-
let(:io) { BinData::IO::Write.new(stream) }
|
309
|
-
|
310
|
-
it "pads entire buffer on short reads" do
|
311
|
-
io.with_buffer(10) do
|
312
|
-
io.writebytes "abcde"
|
313
|
-
end
|
314
|
-
|
315
|
-
_(stream.value).must_equal "abcde\0\0\0\0\0"
|
316
|
-
end
|
317
|
-
|
318
|
-
it "discards excess on large writes" do
|
319
|
-
io.with_buffer(5) do
|
320
|
-
io.writebytes "abcdefghij"
|
321
|
-
end
|
322
|
-
|
323
|
-
_(stream.value).must_equal "abcde"
|
324
|
-
end
|
325
|
-
|
326
|
-
it "is nestable" do
|
327
|
-
io.with_buffer(10) do
|
328
|
-
io.with_buffer(5) do
|
329
|
-
io.writebytes "abc"
|
330
|
-
end
|
331
|
-
io.writebytes "de"
|
332
|
-
end
|
333
|
-
|
334
|
-
_(stream.value).must_equal "abc\0\0de\0\0\0"
|
335
|
-
end
|
336
|
-
|
337
|
-
it "restricts large seeks" do
|
338
|
-
io.with_buffer(10) do
|
339
|
-
io.seekbytes(15)
|
340
|
-
end
|
341
|
-
_(io.offset).must_equal(10)
|
342
|
-
end
|
343
|
-
|
344
|
-
it "restricts large -ve seeks" do
|
345
|
-
io.writebytes("12")
|
346
|
-
io.with_buffer(10) do
|
347
|
-
io.seekbytes(-1)
|
348
|
-
_(io.offset).must_equal(2)
|
349
|
-
end
|
350
|
-
end
|
351
|
-
end
|
352
|
-
|
353
161
|
describe BinData::IO::Read, "reading bits in big endian" do
|
354
162
|
let(:b1) { 0b1111_1010 }
|
355
163
|
let(:b2) { 0b1100_1110 }
|
@@ -554,7 +362,7 @@ describe BinData::IO::Write, "writing bits in little endian" do
|
|
554
362
|
end
|
555
363
|
|
556
364
|
describe BinData::IO::Read, "with changing endian" do
|
557
|
-
it "does not mix different
|
365
|
+
it "does not mix different endianness when reading" do
|
558
366
|
b1 = 0b0110_1010
|
559
367
|
b2 = 0b1110_0010
|
560
368
|
str = [b1, b2].pack("CC")
|
@@ -566,7 +374,7 @@ describe BinData::IO::Read, "with changing endian" do
|
|
566
374
|
end
|
567
375
|
|
568
376
|
describe BinData::IO::Write, "with changing endian" do
|
569
|
-
it "does not mix different
|
377
|
+
it "does not mix different endianness when writing" do
|
570
378
|
io = BitWriterHelper.new
|
571
379
|
io.writebits(0b110, 3, :big)
|
572
380
|
io.writebits(0b010, 3, :little)
|
data/test/registry_test.rb
CHANGED
@@ -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
@@ -62,7 +62,7 @@ describe BinData::Skip, "with :to_abs_offset" do
|
|
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
|
@@ -82,13 +82,20 @@ describe BinData::Skip, "with :to_abs_offset" do
|
|
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 }] ]
|
@@ -97,6 +104,19 @@ describe BinData::Skip, "with :until_valid" do
|
|
97
104
|
_(io.pos).must_equal 5
|
98
105
|
end
|
99
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
|
118
|
+
end
|
119
|
+
|
100
120
|
it "doesn't skip when validator doesn't assert" do
|
101
121
|
skip_obj = [:string, { read_length: 1 }]
|
102
122
|
fields = [ [:skip, :s, { until_valid: skip_obj }] ]
|
@@ -105,13 +125,13 @@ describe BinData::Skip, "with :until_valid" do
|
|
105
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
|
@@ -123,15 +143,40 @@ describe BinData::Skip, "with :until_valid" do
|
|
123
143
|
}.must_raise IOError
|
124
144
|
end
|
125
145
|
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
129
152
|
end
|
130
|
-
string :a, read_length: 1
|
131
|
-
end
|
132
153
|
|
133
|
-
it "uses block form" do
|
134
154
|
obj = DSLSkip.read(io)
|
135
155
|
_(obj.a).must_equal "f"
|
136
156
|
end
|
137
157
|
end
|
158
|
+
|
159
|
+
describe BinData::Skip, "with :until_valid" do
|
160
|
+
class SkipSearch < BinData::Record
|
161
|
+
skip :s do
|
162
|
+
uint8
|
163
|
+
uint8 asserted_value: 1
|
164
|
+
uint8 :a
|
165
|
+
uint8 :b
|
166
|
+
virtual assert: -> { a == b }
|
167
|
+
end
|
168
|
+
array :data, type: :uint8, initial_length: 4
|
169
|
+
end
|
170
|
+
|
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
|
181
|
+
end
|
182
|
+
end
|