bindata 2.4.10 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.rdoc +39 -0
  3. data/LICENSE +25 -0
  4. data/NEWS.rdoc +5 -0
  5. data/README.md +6 -9
  6. data/bindata.gemspec +9 -4
  7. data/examples/NBT.txt +1 -1
  8. data/examples/list.rb +1 -1
  9. data/lib/bindata/alignment.rb +15 -7
  10. data/lib/bindata/array.rb +54 -54
  11. data/lib/bindata/base.rb +14 -25
  12. data/lib/bindata/base_primitive.rb +24 -20
  13. data/lib/bindata/bits.rb +15 -15
  14. data/lib/bindata/buffer.rb +89 -11
  15. data/lib/bindata/choice.rb +9 -6
  16. data/lib/bindata/count_bytes_remaining.rb +1 -1
  17. data/lib/bindata/delayed_io.rb +18 -10
  18. data/lib/bindata/dsl.rb +37 -35
  19. data/lib/bindata/float.rb +3 -3
  20. data/lib/bindata/framework.rb +8 -10
  21. data/lib/bindata/int.rb +14 -16
  22. data/lib/bindata/io.rb +276 -253
  23. data/lib/bindata/name.rb +1 -1
  24. data/lib/bindata/params.rb +9 -7
  25. data/lib/bindata/primitive.rb +3 -3
  26. data/lib/bindata/registry.rb +18 -18
  27. data/lib/bindata/rest.rb +1 -1
  28. data/lib/bindata/sanitize.rb +9 -16
  29. data/lib/bindata/section.rb +97 -0
  30. data/lib/bindata/skip.rb +140 -51
  31. data/lib/bindata/string.rb +9 -9
  32. data/lib/bindata/stringz.rb +12 -10
  33. data/lib/bindata/struct.rb +92 -68
  34. data/lib/bindata/trace.rb +35 -42
  35. data/lib/bindata/transform/brotli.rb +35 -0
  36. data/lib/bindata/transform/lz4.rb +35 -0
  37. data/lib/bindata/transform/lzma.rb +35 -0
  38. data/lib/bindata/transform/xor.rb +19 -0
  39. data/lib/bindata/transform/xz.rb +35 -0
  40. data/lib/bindata/transform/zlib.rb +33 -0
  41. data/lib/bindata/transform/zstd.rb +35 -0
  42. data/lib/bindata/uint8_array.rb +2 -2
  43. data/lib/bindata/version.rb +1 -1
  44. data/lib/bindata/virtual.rb +4 -7
  45. data/lib/bindata/warnings.rb +1 -1
  46. data/lib/bindata.rb +1 -0
  47. data/test/alignment_test.rb +8 -8
  48. data/test/array_test.rb +98 -96
  49. data/test/base_primitive_test.rb +47 -47
  50. data/test/base_test.rb +24 -24
  51. data/test/bits_test.rb +15 -15
  52. data/test/buffer_test.rb +31 -22
  53. data/test/choice_test.rb +32 -32
  54. data/test/count_bytes_remaining_test.rb +8 -8
  55. data/test/delayed_io_test.rb +91 -30
  56. data/test/float_test.rb +8 -8
  57. data/test/int_test.rb +14 -14
  58. data/test/io_test.rb +110 -302
  59. data/test/lazy_test.rb +38 -38
  60. data/test/params_test.rb +19 -19
  61. data/test/primitive_test.rb +26 -26
  62. data/test/record_test.rb +99 -99
  63. data/test/registry_test.rb +43 -43
  64. data/test/rest_test.rb +5 -5
  65. data/test/section_test.rb +111 -0
  66. data/test/skip_test.rb +71 -26
  67. data/test/string_test.rb +60 -60
  68. data/test/stringz_test.rb +34 -26
  69. data/test/struct_test.rb +167 -92
  70. data/test/system_test.rb +159 -41
  71. data/test/test_helper.rb +24 -13
  72. data/test/uint8_array_test.rb +6 -6
  73. data/test/virtual_test.rb +7 -7
  74. data/test/warnings_test.rb +14 -2
  75. metadata +19 -22
  76. data/.gitignore +0 -2
  77. data/.travis.yml +0 -15
  78. data/BSDL +0 -22
  79. data/COPYING +0 -52
  80. data/INSTALL +0 -12
  81. data/lib/bindata/offset.rb +0 -94
  82. data/test/offset_test.rb +0 -100
@@ -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
- lambda {
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
- lambda {
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, false
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
- lambda {
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
- lambda {
89
+ _ {
90
90
  r.lookup("int3")
91
91
  }.must_raise BinData::UnRegisteredTypeError
92
- lambda {
92
+ _ {
93
93
  r.lookup("int3", {endian: :big})
94
94
  }.must_raise BinData::UnRegisteredTypeError
95
- lambda {
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
- lambda {
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
- lambda {
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
- lambda { BinData::Skip.new(args) }.must_raise ArgumentError
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
- lambda {
63
+ _ {
64
64
  obj.read(io)
65
- }.must_raise BinData::ValidityError
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
- lambda {
83
+ _ {
84
84
  obj.to_binary_s
85
- }.must_raise BinData::ValidityError
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 EOFError when no match" do
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
- lambda {
132
+ _ {
113
133
  obj.read(io)
114
- }.must_raise EOFError
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
- lambda {
141
+ _ {
122
142
  obj.read(io)
123
143
  }.must_raise IOError
124
144
  end
125
145
 
126
- class DSLSkip < BinData::Record
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
- string read_length: 1, assert: "f"
162
+ uint8
163
+ uint8 asserted_value: 1
164
+ uint8 :a
165
+ uint8 :b
166
+ virtual assert: -> { a == b }
129
167
  end
130
- string :a, read_length: 1
168
+ array :data, type: :uint8, initial_length: 4
131
169
  end
132
170
 
133
- it "uses block form" do
134
- obj = DSLSkip.read(io)
135
- obj.a.must_equal "f"
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