bindata 1.2.2 → 1.3.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.

Potentially problematic release.


This version of bindata might be problematic. Click here for more details.

Files changed (52) hide show
  1. data/ChangeLog +12 -0
  2. data/NEWS +53 -0
  3. data/Rakefile +2 -1
  4. data/examples/NBT.txt +149 -0
  5. data/examples/ip_address.rb +1 -2
  6. data/examples/list.rb +124 -0
  7. data/examples/nbt.rb +195 -0
  8. data/lib/bindata.rb +4 -3
  9. data/lib/bindata/alignment.rb +86 -0
  10. data/lib/bindata/array.rb +21 -29
  11. data/lib/bindata/base.rb +82 -81
  12. data/lib/bindata/base_primitive.rb +66 -48
  13. data/lib/bindata/choice.rb +18 -28
  14. data/lib/bindata/deprecated.rb +17 -0
  15. data/lib/bindata/dsl.rb +25 -15
  16. data/lib/bindata/int.rb +2 -2
  17. data/lib/bindata/io.rb +8 -6
  18. data/lib/bindata/offset.rb +91 -0
  19. data/lib/bindata/primitive.rb +22 -11
  20. data/lib/bindata/record.rb +40 -10
  21. data/lib/bindata/sanitize.rb +15 -30
  22. data/lib/bindata/string.rb +16 -17
  23. data/lib/bindata/stringz.rb +0 -1
  24. data/lib/bindata/struct.rb +17 -6
  25. data/lib/bindata/trace.rb +52 -0
  26. data/lib/bindata/wrapper.rb +28 -6
  27. data/manual.haml +56 -10
  28. data/manual.md +318 -113
  29. data/spec/alignment_spec.rb +61 -0
  30. data/spec/array_spec.rb +139 -178
  31. data/spec/base_primitive_spec.rb +86 -111
  32. data/spec/base_spec.rb +200 -172
  33. data/spec/bits_spec.rb +45 -53
  34. data/spec/choice_spec.rb +91 -87
  35. data/spec/deprecated_spec.rb +36 -14
  36. data/spec/float_spec.rb +16 -68
  37. data/spec/int_spec.rb +26 -27
  38. data/spec/io_spec.rb +105 -105
  39. data/spec/lazy_spec.rb +50 -50
  40. data/spec/primitive_spec.rb +36 -36
  41. data/spec/record_spec.rb +134 -134
  42. data/spec/registry_spec.rb +34 -38
  43. data/spec/rest_spec.rb +8 -11
  44. data/spec/skip_spec.rb +9 -17
  45. data/spec/spec_common.rb +4 -0
  46. data/spec/string_spec.rb +92 -115
  47. data/spec/stringz_spec.rb +41 -74
  48. data/spec/struct_spec.rb +132 -153
  49. data/spec/system_spec.rb +115 -60
  50. data/spec/wrapper_spec.rb +63 -31
  51. data/tasks/pkg.rake +1 -1
  52. metadata +15 -7
@@ -4,148 +4,115 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_common"))
4
4
  require 'bindata/stringz'
5
5
 
6
6
  describe BinData::Stringz, "when empty" do
7
- before(:each) do
8
- @str = BinData::Stringz.new
9
- end
10
-
11
- it "should include the zero byte in num_bytes total" do
12
- @str.num_bytes.should == 1
13
- end
14
-
15
- it "should not append the zero byte terminator to the value" do
16
- @str.value.should == ""
17
- end
18
-
19
- it "should write the zero byte terminator" do
20
- @str.to_binary_s.should == "\0"
21
- end
7
+ its(:value) { should == "" }
8
+ its(:num_bytes) { should == 1 }
9
+ its(:to_binary_s) { should == "\0" }
22
10
  end
23
11
 
24
12
  describe BinData::Stringz, "with value set" do
25
- before(:each) do
26
- @str = BinData::Stringz.new
27
- @str.value = "abcd"
28
- end
29
-
30
- it "should include the zero byte in num_bytes total" do
31
- @str.num_bytes.should == 5
32
- end
13
+ subject { BinData::Stringz.new("abcd") }
33
14
 
34
- it "should not append the zero byte terminator to the value" do
35
- @str.value.should == "abcd"
36
- end
37
-
38
- it "should write the zero byte terminator" do
39
- @str.to_binary_s.should == "abcd\0"
40
- end
15
+ its(:value) { should == "abcd" }
16
+ its(:num_bytes) { should == 5 }
17
+ its(:to_binary_s) { should == "abcd\0" }
41
18
  end
42
19
 
43
20
  describe BinData::Stringz, "when reading" do
44
- before(:each) do
45
- @str = BinData::Stringz.new
46
- end
47
-
48
21
  it "should stop at the first zero byte" do
49
22
  io = StringIO.new("abcd\0xyz\0")
50
- @str.read(io)
51
- @str.value.should == "abcd"
23
+ subject.read(io)
52
24
  io.pos.should == 5
25
+ subject.should == "abcd"
53
26
  end
54
27
 
55
28
  it "should handle a zero length string" do
56
29
  io = StringIO.new("\0abcd")
57
- @str.read(io)
58
- @str.value.should == ""
30
+ subject.read(io)
59
31
  io.pos.should == 1
32
+ subject.should == ""
60
33
  end
61
34
 
62
35
  it "should fail if no zero byte is found" do
63
- lambda {@str.read("abcd") }.should raise_error(EOFError)
36
+ lambda {subject.read("abcd") }.should raise_error(EOFError)
64
37
  end
65
38
  end
66
39
 
67
40
  describe BinData::Stringz, "when setting the value" do
68
- before(:each) do
69
- @str = BinData::Stringz.new
70
- end
71
-
72
41
  it "should include the zero byte in num_bytes total" do
73
- @str.value = "abcd"
74
- @str.num_bytes.should == 5
42
+ subject.assign("abcd")
43
+ subject.num_bytes.should == 5
75
44
  end
76
45
 
77
46
  it "should accept empty strings" do
78
- @str.value = ""
79
- @str.value.should == ""
47
+ subject.assign("")
48
+ subject.should == ""
80
49
  end
81
50
 
82
51
  it "should accept strings that aren't zero terminated" do
83
- @str.value = "abcd"
84
- @str.value.should == "abcd"
52
+ subject.assign("abcd")
53
+ subject.should == "abcd"
85
54
  end
86
55
 
87
56
  it "should accept strings that are zero terminated" do
88
- @str.value = "abcd\0"
89
- @str.value.should == "abcd"
57
+ subject.assign("abcd\0")
58
+ subject.should == "abcd"
90
59
  end
91
60
 
92
61
  it "should accept up to the first zero byte" do
93
- @str.value = "abcd\0xyz\0"
94
- @str.value.should == "abcd"
62
+ subject.assign("abcd\0xyz\0")
63
+ subject.should == "abcd"
95
64
  end
96
65
  end
97
66
 
98
67
  describe BinData::Stringz, "with max_length" do
99
- before(:each) do
100
- @str = BinData::Stringz.new(:max_length => 5)
101
- end
68
+ subject { BinData::Stringz.new(:max_length => 5) }
102
69
 
103
70
  it "should read less than max_length" do
104
71
  io = StringIO.new("abc\0xyz")
105
- @str.read(io)
106
- @str.value.should == "abc"
72
+ subject.read(io)
73
+ subject.should == "abc"
107
74
  end
108
75
 
109
76
  it "should read exactly max_length" do
110
77
  io = StringIO.new("abcd\0xyz")
111
- @str.read(io)
112
- @str.value.should == "abcd"
78
+ subject.read(io)
79
+ subject.should == "abcd"
113
80
  end
114
81
 
115
82
  it "should read no more than max_length" do
116
83
  io = StringIO.new("abcdefg\0xyz")
117
- @str.read(io)
118
- @str.value.should == "abcd"
84
+ subject.read(io)
119
85
  io.pos.should == 5
86
+ subject.should == "abcd"
120
87
  end
121
88
 
122
89
  it "should accept values less than max_length" do
123
- @str.value = "abc"
124
- @str.value.should == "abc"
90
+ subject.assign("abc")
91
+ subject.should == "abc"
125
92
  end
126
93
 
127
94
  it "should accept values exactly max_length" do
128
- @str.value = "abcd"
129
- @str.value.should == "abcd"
95
+ subject.assign("abcd")
96
+ subject.should == "abcd"
130
97
  end
131
98
 
132
99
  it "should trim values greater than max_length" do
133
- @str.value = "abcde"
134
- @str.value.should == "abcd"
100
+ subject.assign("abcde")
101
+ subject.should == "abcd"
135
102
  end
136
103
 
137
104
  it "should write values greater than max_length" do
138
- @str.value = "abcde"
139
- @str.to_binary_s.should == "abcd\0"
105
+ subject.assign("abcde")
106
+ subject.to_binary_s.should == "abcd\0"
140
107
  end
141
108
 
142
109
  it "should write values less than max_length" do
143
- @str.value = "abc"
144
- @str.to_binary_s.should == "abc\0"
110
+ subject.assign("abc")
111
+ subject.to_binary_s.should == "abc\0"
145
112
  end
146
113
 
147
114
  it "should write values exactly max_length" do
148
- @str.value = "abcd"
149
- @str.to_binary_s.should == "abcd\0"
115
+ subject.assign("abcd")
116
+ subject.to_binary_s.should == "abcd\0"
150
117
  end
151
118
  end
@@ -42,72 +42,71 @@ describe BinData::Struct, "when initializing" do
42
42
  end
43
43
 
44
44
  describe BinData::Struct, "with anonymous fields" do
45
- before(:each) do
46
- @params = { :fields => [
47
- [:int8, :a, {:initial_value => 10}],
48
- [:int8, nil],
49
- [:int8, '', {:value => :a}]] }
50
- @obj = BinData::Struct.new(@params)
51
- end
45
+ subject {
46
+ params = { :fields => [
47
+ [:int8, :a, {:initial_value => 5}],
48
+ [:int8, nil],
49
+ [:int8, '', {:value => :a}]
50
+ ] }
51
+ BinData::Struct.new(params)
52
+ }
52
53
 
53
54
  it "should only show non anonymous fields" do
54
- @obj.field_names.should == ["a"]
55
+ subject.field_names.should == ["a"]
55
56
  end
56
57
 
57
58
  it "should not include anonymous fields in snapshot" do
58
- @obj.a = 5
59
- @obj.snapshot.should == {"a" => 5}
59
+ subject.a = 5
60
+ subject.snapshot.should == {"a" => 5}
60
61
  end
61
62
 
62
63
  it "should write anonymous fields" do
63
- str = "\001\002\003"
64
- @obj.read(str)
65
- @obj.a.clear
66
- @obj.to_binary_s.should == "\012\002\012"
64
+ subject.read("\001\002\003")
65
+ subject.a.clear
66
+ subject.to_binary_s.should == "\005\002\005"
67
67
  end
68
68
  end
69
69
 
70
70
  describe BinData::Struct, "with hidden fields" do
71
- before(:each) do
72
- @params = { :hide => [:b, 'c'],
73
- :fields => [
71
+ subject {
72
+ params = { :hide => [:b, :c],
73
+ :fields => [
74
74
  [:int8, :a],
75
- [:int8, 'b', {:initial_value => 10}],
75
+ [:int8, 'b', {:initial_value => 5}],
76
76
  [:int8, :c],
77
77
  [:int8, :d, {:value => :b}]] }
78
- @obj = BinData::Struct.new(@params)
79
- end
78
+ BinData::Struct.new(params)
79
+ }
80
80
 
81
81
  it "should only show fields that aren't hidden" do
82
- @obj.field_names.should == ["a", "d"]
82
+ subject.field_names.should == ["a", "d"]
83
83
  end
84
84
 
85
85
  it "should be able to access hidden fields directly" do
86
- @obj.b.should == 10
87
- @obj.c = 15
88
- @obj.c.should == 15
86
+ subject.b.should == 5
87
+ subject.c = 15
88
+ subject.c.should == 15
89
89
 
90
- @obj.should respond_to(:b=)
90
+ subject.should respond_to(:b=)
91
91
  end
92
92
 
93
93
  it "should not include hidden fields in snapshot" do
94
- @obj.b = 5
95
- @obj.snapshot.should == {"a" => 0, "d" => 5}
94
+ subject.b = 7
95
+ subject.snapshot.should == {"a" => 0, "d" => 7}
96
96
  end
97
97
  end
98
98
 
99
99
  describe BinData::Struct, "with multiple fields" do
100
- before(:each) do
101
- @params = { :fields => [ [:int8, :a], [:int8, :b] ] }
102
- @obj = BinData::Struct.new(@params)
103
- @obj.a = 1
104
- @obj.b = 2
105
- end
100
+ let(:params) { { :fields => [ [:int8, :a], [:int8, :b] ] } }
101
+ subject { BinData::Struct.new({:a => 1, :b => 2}, params) }
102
+
103
+ its(:field_names) { should == ["a", "b"] }
104
+ its(:to_binary_s) { should == "\x01\x02" }
106
105
 
107
106
  it "should return num_bytes" do
108
- @obj.a.num_bytes.should == 1
109
- @obj.b.num_bytes.should == 1
110
- @obj.num_bytes.should == 2
107
+ subject.a.num_bytes.should == 1
108
+ subject.b.num_bytes.should == 1
109
+ subject.num_bytes.should == 2
111
110
  end
112
111
 
113
112
  it "should identify accepted parameters" do
@@ -116,194 +115,174 @@ describe BinData::Struct, "with multiple fields" do
116
115
  BinData::Struct.accepted_parameters.all.should include(:endian)
117
116
  end
118
117
 
119
- it "should return field names" do
120
- @obj.field_names.should == ["a", "b"]
121
- end
122
-
123
118
  it "should clear" do
124
- @obj.a = 6
125
- @obj.clear
126
- @obj.should be_clear
119
+ subject.a = 6
120
+ subject.clear
121
+ subject.should be_clear
127
122
  end
128
123
 
129
124
  it "should clear individual elements" do
130
- @obj.a = 6
131
- @obj.b = 7
132
- @obj.a.clear
133
- @obj.a.should be_clear
134
- @obj.b.should_not be_clear
135
- end
136
-
137
- it "should write ordered" do
138
- @obj.to_binary_s.should == "\x01\x02"
125
+ subject.a = 6
126
+ subject.b = 7
127
+ subject.a.clear
128
+ subject.a.should be_clear
129
+ subject.b.should_not be_clear
139
130
  end
140
131
 
141
132
  it "should read ordered" do
142
- @obj.read("\x03\x04")
133
+ subject.read("\x03\x04")
143
134
 
144
- @obj.a.should == 3
145
- @obj.b.should == 4
135
+ subject.a.should == 3
136
+ subject.b.should == 4
146
137
  end
147
138
 
148
139
  it "should return a snapshot" do
149
- snap = @obj.snapshot
140
+ snap = subject.snapshot
150
141
  snap.a.should == 1
151
142
  snap.b.should == 2
152
143
  snap.should == { "a" => 1, "b" => 2 }
153
144
  end
154
145
 
155
146
  it "should assign from partial hash" do
156
- @obj.assign("a" => 3)
157
- @obj.a.should == 3
158
- @obj.b.should == 0
147
+ subject.assign("a" => 3)
148
+ subject.a.should == 3
149
+ subject.b.should == 0
159
150
  end
160
151
 
161
152
  it "should assign from hash" do
162
- @obj.assign("a" => 3, "b" => 4)
163
- @obj.a.should == 3
164
- @obj.b.should == 4
153
+ subject.assign("a" => 3, "b" => 4)
154
+ subject.a.should == 3
155
+ subject.b.should == 4
165
156
  end
166
157
 
167
158
  it "should assign from nil" do
168
- @obj.assign(nil)
169
- @obj.should be_clear
159
+ subject.assign(nil)
160
+ subject.should be_clear
170
161
  end
171
162
 
172
163
  it "should assign from Struct" do
173
- src = BinData::Struct.new(@params)
164
+ src = BinData::Struct.new(params)
174
165
  src.a = 3
175
166
  src.b = 4
176
167
 
177
- @obj.assign(src)
178
- @obj.a.should == 3
179
- @obj.b.should == 4
168
+ subject.assign(src)
169
+ subject.a.should == 3
170
+ subject.b.should == 4
180
171
  end
181
172
 
182
173
  it "should assign from snapshot" do
183
- src = BinData::Struct.new(@params)
174
+ src = BinData::Struct.new(params)
184
175
  src.a = 3
185
176
  src.b = 4
186
177
 
187
- @obj.assign(src.snapshot)
188
- @obj.a.should == 3
189
- @obj.b.should == 4
178
+ subject.assign(src.snapshot)
179
+ subject.a.should == 3
180
+ subject.b.should == 4
190
181
  end
191
182
 
192
183
  it "should fail on unknown method call" do
193
- lambda { @obj.does_not_exist }.should raise_error(NoMethodError)
184
+ lambda { subject.does_not_exist }.should raise_error(NoMethodError)
194
185
  end
195
186
  end
196
187
 
197
188
  describe BinData::Struct, "with nested structs" do
198
- before(:each) do
189
+ subject {
199
190
  inner1 = [ [:int8, :w, {:initial_value => 3}],
200
191
  [:int8, :x, {:value => :the_val}] ]
201
192
 
202
193
  inner2 = [ [:int8, :y, {:value => lambda { parent.b.w }}],
203
194
  [:int8, :z] ]
204
195
 
205
- @params = { :fields => [
206
- [:int8, :a, {:initial_value => 6}],
207
- [:struct, :b, {:fields => inner1, :the_val => :a}],
208
- [:struct, :c, {:fields => inner2}]] }
209
- @obj = BinData::Struct.new(@params)
210
- end
196
+ params = { :fields => [
197
+ [:int8, :a, {:initial_value => 6}],
198
+ [:struct, :b, {:fields => inner1, :the_val => :a}],
199
+ [:struct, :c, {:fields => inner2}]] }
200
+ BinData::Struct.new(params)
201
+ }
211
202
 
212
- it "should included nested field names" do
213
- @obj.field_names.should == ["a", "b", "c"]
214
- end
203
+ its(:field_names) { should == ["a", "b", "c"] }
215
204
 
216
205
  it "should return num_bytes" do
217
- @obj.b.num_bytes.should == 2
218
- @obj.c.num_bytes.should == 2
219
- @obj.num_bytes.should == 5
206
+ subject.b.num_bytes.should == 2
207
+ subject.c.num_bytes.should == 2
208
+ subject.num_bytes.should == 5
220
209
  end
221
210
 
222
211
  it "should access nested fields" do
223
- @obj.a.should == 6
224
- @obj.b.w.should == 3
225
- @obj.b.x.should == 6
226
- @obj.c.y.should == 3
227
- @obj.c.z.should == 0
212
+ subject.a.should == 6
213
+ subject.b.w.should == 3
214
+ subject.b.x.should == 6
215
+ subject.c.y.should == 3
216
+ subject.c.z.should == 0
228
217
  end
229
218
 
230
219
  it "should return correct offset" do
231
- @obj.b.offset.should == 1
232
- @obj.b.w.offset.should == 1
233
- @obj.c.offset.should == 3
234
- @obj.c.z.offset.should == 4
220
+ subject.b.offset.should == 1
221
+ subject.b.w.offset.should == 1
222
+ subject.c.offset.should == 3
223
+ subject.c.z.offset.should == 4
235
224
  end
236
225
  end
237
226
 
238
227
  describe BinData::Struct, "with an endian defined" do
239
- before(:each) do
240
- @obj = BinData::Struct.new(:endian => :little,
241
- :fields => [
242
- [:uint16, :a],
243
- [:float, :b],
244
- [:array, :c,
245
- {:type => :int8, :initial_length => 2}],
246
- [:choice, :d,
247
- {:choices => [[:uint16], [:uint32]],
248
- :selection => 1}],
249
- [:struct, :e,
250
- {:fields => [[:uint16, :f],
251
- [:uint32be, :g]]}],
252
- [:struct, :h,
253
- {:fields => [
254
- [:struct, :i,
255
- {:fields => [[:uint16, :j]]}]]}]])
256
-
257
- end
228
+ subject {
229
+ BinData::Struct.new(:endian => :little,
230
+ :fields => [
231
+ [:uint16, :a],
232
+ [:float, :b],
233
+ [:array, :c,
234
+ {:type => :int8, :initial_length => 2}],
235
+ [:choice, :d,
236
+ {:choices => [[:uint16], [:uint32]],
237
+ :selection => 1}],
238
+ [:struct, :e,
239
+ {:fields => [[:uint16, :f],
240
+ [:uint32be, :g]]}],
241
+ [:struct, :h,
242
+ {:fields => [
243
+ [:struct, :i,
244
+ {:fields => [[:uint16, :j]]}]]}]])
245
+ }
258
246
 
259
247
  it "should use correct endian" do
260
- @obj.a = 1
261
- @obj.b = 2.0
262
- @obj.c[0] = 3
263
- @obj.c[1] = 4
264
- @obj.d = 5
265
- @obj.e.f = 6
266
- @obj.e.g = 7
267
- @obj.h.i.j = 8
248
+ subject.a = 1
249
+ subject.b = 2.0
250
+ subject.c[0] = 3
251
+ subject.c[1] = 4
252
+ subject.d = 5
253
+ subject.e.f = 6
254
+ subject.e.g = 7
255
+ subject.h.i.j = 8
268
256
 
269
257
  expected = [1, 2.0, 3, 4, 5, 6, 7, 8].pack('veCCVvNv')
270
258
 
271
- @obj.to_binary_s.should == expected
259
+ subject.to_binary_s.should == expected
272
260
  end
273
261
  end
274
262
 
275
263
  describe BinData::Struct, "with bit fields" do
276
- before(:each) do
277
- @params = { :fields => [ [:bit1le, :a], [:bit2le, :b], [:uint8, :c], [:bit1le, :d] ] }
278
- @obj = BinData::Struct.new(@params)
279
- @obj.a = 1
280
- @obj.b = 2
281
- @obj.c = 3
282
- @obj.d = 1
283
- end
264
+ subject {
265
+ params = { :fields => [ [:bit1le, :a], [:bit2le, :b], [:uint8, :c], [:bit1le, :d] ] }
266
+ BinData::Struct.new({:a => 1, :b => 2, :c => 3, :d => 1}, params)
267
+ }
284
268
 
285
- it "should return num_bytes" do
286
- @obj.num_bytes.should == 3
287
- end
288
-
289
- it "should write" do
290
- @obj.to_binary_s.should == [0b0000_0101, 3, 1].pack("C*")
291
- end
269
+ its(:num_bytes) { should == 3 }
270
+ its(:to_binary_s) { should == [0b0000_0101, 3, 1].pack("C*") }
292
271
 
293
272
  it "should read" do
294
273
  str = [0b0000_0110, 5, 0].pack("C*")
295
- @obj.read(str)
296
- @obj.a.should == 0
297
- @obj.b.should == 3
298
- @obj.c.should == 5
299
- @obj.d.should == 0
274
+ subject.read(str)
275
+ subject.a.should == 0
276
+ subject.b.should == 3
277
+ subject.c.should == 5
278
+ subject.d.should == 0
300
279
  end
301
280
 
302
281
  it "should have correct offsets" do
303
- @obj.a.offset.should == 0
304
- @obj.b.offset.should == 0
305
- @obj.c.offset.should == 1
306
- @obj.d.offset.should == 2
282
+ subject.a.offset.should == 0
283
+ subject.b.offset.should == 0
284
+ subject.c.offset.should == 1
285
+ subject.d.offset.should == 2
307
286
  end
308
287
  end
309
288
 
@@ -315,12 +294,12 @@ describe BinData::Struct, "with nested endian" do
315
294
  :fields => [[:int16, :a],
316
295
  [:struct, :s, nested_params],
317
296
  [:int16, :d]] }
318
- obj = BinData::Struct.new(params)
319
- obj.read("\x00\x01\x02\x00\x03\x00\x00\x04")
297
+ subject = BinData::Struct.new(params)
298
+ subject.read("\x00\x01\x02\x00\x03\x00\x00\x04")
320
299
 
321
- obj.a.should == 1
322
- obj.s.b.should == 2
323
- obj.s.c.should == 3
324
- obj.d.should == 4
300
+ subject.a.should == 1
301
+ subject.s.b.should == 2
302
+ subject.s.c.should == 3
303
+ subject.d.should == 4
325
304
  end
326
305
  end