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
@@ -12,102 +12,98 @@ describe BinData::Registry do
12
12
  C = Class.new
13
13
  D = Class.new
14
14
 
15
- before(:each) do
16
- @r = BinData::Registry.new
17
- end
15
+ let(:r) { BinData::Registry.new }
18
16
 
19
17
  it "should determine if a name is registered" do
20
- @r.register('A', A)
18
+ r.register('A', A)
21
19
 
22
- @r.is_registered?('a').should be_true
20
+ r.is_registered?('a').should be_true
23
21
  end
24
22
 
25
23
  it "should determine if a name is not registered" do
26
24
  lambda {
27
- @r.is_registered?('xyz')
25
+ r.is_registered?('xyz')
28
26
  }.should raise_error(BinData::UnRegisteredTypeError)
29
27
  end
30
28
 
31
29
  it "should lookup registered names" do
32
- @r.register('ASubClass', A)
33
- @r.register('AnotherSubClass', B)
30
+ r.register('ASubClass', A)
31
+ r.register('AnotherSubClass', B)
34
32
 
35
- @r.lookup('a_sub_class').should == A
36
- @r.lookup('another_sub_class').should == B
33
+ r.lookup('a_sub_class').should == A
34
+ r.lookup('another_sub_class').should == B
37
35
  end
38
36
 
39
37
  it "should not lookup unregistered names" do
40
38
  lambda {
41
- @r.lookup('a_non_existent_sub_class')
39
+ r.lookup('a_non_existent_sub_class')
42
40
  }.should raise_error(BinData::UnRegisteredTypeError)
43
41
  end
44
42
 
45
43
  it "should allow overriding of registered classes" do
46
- @r.register('A', A)
47
- @r.register('A', B)
44
+ r.register('A', A)
45
+ r.register('A', B)
48
46
 
49
- @r.lookup('a').should == B
47
+ r.lookup('a').should == B
50
48
  end
51
49
 
52
50
  it "should convert CamelCase to underscores" do
53
- @r.underscore_name('CamelCase').should == 'camel_case'
51
+ r.underscore_name('CamelCase').should == 'camel_case'
54
52
  end
55
53
 
56
54
  it "should convert adjacent caps camelCase to underscores" do
57
- @r.underscore_name('XYZCamelCase').should == 'xyz_camel_case'
55
+ r.underscore_name('XYZCamelCase').should == 'xyz_camel_case'
58
56
  end
59
57
 
60
58
  it "should ignore the outer nestings of classes" do
61
- @r.underscore_name('A::B::C').should == 'c'
59
+ r.underscore_name('A::B::C').should == 'c'
62
60
  end
63
61
  end
64
62
 
65
63
  describe BinData::Registry, "with numerics" do
66
- before(:each) do
67
- @r = BinData::RegisteredClasses
68
- end
64
+ let(:r) { BinData::RegisteredClasses }
69
65
 
70
66
  it "should lookup integers with endian" do
71
- @r.lookup("int24", :big).to_s.should == "BinData::Int24be"
72
- @r.lookup("int24", :little).to_s.should == "BinData::Int24le"
73
- @r.lookup("uint24", :big).to_s.should == "BinData::Uint24be"
74
- @r.lookup("uint24", :little).to_s.should == "BinData::Uint24le"
67
+ r.lookup("int24", :big).to_s.should == "BinData::Int24be"
68
+ r.lookup("int24", :little).to_s.should == "BinData::Int24le"
69
+ r.lookup("uint24", :big).to_s.should == "BinData::Uint24be"
70
+ r.lookup("uint24", :little).to_s.should == "BinData::Uint24le"
75
71
  end
76
72
 
77
73
  it "should not lookup integers without endian" do
78
74
  lambda {
79
- @r.lookup("int24")
75
+ r.lookup("int24")
80
76
  }.should raise_error(BinData::UnRegisteredTypeError)
81
77
  end
82
78
 
83
79
  it "should not lookup non byte based integers" do
84
80
  lambda {
85
- @r.lookup("int3")
81
+ r.lookup("int3")
86
82
  }.should raise_error(BinData::UnRegisteredTypeError)
87
83
  lambda {
88
- @r.lookup("int3", :big)
84
+ r.lookup("int3", :big)
89
85
  }.should raise_error(BinData::UnRegisteredTypeError)
90
86
  lambda {
91
- @r.lookup("int3", :little)
87
+ r.lookup("int3", :little)
92
88
  }.should raise_error(BinData::UnRegisteredTypeError)
93
89
  end
94
90
 
95
91
  it "should lookup floats with endian" do
96
- @r.lookup("float", :big).to_s.should == "BinData::FloatBe"
97
- @r.lookup("float", :little).to_s.should == "BinData::FloatLe"
98
- @r.lookup("double", :big).to_s.should == "BinData::DoubleBe"
99
- @r.lookup("double", :little).to_s.should == "BinData::DoubleLe"
92
+ r.lookup("float", :big).to_s.should == "BinData::FloatBe"
93
+ r.lookup("float", :little).to_s.should == "BinData::FloatLe"
94
+ r.lookup("double", :big).to_s.should == "BinData::DoubleBe"
95
+ r.lookup("double", :little).to_s.should == "BinData::DoubleLe"
100
96
  end
101
97
 
102
98
  it "should lookup bits" do
103
- @r.lookup("bit5").to_s.should == "BinData::Bit5"
104
- @r.lookup("bit6le").to_s.should == "BinData::Bit6le"
99
+ r.lookup("bit5").to_s.should == "BinData::Bit5"
100
+ r.lookup("bit6le").to_s.should == "BinData::Bit6le"
105
101
  end
106
102
 
107
103
  it "should lookup bits by ignoring endian" do
108
- @r.lookup("bit2", :big).to_s.should == "BinData::Bit2"
109
- @r.lookup("bit3le", :big).to_s.should == "BinData::Bit3le"
110
- @r.lookup("bit2", :little).to_s.should == "BinData::Bit2"
111
- @r.lookup("bit3le", :little).to_s.should == "BinData::Bit3le"
104
+ r.lookup("bit2", :big).to_s.should == "BinData::Bit2"
105
+ r.lookup("bit3le", :big).to_s.should == "BinData::Bit3le"
106
+ r.lookup("bit2", :little).to_s.should == "BinData::Bit2"
107
+ r.lookup("bit3le", :little).to_s.should == "BinData::Bit3le"
112
108
  end
113
109
  end
@@ -4,26 +4,23 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_common"))
4
4
  require 'bindata/rest'
5
5
 
6
6
  describe BinData::Rest do
7
+ it { should == "" }
8
+
7
9
  it "should read till end of stream" do
8
10
  data = "abcdefghij"
9
- BinData::Rest.read(data).should == data
10
- end
11
-
12
- it "should default to the empty string" do
13
- BinData::Rest.new.value.should == ""
11
+ subject.read(data).should == data
14
12
  end
15
13
 
16
14
  it "should allow setting value for completeness" do
17
- rest = BinData::Rest.new
18
- rest.value = "123"
19
- rest.value.should == "123"
20
- rest.to_binary_s.should == "123"
15
+ subject.assign("123")
16
+ subject.should == "123"
17
+ subject.to_binary_s.should == "123"
21
18
  end
22
19
 
23
20
  it "should accept BinData::BasePrimitive parameters" do
24
21
  rest = BinData::Rest.new(:check_value => "abc")
25
22
  lambda {
26
- rest.read("abc")
27
- }.should_not raise_error(BinData::ValidityError)
23
+ rest.read("xyz")
24
+ }.should raise_error(BinData::ValidityError)
28
25
  end
29
26
  end
@@ -4,32 +4,24 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_common"))
4
4
  require 'bindata/skip'
5
5
 
6
6
  describe BinData::Skip do
7
- before(:each) do
8
- @skip = BinData::Skip.new(:length => 5)
9
- end
7
+ subject { BinData::Skip.new(:length => 5) }
8
+ let(:io) { StringIO.new("abcdefghij") }
10
9
 
11
- it "should default to the empty string" do
12
- @skip.should == ""
13
- end
10
+ it { should == "" }
11
+ its(:to_binary_s) { should == "\000" * 5 }
14
12
 
15
13
  it "should skip bytes" do
16
- io = StringIO.new("abcdefghij")
17
- @skip.read(io)
14
+ subject.read(io)
18
15
  io.pos.should == 5
19
16
  end
20
17
 
21
- it "should have expected binary representation" do
22
- @skip.to_binary_s.should == "\000" * 5
23
- end
24
-
25
18
  it "should have expected binary representation after setting value" do
26
- @skip.value = "123"
27
- @skip.to_binary_s.should == "\000" * 5
19
+ subject.assign("123")
20
+ subject.to_binary_s.should == "\000" * 5
28
21
  end
29
22
 
30
23
  it "should have expected binary representation after reading" do
31
- io = StringIO.new("abcdefghij")
32
- @skip.read(io)
33
- @skip.to_binary_s.should == "\000" * 5
24
+ subject.read(io)
25
+ subject.to_binary_s.should == "\000" * 5
34
26
  end
35
27
  end
@@ -13,6 +13,10 @@ class Object
13
13
  protected_method_names = cls.protected_instance_methods - Object.protected_instance_methods
14
14
  cls.send(:public, *protected_method_names)
15
15
  end
16
+
17
+ def value_read_from_written
18
+ self.class.read(self.to_binary_s)
19
+ end
16
20
  end
17
21
 
18
22
  class StringIO
@@ -22,170 +22,147 @@ describe BinData::String, "with mutually exclusive parameters" do
22
22
  end
23
23
 
24
24
  describe BinData::String, "when assigning" do
25
- before(:each) do
26
- @small = BinData::String.new(:length => 3, :pad_char => "A")
27
- @large = BinData::String.new(:length => 5, :pad_char => "B")
28
- end
25
+ let(:small) { BinData::String.new(:length => 3, :pad_char => "A") }
26
+ let(:large) { BinData::String.new(:length => 5, :pad_char => "B") }
29
27
 
30
28
  it "should copy data from small to large" do
31
- @large.value = @small
32
- @large.value.should == "AAABB"
29
+ large.assign(small)
30
+ large.should == "AAABB"
33
31
  end
34
32
 
35
33
  it "should copy data from large to small" do
36
- @small.value = @large
37
- @small.value.should == "BBB"
34
+ small.assign(large)
35
+ small.should == "BBB"
38
36
  end
39
37
  end
40
38
 
41
39
  describe BinData::String, "with :read_length" do
42
- before(:each) do
43
- @str = BinData::String.new(:read_length => 5)
44
- end
40
+ subject { BinData::String.new(:read_length => 5) }
45
41
 
46
- it "should have default value" do
47
- @str.num_bytes.should == 0
48
- @str.value.should == ""
49
- end
42
+ its(:num_bytes) { should == 0 }
43
+ its(:value) { should == "" }
50
44
 
51
45
  it "should read :read_length bytes" do
52
- @str.read("abcdefghij")
53
- @str.value.should == "abcde"
46
+ subject.read("abcdefghij")
47
+ subject.should == "abcde"
54
48
  end
55
49
 
56
50
  it "should remember :read_length after value is cleared" do
57
- @str.value = "abc"
58
- @str.num_bytes.should == 3
59
- @str.clear
51
+ subject.assign("abc")
52
+ subject.num_bytes.should == 3
53
+ subject.clear
60
54
 
61
- @str.read("abcdefghij")
62
- @str.value.should == "abcde"
55
+ subject.read("abcdefghij")
56
+ subject.should == "abcde"
63
57
  end
64
58
  end
65
59
 
66
60
  describe BinData::String, "with :length" do
67
- before(:each) do
68
- @str = BinData::String.new(:length => 5)
69
- end
70
-
71
- it "should set num_bytes" do
72
- @str.num_bytes.should == 5
73
- end
61
+ subject { BinData::String.new(:length => 5) }
74
62
 
75
- it "should fill value with pad_char" do
76
- @str.value.should == "\0\0\0\0\0"
77
- end
63
+ its(:num_bytes) { should == 5 }
64
+ its(:value) { should == "\0\0\0\0\0" }
78
65
 
79
66
  it "should retain :length after value is set" do
80
- @str.value = "abcdefghij"
81
- @str.num_bytes.should == 5
67
+ subject.assign("abcdefghij")
68
+ subject.num_bytes.should == 5
82
69
  end
83
70
 
84
71
  it "should read :length bytes" do
85
- @str.read("abcdefghij")
86
- @str.value.should == "abcde"
72
+ subject.read("abcdefghij")
73
+ subject.should == "abcde"
87
74
  end
88
75
 
89
76
  it "should pad values less than :length" do
90
- @str.value = "abc"
91
- @str.value.should == "abc\0\0"
77
+ subject.assign("abc")
78
+ subject.should == "abc\0\0"
92
79
  end
93
80
 
94
81
  it "should accept values exactly :length" do
95
- @str.value = "abcde"
96
- @str.value.should == "abcde"
82
+ subject.assign("abcde")
83
+ subject.should == "abcde"
97
84
  end
98
85
 
99
86
  it "should truncate values greater than :length" do
100
- @str.value = "abcdefg"
101
- @str.value.should == "abcde"
87
+ subject.assign("abcdefghij")
88
+ subject.should == "abcde"
102
89
  end
103
90
  end
104
91
 
105
92
  describe BinData::String, "with :read_length and :initial_value" do
106
- before(:each) do
107
- @str = BinData::String.new(:read_length => 5, :initial_value => "abcdefghij")
108
- end
93
+ subject { BinData::String.new(:read_length => 5, :initial_value => "abcdefghij") }
109
94
 
110
- it "should use :initial_value before value is read" do
111
- @str.num_bytes.should == 10
112
- @str.value.should == "abcdefghij"
113
- end
95
+ its(:num_bytes) { should == 10 }
96
+ its(:value) { should == "abcdefghij" }
114
97
 
115
98
  it "should use :read_length for reading" do
116
99
  io = StringIO.new("ABCDEFGHIJKLMNOPQRST")
117
- @str.read(io)
100
+ subject.read(io)
118
101
  io.pos.should == 5
119
102
  end
120
103
 
121
104
  it "should forget :initial_value after reading" do
122
- @str.read("ABCDEFGHIJKLMNOPQRST")
123
- @str.num_bytes.should == 5
124
- @str.value.should == "ABCDE"
105
+ subject.read("ABCDEFGHIJKLMNOPQRST")
106
+ subject.num_bytes.should == 5
107
+ subject.should == "ABCDE"
125
108
  end
126
109
  end
127
110
 
128
111
  describe BinData::String, "with :read_length and :value" do
129
- before(:each) do
130
- @str = BinData::String.new(:read_length => 5, :value => "abcdefghij")
131
- end
112
+ subject { BinData::String.new(:read_length => 5, :value => "abcdefghij") }
132
113
 
133
- it "should not be affected by :read_length before value is read" do
134
- @str.num_bytes.should == 10
135
- @str.value.should == "abcdefghij"
136
- end
114
+ its(:num_bytes) { should == 10 }
115
+ its(:value) { should == "abcdefghij" }
137
116
 
138
117
  it "should use :read_length for reading" do
139
118
  io = StringIO.new("ABCDEFGHIJKLMNOPQRST")
140
- @str.read(io)
119
+ subject.read(io)
141
120
  io.pos.should == 5
142
- end
143
-
144
- it "should not be affected by :read_length after reading" do
145
- @str.read("ABCDEFGHIJKLMNOPQRST")
146
- @str.num_bytes.should == 10
147
- @str.value.should == "abcdefghij"
148
121
  end
149
122
 
150
- it "should return read value while reading" do
151
- @str.read("ABCDEFGHIJKLMNOPQRST")
123
+ context "after reading" do
124
+ before(:each) do
125
+ subject.read("ABCDEFGHIJKLMNOPQRST")
126
+ end
152
127
 
153
- def @str.reading?; true; end
128
+ it "should not be affected by :read_length after reading" do
129
+ subject.num_bytes.should == 10
130
+ subject.should == "abcdefghij"
131
+ end
154
132
 
155
- @str.value.should == "ABCDE"
133
+ it "should return read value while reading" do
134
+ subject.stub(:reading?).and_return(true)
135
+ subject.should == "ABCDE"
136
+ end
156
137
  end
157
138
  end
158
139
 
159
140
  describe BinData::String, "with :length and :initial_value" do
160
- before(:each) do
161
- @str = BinData::String.new(:length => 5, :initial_value => "abcdefghij")
162
- end
141
+ subject { BinData::String.new(:length => 5, :initial_value => "abcdefghij") }
163
142
 
164
- it "should apply :length to :initial_value" do
165
- @str.num_bytes.should == 5
166
- @str.value.should == "abcde"
167
- end
143
+ its(:num_bytes) { should == 5 }
144
+ its(:value) { should == "abcde" }
168
145
 
169
146
  it "should forget :initial_value after reading" do
170
147
  io = StringIO.new("ABCDEFGHIJKLMNOPQRST")
171
- @str.read(io)
148
+ subject.read(io)
172
149
  io.pos.should == 5
173
- @str.num_bytes.should == 5
174
- @str.value.should == "ABCDE"
150
+ subject.num_bytes.should == 5
151
+ subject.should == "ABCDE"
175
152
  end
176
153
  end
177
154
 
178
155
  describe BinData::String, "with :pad_char" do
179
156
  it "should accept a numeric value for :pad_char" do
180
- @str = BinData::String.new(:length => 5, :pad_char => 6)
181
- @str.value = "abc"
182
- @str.value.should == "abc\x06\x06"
157
+ str = BinData::String.new(:length => 5, :pad_char => 6)
158
+ str.assign("abc")
159
+ str.should == "abc\x06\x06"
183
160
  end
184
161
 
185
162
  it "should accept a character for :pad_char" do
186
- @str = BinData::String.new(:length => 5, :pad_char => "R")
187
- @str.value = "abc"
188
- @str.value.should == "abcRR"
163
+ str = BinData::String.new(:length => 5, :pad_char => "R")
164
+ str.assign("abc")
165
+ str.should == "abcRR"
189
166
  end
190
167
 
191
168
  it "should not accept a string for :pad_char" do
@@ -198,33 +175,33 @@ describe BinData::String, "with :trim_padding" do
198
175
  it "set false is the default" do
199
176
  str1 = BinData::String.new(:length => 5)
200
177
  str2 = BinData::String.new(:length => 5, :trim_padding => false)
201
- str1.value = "abc"
202
- str2.value = "abc"
203
- str1.value.should == "abc\0\0"
204
- str2.value.should == "abc\0\0"
205
- end
206
-
207
- it "should trim the value" do
208
- str = BinData::String.new(:pad_char => 'R', :trim_padding => true)
209
- str.value = "abcRR"
210
- str.value.should == "abc"
211
- end
212
-
213
- it "should not affect num_bytes" do
214
- str = BinData::String.new(:pad_char => 'R', :trim_padding => true)
215
- str.value = "abcRR"
216
- str.num_bytes.should == 5
217
- end
218
-
219
- it "should trim if last char is :pad_char" do
220
- str = BinData::String.new(:pad_char => 'R', :trim_padding => true)
221
- str.value = "abcRR"
222
- str.value.should == "abc"
223
- end
224
-
225
- it "should not trim if value contains :pad_char not at the end" do
226
- str = BinData::String.new(:pad_char => 'R', :trim_padding => true)
227
- str.value = "abcRRde"
228
- str.value.should == "abcRRde"
178
+ str1.assign("abc")
179
+ str2.assign("abc")
180
+ str1.should == "abc\0\0"
181
+ str2.should == "abc\0\0"
182
+ end
183
+
184
+ context "trim padding set" do
185
+ subject { BinData::String.new(:pad_char => 'R', :trim_padding => true) }
186
+
187
+ it "should trim the value" do
188
+ subject.assign("abcRR")
189
+ subject.should == "abc"
190
+ end
191
+
192
+ it "should not affect num_bytes" do
193
+ subject.assign("abcRR")
194
+ subject.num_bytes.should == 5
195
+ end
196
+
197
+ it "should trim if last char is :pad_char" do
198
+ subject.assign("abcRR")
199
+ subject.should == "abc"
200
+ end
201
+
202
+ it "should not trim if value contains :pad_char not at the end" do
203
+ subject.assign("abcRRde")
204
+ subject.should == "abcRRde"
205
+ end
229
206
  end
230
207
  end