bindata 0.9.0 → 0.9.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.
- data/ChangeLog +9 -3
- data/README +10 -0
- data/examples/gzip.rb +32 -45
- data/lib/bindata.rb +2 -1
- data/lib/bindata/array.rb +51 -51
- data/lib/bindata/base.rb +69 -39
- data/lib/bindata/bits.rb +807 -0
- data/lib/bindata/choice.rb +3 -3
- data/lib/bindata/float.rb +2 -2
- data/lib/bindata/int.rb +5 -5
- data/lib/bindata/io.rb +192 -0
- data/lib/bindata/rest.rb +1 -1
- data/lib/bindata/single.rb +42 -53
- data/lib/bindata/string.rb +1 -1
- data/lib/bindata/stringz.rb +1 -1
- data/lib/bindata/struct.rb +45 -37
- data/spec/array_spec.rb +37 -0
- data/spec/base_spec.rb +34 -17
- data/spec/bits_spec.rb +139 -0
- data/spec/io_spec.rb +288 -0
- data/spec/single_spec.rb +4 -3
- data/spec/string_spec.rb +2 -1
- data/spec/struct_spec.rb +25 -0
- metadata +6 -2
data/spec/array_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require File.expand_path(File.dirname(__FILE__)) + '/spec_common'
|
4
4
|
require 'bindata/array'
|
5
|
+
require 'bindata/bits'
|
5
6
|
require 'bindata/int'
|
6
7
|
require 'bindata/struct'
|
7
8
|
|
@@ -266,3 +267,39 @@ describe BinData::Array, "with :read_until containing +array+ and +index+" do
|
|
266
267
|
@data.length.should == 7
|
267
268
|
end
|
268
269
|
end
|
270
|
+
|
271
|
+
describe BinData::Array, "of bits" do
|
272
|
+
before(:each) do
|
273
|
+
@data = BinData::Array.new(:type => :bit1, :initial_length => 15)
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should read" do
|
277
|
+
str = [0b0001_0100, 0b1000_1000].pack("CC")
|
278
|
+
@data.read(str)
|
279
|
+
@data[0].should == 0
|
280
|
+
@data[1].should == 0
|
281
|
+
@data[2].should == 0
|
282
|
+
@data[3].should == 1
|
283
|
+
@data[4].should == 0
|
284
|
+
@data[5].should == 1
|
285
|
+
@data[6].should == 0
|
286
|
+
@data[7].should == 0
|
287
|
+
@data[8].should == 1
|
288
|
+
@data[9].should == 0
|
289
|
+
@data[10].should == 0
|
290
|
+
@data[11].should == 0
|
291
|
+
@data[12].should == 1
|
292
|
+
@data[13].should == 0
|
293
|
+
@data[14].should == 0
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should write" do
|
297
|
+
@data[3] = 1
|
298
|
+
@data.to_s.should == [0b0001_0000, 0b0000_0000].pack("CC")
|
299
|
+
end
|
300
|
+
|
301
|
+
it "should return num_bytes" do
|
302
|
+
@data.num_bytes.should == 2
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
data/spec/base_spec.rb
CHANGED
@@ -5,13 +5,13 @@ require 'bindata/base'
|
|
5
5
|
|
6
6
|
class BaseStub < BinData::Base
|
7
7
|
def clear; end
|
8
|
-
def _do_read(io) end
|
9
|
-
def done_read; end
|
10
|
-
def _write(io) end
|
11
|
-
def _num_bytes; end
|
12
|
-
def snapshot; end
|
13
8
|
def single_value?; end
|
14
9
|
def field_names; end
|
10
|
+
def snapshot; end
|
11
|
+
def done_read; end
|
12
|
+
def _do_read(io) end
|
13
|
+
def _do_write(io) end
|
14
|
+
def _do_num_bytes; end
|
15
15
|
end
|
16
16
|
|
17
17
|
describe BinData::Base, "with mandatory parameters" do
|
@@ -142,7 +142,7 @@ describe BinData::Base, "with :check_offset" do
|
|
142
142
|
class TenByteOffsetBase < BaseStub
|
143
143
|
def do_read(io)
|
144
144
|
# advance the io position before checking offset
|
145
|
-
io.
|
145
|
+
io.seekbytes(10)
|
146
146
|
super(io)
|
147
147
|
end
|
148
148
|
end
|
@@ -184,7 +184,7 @@ describe BinData::Base, "with :adjust_offset" do
|
|
184
184
|
class TenByteAdjustingOffsetBase < BaseStub
|
185
185
|
def do_read(io)
|
186
186
|
# advance the io position before checking offset
|
187
|
-
io.
|
187
|
+
io.seekbytes(10)
|
188
188
|
super(io)
|
189
189
|
end
|
190
190
|
end
|
@@ -226,8 +226,8 @@ describe BinData::Base, "with :readwrite => false" do
|
|
226
226
|
class NoIOBase < BaseStub
|
227
227
|
attr_accessor :mock
|
228
228
|
def _do_read(io) mock._do_read(io); end
|
229
|
-
def
|
230
|
-
def
|
229
|
+
def _do_write(io) mock._do_write(io); end
|
230
|
+
def _do_num_bytes; mock._do_num_bytes; end
|
231
231
|
end
|
232
232
|
END
|
233
233
|
end
|
@@ -250,16 +250,33 @@ describe BinData::Base, "with :readwrite => false" do
|
|
250
250
|
end
|
251
251
|
|
252
252
|
it "should have zero num_bytes" do
|
253
|
-
@obj.mock.should_not_receive(:
|
253
|
+
@obj.mock.should_not_receive(:_do_num_bytes)
|
254
254
|
@obj.num_bytes.should be_zero
|
255
255
|
end
|
256
256
|
end
|
257
257
|
|
258
|
+
describe BinData::Base, "with :onlyif" do
|
259
|
+
before(:all) do
|
260
|
+
eval <<-END
|
261
|
+
class OnlyIfBase < BinData::Base
|
262
|
+
public :has_param?, :param
|
263
|
+
end
|
264
|
+
END
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should alias to :readwrite" do
|
268
|
+
obj = OnlyIfBase.new(:onlyif => "a")
|
269
|
+
obj.should_not have_param(:onlyif)
|
270
|
+
obj.should have_param(:readwrite)
|
271
|
+
obj.param(:readwrite).should == "a"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
258
275
|
describe BinData::Base, "when subclassing" do
|
259
276
|
before(:all) do
|
260
277
|
eval <<-END
|
261
278
|
class SubClassOfBase < BinData::Base
|
262
|
-
public :_do_read, :
|
279
|
+
public :_do_read, :_do_write, :_do_num_bytes
|
263
280
|
end
|
264
281
|
END
|
265
282
|
end
|
@@ -273,13 +290,13 @@ describe BinData::Base, "when subclassing" do
|
|
273
290
|
SubClassOfBase.all_possible_field_names(nil)
|
274
291
|
}.should raise_error(NotImplementedError)
|
275
292
|
lambda { @obj.clear }.should raise_error(NotImplementedError)
|
276
|
-
lambda { @obj._do_read(nil) }.should raise_error(NotImplementedError)
|
277
|
-
lambda { @obj.done_read }.should raise_error(NotImplementedError)
|
278
|
-
lambda { @obj._write(nil) }.should raise_error(NotImplementedError)
|
279
|
-
lambda { @obj._num_bytes }.should raise_error(NotImplementedError)
|
280
|
-
lambda { @obj.snapshot }.should raise_error(NotImplementedError)
|
281
293
|
lambda { @obj.single_value? }.should raise_error(NotImplementedError)
|
282
294
|
lambda { @obj.field_names }.should raise_error(NotImplementedError)
|
295
|
+
lambda { @obj.snapshot }.should raise_error(NotImplementedError)
|
296
|
+
lambda { @obj.done_read }.should raise_error(NotImplementedError)
|
297
|
+
lambda { @obj._do_read(nil) }.should raise_error(NotImplementedError)
|
298
|
+
lambda { @obj._do_write(nil) }.should raise_error(NotImplementedError)
|
299
|
+
lambda { @obj._do_num_bytes }.should raise_error(NotImplementedError)
|
283
300
|
end
|
284
301
|
end
|
285
302
|
|
@@ -323,7 +340,7 @@ describe BinData::Base do
|
|
323
340
|
eval <<-END
|
324
341
|
class InstanceOfBase < BaseStub
|
325
342
|
def snapshot; 123; end
|
326
|
-
def
|
343
|
+
def _do_write(io); io.writebytes('456'); end
|
327
344
|
end
|
328
345
|
END
|
329
346
|
end
|
data/spec/bits_spec.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__)) + '/spec_common'
|
4
|
+
require 'bindata/bits'
|
5
|
+
|
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
|
11
|
+
|
12
|
+
obj = BinData::Bit1le.new
|
13
|
+
obj.value = true
|
14
|
+
obj.value.should == 1
|
15
|
+
end
|
16
|
+
|
17
|
+
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
|
25
|
+
end
|
26
|
+
|
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
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "All bitfields" do
|
39
|
+
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
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
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
|
61
|
+
|
62
|
+
obj.value = -1
|
63
|
+
obj.value.should == 0
|
64
|
+
|
65
|
+
obj.value = 1 << nbits
|
66
|
+
obj.value.should == ((1 << nbits) - 1)
|
67
|
+
end
|
68
|
+
|
69
|
+
nbits += 1
|
70
|
+
end
|
71
|
+
rescue NameError
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
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
|
81
|
+
|
82
|
+
str = [0b1000_0000].pack("C") + "\000" * (nbits / 8)
|
83
|
+
obj.read(str)
|
84
|
+
obj.value.should == 1 << (nbits - 1)
|
85
|
+
|
86
|
+
nbits += 1
|
87
|
+
end
|
88
|
+
rescue NameError
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
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
|
102
|
+
|
103
|
+
nbits += 1
|
104
|
+
end
|
105
|
+
rescue NameError
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
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
|
+
value.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
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/spec/io_spec.rb
ADDED
@@ -0,0 +1,288 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__)) + '/spec_common'
|
4
|
+
require 'bindata/io'
|
5
|
+
|
6
|
+
describe BinData::IO do
|
7
|
+
it "should wrap strings in StringIO" do
|
8
|
+
io = BinData::IO.new("abcd")
|
9
|
+
io.raw_io.class.should == StringIO
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not wrap IO objects" do
|
13
|
+
stream = StringIO.new
|
14
|
+
io = BinData::IO.new(stream)
|
15
|
+
io.raw_io.should == stream
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise error when io is BinData::IO" do
|
19
|
+
lambda {
|
20
|
+
io = BinData::IO.new(BinData::IO.new(""))
|
21
|
+
}.should raise_error(ArgumentError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return correct offset" do
|
25
|
+
stream = StringIO.new("abcdefghij")
|
26
|
+
stream.seek(3, IO::SEEK_CUR)
|
27
|
+
|
28
|
+
io = BinData::IO.new(stream)
|
29
|
+
io.offset.should == 0
|
30
|
+
io.readbytes(4)
|
31
|
+
io.offset.should == 4
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should seek" do
|
35
|
+
stream = StringIO.new("abcdefghij")
|
36
|
+
io = BinData::IO.new(stream)
|
37
|
+
|
38
|
+
io.seekbytes(2)
|
39
|
+
io.readbytes(4).should == "cdef"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should raise error when reading at eof" do
|
43
|
+
stream = StringIO.new("abcdefghij")
|
44
|
+
io = BinData::IO.new(stream)
|
45
|
+
io.seekbytes(10)
|
46
|
+
lambda {
|
47
|
+
io.readbytes(3)
|
48
|
+
}.should raise_error(EOFError)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should raise error on short reads" do
|
52
|
+
stream = StringIO.new("abcdefghij")
|
53
|
+
io = BinData::IO.new(stream)
|
54
|
+
lambda {
|
55
|
+
io.readbytes(20)
|
56
|
+
}.should raise_error(IOError)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should write" do
|
60
|
+
stream = StringIO.new
|
61
|
+
io = BinData::IO.new(stream)
|
62
|
+
io.writebytes("abcd")
|
63
|
+
|
64
|
+
stream.rewind
|
65
|
+
stream.read.should == "abcd"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe BinData::IO, "reading bits in big endian" do
|
70
|
+
before(:each) do
|
71
|
+
@b1 = 0b1111_1010
|
72
|
+
@b2 = 0b1100_1110
|
73
|
+
@b3 = 0b0110_1010
|
74
|
+
str = [@b1, @b2, @b3].pack("CCC")
|
75
|
+
@io = BinData::IO.new(str)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should read a bitfield less than 1 byte" do
|
79
|
+
@io.readbits(3).should == 0b111
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should read a bitfield more than 1 byte" do
|
83
|
+
@io.readbits(10).should == 0b1111_1010_11
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should read a bitfield more than 2 bytes" do
|
87
|
+
@io.readbits(17).should == 0b1111_1010_1100_1110_0
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should read two bitfields totalling less than 1 byte" do
|
91
|
+
@io.readbits(5).should == 0b1111_1
|
92
|
+
@io.readbits(2).should == 0b01
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should read two bitfields totalling more than 1 byte" do
|
96
|
+
@io.readbits(6).should == 0b1111_10
|
97
|
+
@io.readbits(8).should == 0b10_1100_11
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should read two bitfields totalling more than 2 bytes" do
|
101
|
+
@io.readbits(7).should == 0b1111_101
|
102
|
+
@io.readbits(12).should == 0b0_1100_1110_011
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should ignore unused bits when reading bytes" do
|
106
|
+
@io.readbits(3).should == 0b111
|
107
|
+
@io.readbytes(1).should == [@b2].pack("C")
|
108
|
+
@io.readbits(2).should == 0b01
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe BinData::IO, "reading bits in little endian" do
|
113
|
+
before(:each) do
|
114
|
+
@b1 = 0b1111_1010
|
115
|
+
@b2 = 0b1100_1110
|
116
|
+
@b3 = 0b0110_1010
|
117
|
+
str = [@b1, @b2, @b3].pack("CCC")
|
118
|
+
@io = BinData::IO.new(str)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should read a bitfield less than 1 byte" do
|
122
|
+
@io.readbits(3, :little).should == 0b010
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should read a bitfield more than 1 byte" do
|
126
|
+
@io.readbits(10, :little).should == 0b10_1111_1010
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should read a bitfield more than 2 bytes" do
|
130
|
+
@io.readbits(17, :little).should == 0b0_1100_1110_1111_1010
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should read two bitfields totalling less than 1 byte" do
|
134
|
+
@io.readbits(5, :little).should == 0b1_1010
|
135
|
+
@io.readbits(2, :little).should == 0b11
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should read two bitfields totalling more than 1 byte" do
|
139
|
+
@io.readbits(6, :little).should == 0b11_1010
|
140
|
+
@io.readbits(8, :little).should == 0b00_1110_11
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should read two bitfields totalling more than 2 bytes" do
|
144
|
+
@io.readbits(7, :little).should == 0b111_1010
|
145
|
+
@io.readbits(12, :little).should == 0b010_1100_1110_1
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should ignore unused bits when reading bytes" do
|
149
|
+
@io.readbits(3, :little).should == 0b010
|
150
|
+
@io.readbytes(1).should == [@b2].pack("C")
|
151
|
+
@io.readbits(2, :little).should == 0b10
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class BitWriterHelper
|
156
|
+
def initialize
|
157
|
+
@stringio = StringIO.new
|
158
|
+
@io = BinData::IO.new(@stringio)
|
159
|
+
end
|
160
|
+
|
161
|
+
def writebits(val, nbits, endian = :big)
|
162
|
+
@io.writebits(val, nbits, endian)
|
163
|
+
end
|
164
|
+
|
165
|
+
def writebytes(val)
|
166
|
+
@io.writebytes(val)
|
167
|
+
end
|
168
|
+
|
169
|
+
def value
|
170
|
+
@io.flushbits
|
171
|
+
@stringio.rewind
|
172
|
+
@stringio.read
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe BinData::IO, "writing bits in big endian" do
|
177
|
+
before(:each) do
|
178
|
+
@io = BitWriterHelper.new
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should write a bitfield less than 1 byte" do
|
182
|
+
@io.writebits(0b010, 3)
|
183
|
+
@io.value.should == [0b0100_0000].pack("C")
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should write a bitfield more than 1 byte" do
|
187
|
+
@io.writebits(0b10_1001_1101, 10)
|
188
|
+
@io.value.should == [0b1010_0111, 0b0100_0000].pack("CC")
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should write a bitfield more than 2 bytes" do
|
192
|
+
@io.writebits(0b101_1000_0010_1001_1101, 19)
|
193
|
+
@io.value.should == [0b1011_0000, 0b0101_0011, 0b1010_0000].pack("CCC")
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should write two bitfields totalling less than 1 byte" do
|
197
|
+
@io.writebits(0b1_1001, 5)
|
198
|
+
@io.writebits(0b00, 2)
|
199
|
+
@io.value.should == [0b1100_1000].pack("C")
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should write two bitfields totalling more than 1 byte" do
|
203
|
+
@io.writebits(0b01_0101, 6)
|
204
|
+
@io.writebits(0b001_1001, 7)
|
205
|
+
@io.value.should == [0b0101_0100, 0b1100_1000].pack("CC")
|
206
|
+
end
|
207
|
+
|
208
|
+
it "should write two bitfields totalling more than 2 bytes" do
|
209
|
+
@io.writebits(0b01_0111, 6)
|
210
|
+
@io.writebits(0b1_0010_1001_1001, 13)
|
211
|
+
@io.value.should == [0b0101_1110, 0b0101_0011, 0b0010_0000].pack("CCC")
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should pad unused bits when writing bytes" do
|
215
|
+
@io.writebits(0b101, 3)
|
216
|
+
@io.writebytes([0b1011_1111].pack("C"))
|
217
|
+
@io.writebits(0b01, 2)
|
218
|
+
|
219
|
+
@io.value.should == [0b1010_0000, 0b1011_1111, 0b0100_0000].pack("CCC")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe BinData::IO, "writing bits in little endian" do
|
224
|
+
before(:each) do
|
225
|
+
@io = BitWriterHelper.new
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should write a bitfield less than 1 byte" do
|
229
|
+
@io.writebits(0b010, 3, :little)
|
230
|
+
@io.value.should == [0b0000_0010].pack("C")
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should write a bitfield more than 1 byte" do
|
234
|
+
@io.writebits(0b10_1001_1101, 10, :little)
|
235
|
+
@io.value.should == [0b1001_1101, 0b0000_0010].pack("CC")
|
236
|
+
end
|
237
|
+
|
238
|
+
it "should write a bitfield more than 2 bytes" do
|
239
|
+
@io.writebits(0b101_1000_0010_1001_1101, 19, :little)
|
240
|
+
@io.value.should == [0b1001_1101, 0b1000_0010, 0b0000_0101].pack("CCC")
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should write two bitfields totalling less than 1 byte" do
|
244
|
+
@io.writebits(0b1_1001, 5, :little)
|
245
|
+
@io.writebits(0b00, 2, :little)
|
246
|
+
@io.value.should == [0b0001_1001].pack("C")
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should write two bitfields totalling more than 1 byte" do
|
250
|
+
@io.writebits(0b01_0101, 6, :little)
|
251
|
+
@io.writebits(0b001_1001, 7, :little)
|
252
|
+
@io.value.should == [0b0101_0101, 0b0000_0110].pack("CC")
|
253
|
+
end
|
254
|
+
|
255
|
+
it "should write two bitfields totalling more than 2 bytes" do
|
256
|
+
@io.writebits(0b01_0111, 6, :little)
|
257
|
+
@io.writebits(0b1_0010_1001_1001, 13, :little)
|
258
|
+
@io.value.should == [0b0101_0111, 0b1010_0110, 0b0000_0100].pack("CCC")
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should pad unused bits when writing bytes" do
|
262
|
+
@io.writebits(0b101, 3, :little)
|
263
|
+
@io.writebytes([0b1011_1111].pack("C"))
|
264
|
+
@io.writebits(0b01, 2, :little)
|
265
|
+
|
266
|
+
@io.value.should == [0b0000_0101, 0b1011_1111, 0b0000_0001].pack("CCC")
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
describe BinData::IO, "with changing endian" do
|
271
|
+
it "should not mix different endianess when reading" do
|
272
|
+
b1 = 0b0110_1010
|
273
|
+
b2 = 0b1110_0010
|
274
|
+
str = [b1, b2].pack("CC")
|
275
|
+
io = BinData::IO.new(str)
|
276
|
+
|
277
|
+
io.readbits(3, :big).should == 0b011
|
278
|
+
io.readbits(4, :little).should == 0b0010
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should not mix different endianess when writing" do
|
282
|
+
io = BitWriterHelper.new
|
283
|
+
io.writebits(0b110, 3, :big)
|
284
|
+
io.writebits(0b010, 3, :little)
|
285
|
+
io.value.should == [0b1100_0000, 0b0000_0010].pack("CC")
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|