bindata 0.9.3 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (47) hide show
  1. data/ChangeLog +18 -0
  2. data/NEWS +59 -0
  3. data/README +22 -23
  4. data/TODO +18 -12
  5. data/examples/gzip.rb +4 -4
  6. data/lib/bindata.rb +4 -3
  7. data/lib/bindata/array.rb +202 -132
  8. data/lib/bindata/base.rb +147 -166
  9. data/lib/bindata/{single.rb → base_primitive.rb} +82 -56
  10. data/lib/bindata/bits.rb +31 -770
  11. data/lib/bindata/choice.rb +157 -82
  12. data/lib/bindata/float.rb +25 -27
  13. data/lib/bindata/int.rb +144 -177
  14. data/lib/bindata/io.rb +59 -49
  15. data/lib/bindata/lazy.rb +80 -50
  16. data/lib/bindata/params.rb +134 -26
  17. data/lib/bindata/{single_value.rb → primitive.rb} +71 -64
  18. data/lib/bindata/{multi_value.rb → record.rb} +52 -70
  19. data/lib/bindata/registry.rb +49 -17
  20. data/lib/bindata/rest.rb +6 -10
  21. data/lib/bindata/sanitize.rb +55 -70
  22. data/lib/bindata/string.rb +60 -42
  23. data/lib/bindata/stringz.rb +34 -35
  24. data/lib/bindata/struct.rb +197 -152
  25. data/lib/bindata/trace.rb +35 -0
  26. data/spec/array_spec.rb +128 -112
  27. data/spec/{single_spec.rb → base_primitive_spec.rb} +102 -61
  28. data/spec/base_spec.rb +190 -185
  29. data/spec/bits_spec.rb +126 -98
  30. data/spec/choice_spec.rb +89 -98
  31. data/spec/example.rb +19 -0
  32. data/spec/float_spec.rb +28 -44
  33. data/spec/int_spec.rb +217 -127
  34. data/spec/io_spec.rb +41 -24
  35. data/spec/lazy_spec.rb +95 -49
  36. data/spec/primitive_spec.rb +191 -0
  37. data/spec/{multi_value_spec.rb → record_spec.rb} +124 -89
  38. data/spec/registry_spec.rb +53 -12
  39. data/spec/rest_spec.rb +2 -3
  40. data/spec/sanitize_spec.rb +47 -73
  41. data/spec/spec_common.rb +13 -1
  42. data/spec/string_spec.rb +34 -23
  43. data/spec/stringz_spec.rb +10 -18
  44. data/spec/struct_spec.rb +91 -63
  45. data/spec/system_spec.rb +291 -0
  46. metadata +12 -8
  47. data/spec/single_value_spec.rb +0 -131
data/spec/bits_spec.rb CHANGED
@@ -4,136 +4,164 @@ require File.expand_path(File.dirname(__FILE__)) + '/spec_common'
4
4
  require 'bindata/bits'
5
5
 
6
6
  describe "Bits of size 1" do
7
- it "should accept true as value" do
8
- obj = BinData::Bit1.new
9
- obj.value = true
10
- obj.value.should == 1
7
+ before(:each) do
8
+ @bit_classes = [BinData::Bit1, BinData::Bit1le]
9
+ end
11
10
 
12
- obj = BinData::Bit1le.new
13
- obj.value = true
14
- obj.value.should == 1
11
+ it "should accept true as value" do
12
+ @bit_classes.each do |bit_class|
13
+ obj = bit_class.new
14
+ obj.value = true
15
+ obj.value.should == 1
16
+ end
15
17
  end
16
18
 
17
19
  it "should accept false as value" do
18
- obj = BinData::Bit1.new
19
- obj.value = false
20
- obj.value.should == 0
21
-
22
- obj = BinData::Bit1le.new
23
- obj.value = false
24
- obj.value.should == 0
20
+ @bit_classes.each do |bit_class|
21
+ obj = bit_class.new
22
+ obj.value = false
23
+ obj.value.should == 0
24
+ end
25
25
  end
26
26
 
27
27
  it "should accept nil as value" do
28
- obj = BinData::Bit1.new
29
- obj.value = nil
30
- obj.value.should == 0
31
-
32
- obj = BinData::Bit1le.new
33
- obj.value = nil
34
- obj.value.should == 0
28
+ @bit_classes.each do |bit_class|
29
+ obj = bit_class.new
30
+ obj.value = nil
31
+ obj.value.should == 0
32
+ end
35
33
  end
36
34
  end
37
35
 
38
- describe "All bitfields" do
36
+ share_examples_for "All bitfields" do
37
+
39
38
  it "should have a sensible value of zero" do
40
- begin
41
- nbits = 1
42
- loop do
43
- ["", "le"].each do |suffix|
44
- klass = BinData.const_get("Bit#{nbits}#{suffix}")
45
- klass.new.value.should be_zero
46
- end
47
-
48
- nbits += 1
49
- end
50
- rescue NameError
39
+ all_classes do |bit_class|
40
+ bit_class.new.value.should be_zero
41
+ end
42
+ end
43
+
44
+ it "should avoid underflow" do
45
+ all_classes do |bit_class|
46
+ obj = bit_class.new
47
+
48
+ obj.value = min_value - 1
49
+ obj.value.should == min_value
51
50
  end
52
51
  end
53
52
 
54
- it "should clamp " do
55
- begin
56
- nbits = 1
57
- loop do
58
- ["", "le"].each do |suffix|
59
- klass = BinData.const_get("Bit#{nbits}#{suffix}")
60
- obj = klass.new
53
+ it "should avoid overflow" do
54
+ all_classes do |bit_class|
55
+ obj = bit_class.new
61
56
 
62
- obj.value = -1
63
- obj.value.should == 0
57
+ obj.value = max_value + 1
58
+ obj.value.should == max_value
59
+ end
60
+ end
64
61
 
65
- obj.value = 1 << nbits
66
- obj.value.should == ((1 << nbits) - 1)
67
- end
62
+ it "should assign values" do
63
+ all_classes do |bit_class|
64
+ some_values_within_range.each do |val|
65
+ obj = bit_class.new
66
+ obj.assign(val)
68
67
 
69
- nbits += 1
68
+ obj.value.should == val
70
69
  end
71
- rescue NameError
72
70
  end
73
71
  end
74
72
 
75
- it "should read big endian value" do
76
- begin
77
- nbits = 1
78
- loop do
79
- klass = BinData.const_get("Bit#{nbits}")
80
- obj = klass.new
73
+ it "should assign values from other bit objects" do
74
+ all_classes do |bit_class|
75
+ some_values_within_range.each do |val|
76
+ src = bit_class.new
77
+ src.assign(val)
81
78
 
82
- str = [0b1000_0000].pack("C") + "\000" * (nbits / 8)
83
- obj.read(str)
84
- obj.value.should == 1 << (nbits - 1)
79
+ obj = bit_class.new
80
+ obj.assign(src)
85
81
 
86
- nbits += 1
82
+ obj.value.should == val
87
83
  end
88
- rescue NameError
89
84
  end
90
85
  end
91
86
 
92
- it "should read little endian value" do
93
- begin
94
- nbits = 1
95
- loop do
96
- klass = BinData.const_get("Bit#{nbits}le")
97
- obj = klass.new
98
-
99
- str = [0b0000_0001].pack("C") + "\000" * (nbits / 8)
100
- obj.read(str)
101
- obj.value.should == 1
87
+ it "should have symmetric #read and #write" do
88
+ all_classes do |bit_class|
89
+ some_values_within_range.each do |val|
90
+ obj = bit_class.new
91
+ obj.value = val
102
92
 
103
- nbits += 1
93
+ written = obj.to_binary_s
94
+ bit_class.read(written).should == val
104
95
  end
105
- rescue NameError
106
96
  end
107
97
  end
108
98
 
109
- it "should read written values" do
110
- begin
111
- nbits = 1
112
- loop do
113
- ["", "le"].each do |suffix|
114
- klass = BinData.const_get("Bit#{nbits}#{suffix}")
115
-
116
- min = 0
117
- max = (1 << nbits) - 1
118
- range = (min .. max)
119
-
120
- values = []
121
- values << (min + 1) if range.include?(min + 1)
122
- values << (min + 3) if range.include?(min + 3)
123
- values << (max - 1) if range.include?(max - 1)
124
-
125
- values.each do |val|
126
- obj = klass.new
127
- obj.value = val
128
- str = obj.to_s
129
- obj.read(str)
130
- obj.value.should == val
131
- end
132
- end
133
-
134
- nbits += 1
135
- end
136
- rescue NameError
99
+ def all_classes(&block)
100
+ @bits.each_pair do |bit_class, nbits|
101
+ @nbits = nbits
102
+ yield bit_class
103
+ end
104
+ end
105
+
106
+ def min_value
107
+ 0
108
+ end
109
+
110
+ def max_value
111
+ (1 << @nbits) - 1
112
+ end
113
+
114
+ def some_values_within_range
115
+ lo = min_value + 1
116
+ mid = (min_value + max_value) / 2
117
+ hi = max_value - 1
118
+
119
+ [lo, mid, hi].find_all { |v| (min_value .. max_value).include?(v) }
120
+ end
121
+ end
122
+
123
+ describe "Big endian bitfields" do
124
+ it_should_behave_like "All bitfields"
125
+
126
+ before(:all) do
127
+ @bits = {}
128
+ (1 .. 63).each do |nbits|
129
+ bit_class = BinData.const_get("Bit#{nbits}")
130
+ @bits[bit_class] = nbits
131
+ end
132
+ end
133
+
134
+ it "should read big endian value" do
135
+ @bits.each_pair do |bit_class, nbits|
136
+ obj = bit_class.new
137
+
138
+ nbytes = (nbits + 7) / 8
139
+ str = [0b1000_0000].pack("C") + "\000" * (nbytes - 1)
140
+ obj.read(str)
141
+ obj.value.should == 1 << (nbits - 1)
142
+ end
143
+ end
144
+ end
145
+
146
+ describe "Little endian bitfields" do
147
+ it_should_behave_like "All bitfields"
148
+
149
+ before(:all) do
150
+ @bits = {}
151
+ (1 .. 63).each do |nbits|
152
+ bit_class = BinData.const_get("Bit#{nbits}le")
153
+ @bits[bit_class] = nbits
154
+ end
155
+ end
156
+
157
+ it "should read little endian value" do
158
+ @bits.each_pair do |bit_class, nbits|
159
+ obj = bit_class.new
160
+
161
+ nbytes = (nbits + 7) / 8
162
+ str = [0b0000_0001].pack("C") + "\000" * (nbytes - 1)
163
+ obj.read(str)
164
+ obj.value.should == 1
137
165
  end
138
166
  end
139
167
  end
data/spec/choice_spec.rb CHANGED
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require File.expand_path(File.dirname(__FILE__)) + '/spec_common'
4
+ require File.expand_path(File.dirname(__FILE__)) + '/example'
4
5
  require 'bindata/choice'
5
- require 'bindata/int'
6
- require 'bindata/lazy'
7
- require 'bindata/struct'
8
6
 
9
7
  class Chooser
10
8
  attr_accessor :choice
@@ -31,42 +29,35 @@ describe BinData::Choice, "when instantiating" do
31
29
  end
32
30
 
33
31
  it "should fail if :choices Hash has a symbol as key" do
34
- args = {:choices => {:a => :int8}, :selection => 0}
32
+ args = {:choices => {:a => :example_single}, :selection => 0}
35
33
  lambda { BinData::Choice.new(args) }.should raise_error(ArgumentError)
36
34
  end
37
35
 
38
36
  it "should fail if :choices Hash has a nil key" do
39
- args = {:choices => {nil => :int8}, :selection => 0}
37
+ args = {:choices => {nil => :example_single}, :selection => 0}
40
38
  lambda { BinData::Choice.new(args) }.should raise_error(ArgumentError)
41
39
  end
42
40
  end
43
41
 
44
- describe BinData::Choice, "with choices array" do
45
- before(:each) do
46
- chooser = Chooser.new
47
- @data = BinData::Choice.new(:choices => [[:int8, {:value => 3}],
48
- [:int16le, {:value => 5}],
49
- [:int32le, {:value => 7}]],
50
- :selection => lambda { chooser.choice } )
51
- @chooser = chooser
42
+ share_examples_for "Choice initialized with array or hash" do
43
+ it "should be able to select the choice" do
44
+ @chooser.choice = 3
45
+ @data.value.should == 30
52
46
  end
53
47
 
54
- it "should be able to select the choice" do
55
- @chooser.choice = 0
56
- @data.selection.should == 0
57
- @data.value.should == 3
48
+ it "should show the current selection" do
49
+ @chooser.choice = 3
50
+ @data.selection.should == 3
51
+ end
58
52
 
59
- @chooser.choice = 1
60
- @data.selection.should == 1
61
- @data.value.should == 5
53
+ it "should be able to change the choice" do
54
+ @chooser.choice = 3
62
55
 
63
- @chooser.choice = 2
64
- @data.selection.should == 2
65
- @data.value.should == 7
56
+ @chooser.choice = 7
57
+ @data.value.should == 70
66
58
  end
67
59
 
68
- it "should handle :selection returning nil" do
69
- @chooser.choice = nil
60
+ it "should fail if no choice has been set" do
70
61
  lambda { @data.value }.should raise_error(IndexError)
71
62
  end
72
63
 
@@ -75,8 +66,13 @@ describe BinData::Choice, "with choices array" do
75
66
  lambda { @data.value }.should raise_error(IndexError)
76
67
  end
77
68
 
69
+ it "should not be able to select a nil choice" do
70
+ @chooser.choice = 1
71
+ lambda { @data.value }.should raise_error(IndexError)
72
+ end
73
+
78
74
  it "should handle missing methods correctly" do
79
- @chooser.choice = 0
75
+ @chooser.choice = 3
80
76
 
81
77
  @data.should respond_to(:value)
82
78
  @data.should_not respond_to(:does_not_exist)
@@ -84,125 +80,120 @@ describe BinData::Choice, "with choices array" do
84
80
  end
85
81
 
86
82
  it "should delegate methods to the selected single choice" do
87
- @chooser.choice = 1
83
+ @chooser.choice = 5
88
84
 
89
- @data.num_bytes.should == 2
85
+ @data.num_bytes.should == ExampleSingle.new.num_bytes
90
86
  end
91
87
  end
92
88
 
93
89
  describe BinData::Choice, "with sparse choices array" do
90
+ it_should_behave_like "Choice initialized with array or hash"
91
+
94
92
  before(:each) do
95
93
  chooser = Chooser.new
96
94
  @data = BinData::Choice.new(:choices => [nil, nil, nil,
97
- [:int8, {:value => 3}],
95
+ [:example_single, {:value => 30}],
98
96
  nil,
99
- [:int16le, {:value => 5}],
97
+ [:example_single, {:value => 50}],
100
98
  nil,
101
- [:int32le, {:value => 7}]],
99
+ [:example_single, {:value => 70}]],
102
100
  :selection => lambda { chooser.choice } )
103
101
  @chooser = chooser
104
102
  end
103
+ end
105
104
 
106
- it "should be able to select the choice" do
107
- @chooser.choice = 3
108
- @data.selection.should == 3
109
- @data.value.should == 3
110
-
111
- @chooser.choice = 7
112
- @data.selection.should == 7
113
- @data.value.should == 7
114
- end
115
-
116
- it "should not be able to select an invalid choice" do
117
- @chooser.choice = 99
118
- lambda { @data.value }.should raise_error(IndexError)
119
- end
105
+ describe BinData::Choice, "with choices hash" do
106
+ it_should_behave_like "Choice initialized with array or hash"
120
107
 
121
- it "should not be able to select a nil choice" do
122
- @chooser.choice = 1
123
- lambda { @data.value }.should raise_error(IndexError)
108
+ before(:each) do
109
+ chooser = Chooser.new
110
+ @data = BinData::Choice.new(:choices => {3 => [:example_single, {:value => 30}],
111
+ 5 => [:example_single, {:value => 50}],
112
+ 7 => [:example_single, {:value => 70}]},
113
+ :selection => lambda { chooser.choice } )
114
+ @chooser = chooser
124
115
  end
125
116
  end
126
117
 
127
- describe BinData::Choice, "with choices hash" do
118
+ describe BinData::Choice, "with single values" do
128
119
  before(:each) do
129
120
  chooser = Chooser.new
130
- @data = BinData::Choice.new(:choices => {3 => [:int8, {:value => 3}],
131
- 5 => [:int16le, {:value => 5}],
132
- 7 => [:int32le, {:value => 7}]},
121
+ @data = BinData::Choice.new(:choices => {3 => :example_single,
122
+ 5 => :example_single,
123
+ 7 => :example_single,},
133
124
  :selection => lambda { chooser.choice } )
134
125
  @chooser = chooser
135
126
  end
136
127
 
137
- it "should be able to select the choice" do
128
+ it "should assign raw values" do
138
129
  @chooser.choice = 3
139
- @data.value.should == 3
140
- @data.selection.should == 3
130
+ @data.value = 254
131
+ @data.value.should == 254
132
+ end
141
133
 
142
- @chooser.choice = 7
143
- @data.value.should == 7
144
- @data.selection.should == 7
134
+ it "should assign Single values" do
135
+ obj = ExampleSingle.new
136
+ obj.value = 11
137
+
138
+ @chooser.choice = 3
139
+ @data.value = obj
140
+ @data.value.should == 11
145
141
  end
146
142
 
147
- it "should not be able to select an invalid choice" do
148
- @chooser.choice = 99
149
- lambda { @data.value }.should raise_error(IndexError)
143
+ it "should clear" do
144
+ @chooser.choice = 3
145
+ @data.value = 254
146
+
147
+ @data.clear
148
+ @data.value.should be_zero
150
149
  end
151
- end
152
150
 
153
- describe BinData::Choice, "with single values" do
154
- before(:each) do
155
- chooser = Chooser.new
156
- @data = BinData::Choice.new(:choices => {3 => :uint8,
157
- 5 => :uint16le,
158
- 7 => :uint32le,},
159
- :selection => lambda { chooser.choice } )
160
- @chooser = chooser
151
+ it "should be clear on initialisation" do
152
+ @chooser.choice = 3
153
+
154
+ @data.should be_clear
161
155
  end
162
156
 
163
- it "should copy value when changing selection" do
157
+ it "should not be clear after assignment" do
164
158
  @chooser.choice = 3
165
159
  @data.value = 254
166
160
 
167
- @data.to_s.should == "\xfe"
161
+ @data.should_not be_clear
162
+ end
168
163
 
169
- @chooser.choice = 5
170
- @data.to_s.should == "\xfe\x00"
164
+ it "should not copy value when changing selection" do
165
+ @chooser.choice = 3
166
+ @data.value = 254
171
167
 
172
168
  @chooser.choice = 7
173
- @data.to_s.should == "\xfe\x00\x00\x00"
169
+ @data.value.should_not == 254
170
+ end
171
+
172
+ it "should behave as value" do
173
+ @chooser.choice = 3
174
+ @data.value = 5
175
+
176
+ (@data + 1).should == 6
177
+ (1 + @data).should == 6
174
178
  end
175
179
  end
176
180
 
177
- describe BinData::Choice, "with multi values" do
181
+ describe BinData::Choice, "with copy_on_change => true" do
178
182
  before(:each) do
179
183
  chooser = Chooser.new
180
- @data = BinData::Choice.new(:choices =>
181
- {3 => [:struct, {:fields => [[:int8, :a]]}],
182
- 5 => [:struct, {:fields => [[:int8, :a]]}]},
183
- :selection => lambda { chooser.choice } )
184
+ @data = BinData::Choice.new(:choices => {3 => :example_single,
185
+ 5 => :example_single,
186
+ 7 => :example_single,},
187
+ :selection => lambda { chooser.choice },
188
+ :copy_on_change => true)
184
189
  @chooser = chooser
185
190
  end
186
191
 
187
- it "should access fields" do
188
- @chooser.choice = 3
189
- @data.a = 5
190
- @data.a.should == 5
191
- end
192
-
193
- it "should not copy values when changing fields" do
194
- @chooser.choice = 3
195
- @data.a = 5
196
- @data.a.should == 5
197
-
198
- @chooser.choice = 5
199
- @data.a = 17
200
- @data.a.should == 17
201
-
192
+ it "should copy value when changing selection" do
202
193
  @chooser.choice = 3
203
- @data.a.should == 5
194
+ @data.value = 254
204
195
 
205
- @chooser.choice = 5
206
- @data.a.should == 17
196
+ @chooser.choice = 7
197
+ @data.value.should == 254
207
198
  end
208
199
  end