bit-struct 0.15.0 → 0.16
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.
- checksums.yaml +4 -4
- data/History.txt +5 -1
- data/LICENSE +56 -0
- data/README.md +2 -2
- data/Rakefile +2 -2
- data/examples/field-ripper.rb +1 -1
- data/examples/ip.rb +6 -6
- data/examples/longlong.rb +2 -2
- data/examples/md.rb +1 -1
- data/examples/modular-def.rb +2 -2
- data/examples/native.rb +3 -3
- data/examples/ping.rb +1 -1
- data/examples/raw.rb +1 -1
- data/examples/switch-endian.rb +2 -2
- data/examples/vector.rb +2 -2
- data/lib/bit-struct.rb +0 -11
- data/lib/bit-struct/bit-struct.rb +54 -144
- data/lib/bit-struct/char-field.rb +3 -3
- data/lib/bit-struct/field.rb +94 -0
- data/lib/bit-struct/fields.rb +13 -13
- data/lib/bit-struct/float-field.rb +4 -4
- data/lib/bit-struct/hex-octet-field.rb +3 -3
- data/lib/bit-struct/nested-field.rb +8 -8
- data/lib/bit-struct/octet-field.rb +4 -4
- data/lib/bit-struct/signed-field.rb +23 -28
- data/lib/bit-struct/text-field.rb +2 -2
- data/lib/bit-struct/unsigned-field.rb +24 -27
- data/lib/bit-struct/vector-field.rb +7 -7
- data/lib/bit-struct/vector.rb +21 -21
- data/lib/bit-struct/yaml.rb +2 -2
- data/test/test-endian.rb +3 -3
- data/test/test-vector.rb +4 -4
- data/test/test.rb +49 -43
- metadata +47 -45
@@ -13,13 +13,13 @@ class BitStruct
|
|
13
13
|
"Bad offset, #{offset}, for #{self.class} #{name}." +
|
14
14
|
" Must be multiple of 8."
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
unless length % 8 == 0
|
18
18
|
raise ArgumentError,
|
19
19
|
"Bad length, #{length}, for #{self.class} #{name}." +
|
20
20
|
" Must be multiple of 8."
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
offset_byte = offset / 8
|
24
24
|
length_byte = length / 8
|
25
25
|
last_byte = offset_byte + length_byte - 1
|
@@ -6,21 +6,18 @@ class BitStruct
|
|
6
6
|
def self.class_name
|
7
7
|
@class_name ||= "unsigned"
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def add_accessors_to(cl, attr = name) # :nodoc:
|
11
11
|
offset_byte = offset / 8
|
12
12
|
offset_bit = offset % 8
|
13
|
-
|
13
|
+
|
14
14
|
length_bit = offset_bit + length
|
15
15
|
length_byte = (length_bit/8.0).ceil
|
16
16
|
last_byte = offset_byte + length_byte - 1
|
17
|
-
|
17
|
+
|
18
18
|
divisor = options[:fixed] || options["fixed"]
|
19
19
|
divisor_f = divisor && divisor.to_f
|
20
|
-
|
21
|
-
# raise ArgumentError, "fixed-point divisor must be a fixnum"
|
22
|
-
# end
|
23
|
-
|
20
|
+
|
24
21
|
endian = (options[:endian] || options["endian"]).to_s
|
25
22
|
case endian
|
26
23
|
when "native"
|
@@ -33,15 +30,15 @@ class BitStruct
|
|
33
30
|
raise ArgumentError,
|
34
31
|
"Unrecognized endian option: #{endian.inspect}"
|
35
32
|
end
|
36
|
-
|
33
|
+
|
37
34
|
data_is_big_endian =
|
38
35
|
([1234].pack(ctl) == [1234].pack(length_byte <= 2 ? "n" : "N"))
|
39
|
-
|
36
|
+
|
40
37
|
if length_byte == 1
|
41
38
|
rest = 8 - length_bit
|
42
39
|
mask = ["0"*offset_bit + "1"*length + "0"*rest].pack("B8")[0].ord
|
43
40
|
mask2 = ["1"*offset_bit + "0"*length + "1"*rest].pack("B8")[0].ord
|
44
|
-
|
41
|
+
|
45
42
|
cl.class_eval do
|
46
43
|
if divisor
|
47
44
|
define_method attr do ||
|
@@ -65,11 +62,11 @@ class BitStruct
|
|
65
62
|
end
|
66
63
|
end
|
67
64
|
end
|
68
|
-
|
65
|
+
|
69
66
|
elsif offset_bit == 0 and length % 8 == 0
|
70
67
|
field_length = length
|
71
68
|
byte_range = offset_byte..last_byte
|
72
|
-
|
69
|
+
|
73
70
|
cl.class_eval do
|
74
71
|
case field_length
|
75
72
|
when 8
|
@@ -82,7 +79,7 @@ class BitStruct
|
|
82
79
|
val = (val * divisor).round
|
83
80
|
self[offset_byte] = val
|
84
81
|
end
|
85
|
-
|
82
|
+
|
86
83
|
else
|
87
84
|
define_method attr do ||
|
88
85
|
self[offset_byte]
|
@@ -92,7 +89,7 @@ class BitStruct
|
|
92
89
|
self[offset_byte] = val
|
93
90
|
end
|
94
91
|
end
|
95
|
-
|
92
|
+
|
96
93
|
when 16, 32
|
97
94
|
if divisor
|
98
95
|
define_method attr do ||
|
@@ -103,7 +100,7 @@ class BitStruct
|
|
103
100
|
val = (val * divisor).round
|
104
101
|
self[byte_range] = [val].pack(ctl)
|
105
102
|
end
|
106
|
-
|
103
|
+
|
107
104
|
else
|
108
105
|
define_method attr do ||
|
109
106
|
self[byte_range].unpack(ctl).first
|
@@ -113,7 +110,7 @@ class BitStruct
|
|
113
110
|
self[byte_range] = [val].pack(ctl)
|
114
111
|
end
|
115
112
|
end
|
116
|
-
|
113
|
+
|
117
114
|
else
|
118
115
|
reader_helper = proc do |substr|
|
119
116
|
bytes = substr.unpack("C*")
|
@@ -122,7 +119,7 @@ class BitStruct
|
|
122
119
|
(sum << 8) + byte
|
123
120
|
end
|
124
121
|
end
|
125
|
-
|
122
|
+
|
126
123
|
writer_helper = proc do |val|
|
127
124
|
bytes = []
|
128
125
|
while val > 0
|
@@ -136,21 +133,21 @@ class BitStruct
|
|
136
133
|
bytes.reverse! if data_is_big_endian
|
137
134
|
bytes.pack("C*")
|
138
135
|
end
|
139
|
-
|
136
|
+
|
140
137
|
if divisor
|
141
138
|
define_method attr do ||
|
142
139
|
reader_helper[self[byte_range]] / divisor_f
|
143
140
|
end
|
144
|
-
|
141
|
+
|
145
142
|
define_method "#{attr}=" do |val|
|
146
143
|
self[byte_range] = writer_helper[(val * divisor).round]
|
147
144
|
end
|
148
|
-
|
145
|
+
|
149
146
|
else
|
150
147
|
define_method attr do ||
|
151
148
|
reader_helper[self[byte_range]]
|
152
149
|
end
|
153
|
-
|
150
|
+
|
154
151
|
define_method "#{attr}=" do |val|
|
155
152
|
self[byte_range] = writer_helper[val]
|
156
153
|
end
|
@@ -161,10 +158,10 @@ class BitStruct
|
|
161
158
|
elsif length_byte == 2 # unaligned field that fits within two whole bytes
|
162
159
|
byte_range = offset_byte..last_byte
|
163
160
|
rest = 16 - length_bit
|
164
|
-
|
161
|
+
|
165
162
|
mask = ["0"*offset_bit + "1"*length + "0"*rest]
|
166
163
|
mask = mask.pack("B16").unpack(ctl).first
|
167
|
-
|
164
|
+
|
168
165
|
mask2 = ["1"*offset_bit + "0"*length + "1"*rest]
|
169
166
|
mask2 = mask2.pack("B16").unpack(ctl).first
|
170
167
|
|
@@ -194,14 +191,14 @@ class BitStruct
|
|
194
191
|
end
|
195
192
|
end
|
196
193
|
end
|
197
|
-
|
194
|
+
|
198
195
|
elsif length_byte == 3 # unaligned field that fits within 3 whole bytes
|
199
196
|
byte_range = offset_byte..last_byte
|
200
197
|
rest = 32 - length_bit
|
201
|
-
|
198
|
+
|
202
199
|
mask = ["0"*offset_bit + "1"*length + "0"*rest]
|
203
200
|
mask = mask.pack("B32").unpack(ctl).first
|
204
|
-
|
201
|
+
|
205
202
|
mask2 = ["1"*offset_bit + "0"*length + "1"*rest]
|
206
203
|
mask2 = mask2.pack("B32").unpack(ctl).first
|
207
204
|
|
@@ -239,7 +236,7 @@ class BitStruct
|
|
239
236
|
end
|
240
237
|
end
|
241
238
|
end
|
242
|
-
|
239
|
+
|
243
240
|
else
|
244
241
|
raise "unsupported: #{inspect}"
|
245
242
|
end
|
@@ -8,12 +8,12 @@ class BitStruct
|
|
8
8
|
def self.class_name
|
9
9
|
@class_name ||= "vector"
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
# Used in describe.
|
13
13
|
def class_name
|
14
14
|
@class_name ||= vector_class.name[/\w+$/]
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
# Returns the subclass of Vector that is used to manage the value of this
|
18
18
|
# field. If the class was specified in the BitStruct.vector declaration,
|
19
19
|
# #vector_class will return it, otherwise it will be an anonymous class
|
@@ -39,20 +39,20 @@ class BitStruct
|
|
39
39
|
"Bad offset, #{offset}, for vector field #{name}." +
|
40
40
|
" Must be multiple of 8."
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
unless length % 8 == 0
|
44
44
|
raise ArgumentError,
|
45
45
|
"Bad length, #{length}, for vector field #{name}." +
|
46
46
|
" Must be multiple of 8."
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
offset_byte = offset / 8
|
50
50
|
length_byte = length / 8
|
51
51
|
last_byte = offset_byte + length_byte - 1
|
52
52
|
byte_range = offset_byte..last_byte
|
53
53
|
|
54
54
|
vc = vector_class
|
55
|
-
|
55
|
+
|
56
56
|
cl.class_eval do
|
57
57
|
define_method attr do ||
|
58
58
|
vc.new(self[byte_range])
|
@@ -63,12 +63,12 @@ class BitStruct
|
|
63
63
|
raise ArgumentError, "Size mismatch in vector field assignment " +
|
64
64
|
"to #{attr} with value #{val.inspect}"
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
if val.class != vc
|
68
68
|
warn "Type mismatch in vector field assignment " +
|
69
69
|
"to #{attr} with value #{val.inspect}"
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
self[byte_range] = val
|
73
73
|
end
|
74
74
|
end
|
data/lib/bit-struct/vector.rb
CHANGED
@@ -22,7 +22,7 @@ class BitStruct::Vector < String
|
|
22
22
|
@struct_class = nil
|
23
23
|
end
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Called as a class method with a single argument in a user-defined
|
27
27
|
# subclass to specify a particular BitStruct class to use for each entry,
|
28
28
|
# instead of generating an anonymous class. Called without arguments to
|
@@ -38,7 +38,7 @@ class BitStruct::Vector < String
|
|
38
38
|
@struct_class.default_options default_options
|
39
39
|
else
|
40
40
|
unless @struct_class
|
41
|
-
@struct_class = self == BitStruct::Vector ? BitStruct :
|
41
|
+
@struct_class = self == BitStruct::Vector ? BitStruct :
|
42
42
|
Class.new(superclass.struct_class)
|
43
43
|
@struct_class.default_options default_options
|
44
44
|
end
|
@@ -54,7 +54,7 @@ class BitStruct::Vector < String
|
|
54
54
|
def respond_to?(*m) # :nodoc:
|
55
55
|
orig_respond_to?(*m) || struct_class.respond_to?(*m)
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
# Get or set the hash of default options for the class, which apply to all
|
59
59
|
# fields in the entries. If +h+ is provided, update the default options
|
60
60
|
# with that hash. Default options are inherited.
|
@@ -70,7 +70,7 @@ class BitStruct::Vector < String
|
|
70
70
|
end
|
71
71
|
@default_options
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
def describe(*args)
|
75
75
|
fmt = args[0] || BitStruct.describe_format
|
76
76
|
if block_given?
|
@@ -81,37 +81,37 @@ class BitStruct::Vector < String
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
# Convenience method for instances. Returns the BitStruct class that
|
86
86
|
# describes each entry.
|
87
87
|
def struct_class
|
88
88
|
self.class.struct_class
|
89
89
|
end
|
90
|
-
|
91
|
-
# Convenience method for instances. Returns the string length in bytes of
|
90
|
+
|
91
|
+
# Convenience method for instances. Returns the string length in bytes of
|
92
92
|
# each entry in the vector.
|
93
93
|
def struct_class_length
|
94
94
|
self.class.struct_class.round_byte_length
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
# +arg+ can be an integer (number of entries) or a string
|
98
98
|
# (binary data, such as another Vector of the same size).
|
99
99
|
def initialize arg # :yields: instance
|
100
100
|
case arg
|
101
101
|
when Integer
|
102
102
|
super(struct_class.initial_value * arg)
|
103
|
-
|
103
|
+
|
104
104
|
else
|
105
105
|
begin
|
106
106
|
super arg
|
107
107
|
rescue NameError
|
108
108
|
raise ArgumentError, "must be string or integer: #{arg.inspect}"
|
109
109
|
end
|
110
|
-
end
|
110
|
+
end
|
111
111
|
|
112
112
|
yield self if block_given?
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
# Get the +i+-th entry. Returns a *copy* of the entry. If you want to
|
116
116
|
# use this copy to modify the entry, you must modify the copy and then
|
117
117
|
# use #[]= to replace the entry with the copy.
|
@@ -122,29 +122,29 @@ class BitStruct::Vector < String
|
|
122
122
|
unless (0...(length / entry_length)).include? i
|
123
123
|
raise ArgumentError, "index out of range: #{i}"
|
124
124
|
end
|
125
|
-
|
125
|
+
|
126
126
|
sc.new slice(entry_length * i, entry_length)
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
alias _old_replace_substr []=
|
130
130
|
|
131
131
|
# Set the +i+-th entry to +val+.
|
132
132
|
def []=(i,val)
|
133
133
|
entry_length = struct_class_length
|
134
|
-
|
134
|
+
|
135
135
|
unless (0...(length / entry_length)).include? i
|
136
136
|
raise ArgumentError, "index out of range: #{i}"
|
137
137
|
end
|
138
|
-
|
138
|
+
|
139
139
|
unless val.length == entry_length
|
140
140
|
raise ArgumentError, "wrong entry length: #{val.length} != #{entry_length}"
|
141
141
|
end
|
142
|
-
|
142
|
+
|
143
143
|
_old_replace_substr(entry_length * i, entry_length, val)
|
144
144
|
end
|
145
|
-
|
145
|
+
|
146
146
|
## TODO: [i..j] etc.
|
147
|
-
|
147
|
+
|
148
148
|
# Iterate over entries.
|
149
149
|
def each
|
150
150
|
entry_length = struct_class_length
|
@@ -152,7 +152,7 @@ class BitStruct::Vector < String
|
|
152
152
|
yield self[i]
|
153
153
|
end
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
def inspect_with_options(opts = BitStruct::DEFAULT_INSPECT_OPTS)
|
157
157
|
if opts[:include_class]
|
158
158
|
opts = opts.dup
|
@@ -161,14 +161,14 @@ class BitStruct::Vector < String
|
|
161
161
|
else
|
162
162
|
s = ""
|
163
163
|
end
|
164
|
-
|
164
|
+
|
165
165
|
s << entries.map{|entry| entry.inspect(opts)}.join(opts[:separator])
|
166
166
|
lb, rb = opts[:brackets]
|
167
167
|
[lb, s, rb].join
|
168
168
|
end
|
169
169
|
|
170
170
|
alias inspect inspect_with_options
|
171
|
-
|
171
|
+
|
172
172
|
def inspect_detailed
|
173
173
|
inspect(BitStruct::DETAILED_INSPECT_OPTS)
|
174
174
|
end
|
data/lib/bit-struct/yaml.rb
CHANGED
@@ -7,7 +7,7 @@ class BitStruct
|
|
7
7
|
end
|
8
8
|
|
9
9
|
YAML.add_ruby_type(/^bitstruct/) do |type, val|
|
10
|
-
|
10
|
+
_subtype, subclass = YAML.read_type_class(type, Object)
|
11
11
|
subclass.new(val)
|
12
12
|
end
|
13
13
|
|
@@ -74,7 +74,7 @@ class BitStruct
|
|
74
74
|
raise YAML::TypeError, "Invalid BitStruct: " + val.inspect
|
75
75
|
end
|
76
76
|
|
77
|
-
|
77
|
+
_bitstruct_name, bitstruct_type = YAML.read_type_class( tag, BitStruct )
|
78
78
|
|
79
79
|
st = bitstruct_type.new
|
80
80
|
|
data/test/test-endian.rb
CHANGED
@@ -8,21 +8,21 @@ class Test_Endian < Minitest::Test
|
|
8
8
|
unsigned :f_native, 32, :endian => :native
|
9
9
|
unsigned :f_network, 32, :endian => :network
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
attr_reader :bs
|
13
13
|
|
14
14
|
def setup
|
15
15
|
@bs = Endian.new
|
16
16
|
bs.f_big = bs.f_little = bs.f_native = bs.f_network = 0x01020304
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def test_readers
|
20
20
|
assert_equal(0x01020304, bs.f_big)
|
21
21
|
assert_equal(0x01020304, bs.f_little)
|
22
22
|
assert_equal(0x01020304, bs.f_native)
|
23
23
|
assert_equal(0x01020304, bs.f_network)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def test_writers
|
27
27
|
bs.fields.each do |field|
|
28
28
|
byte_offset = field.offset / 8
|
data/test/test-vector.rb
CHANGED
@@ -9,20 +9,20 @@ class Test_Vector < Minitest::Test
|
|
9
9
|
unsigned :x, 16
|
10
10
|
signed :y, 32
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
unsigned :other, 16, "other stuff"
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
attr_reader :pkt
|
17
17
|
|
18
18
|
def setup
|
19
19
|
@pkt = Packet.new
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def test_length
|
23
23
|
assert_equal(Packet.round_byte_length, pkt.length)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def test_writers
|
27
27
|
assert_equal(pkt.v[2].x, 0)
|
28
28
|
v = pkt.v
|
data/test/test.rb
CHANGED
@@ -10,18 +10,18 @@ class Test_BitStruct < Minitest::Test
|
|
10
10
|
class T2 < BitStruct
|
11
11
|
unsigned :bar, 8
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
class Rest < BitStruct
|
15
15
|
unsigned :zap, 8
|
16
16
|
rest :body, T2
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
class NestedPart < BitStruct
|
20
20
|
unsigned :x, 5
|
21
21
|
unsigned :y, 3, :default => 2
|
22
22
|
char :s, 5*8
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
class Container < BitStruct
|
26
26
|
nest :n1, NestedPart, :default => NestedPart.new(:x=>1, :s=>"deflt")
|
27
27
|
nest :n2, NestedPart
|
@@ -66,7 +66,7 @@ class Test_BitStruct < Minitest::Test
|
|
66
66
|
float next_name, 64, :format => "%10.5f"
|
67
67
|
|
68
68
|
octets next_name, 32, :default => "192.168.1.123"
|
69
|
-
|
69
|
+
|
70
70
|
hex_octets next_name, 48, :default => "ab:cd:ef:01:23:45"
|
71
71
|
|
72
72
|
unsigned next_name, 1
|
@@ -76,14 +76,14 @@ class Test_BitStruct < Minitest::Test
|
|
76
76
|
signed next_name, 7, :fixed => 1000 # unaligned!
|
77
77
|
|
78
78
|
char next_name, 24
|
79
|
-
|
79
|
+
|
80
80
|
rest :bs_body
|
81
|
-
|
81
|
+
|
82
82
|
INITIAL_VALUES = {
|
83
83
|
f1 => 1234,
|
84
84
|
f2 => 5678
|
85
85
|
}
|
86
|
-
|
86
|
+
|
87
87
|
INITIAL_VALUES.each do |f, v|
|
88
88
|
initial_value.send "#{f}=", v
|
89
89
|
end
|
@@ -106,11 +106,11 @@ class Test_BitStruct < Minitest::Test
|
|
106
106
|
unsigned next_name, 8
|
107
107
|
|
108
108
|
unsigned next_name, 1
|
109
|
-
|
109
|
+
|
110
110
|
rest :bs1_body
|
111
111
|
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
def setup
|
115
115
|
srand(767343)
|
116
116
|
@bs = BS.new
|
@@ -127,7 +127,7 @@ class Test_BitStruct < Minitest::Test
|
|
127
127
|
bs.fields.each do |field|
|
128
128
|
iv = initial_values && initial_values[field.name]
|
129
129
|
iv ||= field.default
|
130
|
-
|
130
|
+
|
131
131
|
if iv
|
132
132
|
case field
|
133
133
|
when BitStruct::FloatField
|
@@ -141,21 +141,21 @@ class Test_BitStruct < Minitest::Test
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
def test_init_with_value
|
146
146
|
randomize(@bs_1)
|
147
147
|
|
148
148
|
b = BS_1.new(@bs_1)
|
149
149
|
assert_equal(@bs_1, b, "Initialize with argument failed.")
|
150
|
-
|
150
|
+
|
151
151
|
c = BS_1.new(b)
|
152
152
|
assert_equal(@bs_1, c, "Initialize with argument failed.")
|
153
|
-
|
153
|
+
|
154
154
|
b1 = BS_1.new("")
|
155
155
|
b2 = BS_1.new(nil)
|
156
156
|
assert_equal(b1, b2, "Initialize with short argument failed.")
|
157
157
|
end
|
158
|
-
|
158
|
+
|
159
159
|
def test_init_with_hash
|
160
160
|
randomize(@bs_1)
|
161
161
|
|
@@ -167,25 +167,25 @@ class Test_BitStruct < Minitest::Test
|
|
167
167
|
b = BS_1.new(h)
|
168
168
|
assert_equal(@bs_1, b, "Initialize with argument failed.")
|
169
169
|
end
|
170
|
-
|
170
|
+
|
171
171
|
def test_join
|
172
172
|
assert_equal(@bs+@bs_1, BitStruct.join(@bs,@bs_1))
|
173
173
|
assert_equal(@bs+@bs_1, [@bs,@bs_1].join(""))
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
def test_parse
|
177
177
|
orig = @testers
|
178
178
|
orig.each do |bs|
|
179
179
|
randomize(bs)
|
180
180
|
end
|
181
|
-
|
181
|
+
|
182
182
|
data = BitStruct.join(orig)
|
183
183
|
round_trip = BitStruct.parse(data, orig.map{|bs|bs.class})
|
184
184
|
orig.zip(round_trip) do |bs1, bs2|
|
185
185
|
assert_equal(bs1, bs2)
|
186
186
|
end
|
187
187
|
end
|
188
|
-
|
188
|
+
|
189
189
|
def test_closed
|
190
190
|
assert_raises(BitStruct::ClosedClassError) do
|
191
191
|
BS.class_eval do
|
@@ -193,7 +193,7 @@ class Test_BitStruct < Minitest::Test
|
|
193
193
|
end
|
194
194
|
end
|
195
195
|
end
|
196
|
-
|
196
|
+
|
197
197
|
def test_rest
|
198
198
|
len0 = @bs_1.length
|
199
199
|
|
@@ -204,16 +204,16 @@ class Test_BitStruct < Minitest::Test
|
|
204
204
|
@bs_1.bs1_body = "b"*60
|
205
205
|
assert_equal("b"*60, @bs_1.bs1_body)
|
206
206
|
assert_equal(len0+60, @bs_1.length)
|
207
|
-
|
207
|
+
|
208
208
|
@bs_1.bs1_body = "c"*40
|
209
209
|
assert_equal("c"*40, @bs_1.bs1_body)
|
210
210
|
assert_equal(len0+40, @bs_1.length)
|
211
|
-
|
211
|
+
|
212
212
|
@bs_1.bs1_body = ""
|
213
213
|
assert_equal("", @bs_1.bs1_body)
|
214
214
|
assert_equal(len0, @bs_1.length)
|
215
215
|
end
|
216
|
-
|
216
|
+
|
217
217
|
def test_rest_with_class
|
218
218
|
r = Rest.new
|
219
219
|
t2 = T2.new
|
@@ -221,38 +221,44 @@ class Test_BitStruct < Minitest::Test
|
|
221
221
|
r.body = t2
|
222
222
|
assert_equal(123, r.body.bar)
|
223
223
|
end
|
224
|
-
|
224
|
+
|
225
|
+
def test_rest_with_class_constructed
|
226
|
+
r = Rest.new(['0011'].pack('H*'))
|
227
|
+
assert_equal(0x00, r.zap)
|
228
|
+
assert_equal(0x11, r.body.bar)
|
229
|
+
end
|
230
|
+
|
225
231
|
def test_nest
|
226
232
|
cont = Container.new
|
227
233
|
n1 = cont.n1
|
228
|
-
|
234
|
+
|
229
235
|
assert_equal(1, n1.x)
|
230
236
|
assert_equal(2, n1.y)
|
231
237
|
assert_equal("deflt", n1.s)
|
232
|
-
|
238
|
+
|
233
239
|
n1.sub(/./, " ")
|
234
240
|
|
235
241
|
assert_equal(1, n1.x)
|
236
242
|
assert_equal(2, n1.y)
|
237
243
|
assert_equal("deflt", n1.s)
|
238
|
-
|
244
|
+
|
239
245
|
n1 = cont.n1
|
240
246
|
n2 = cont.n2
|
241
|
-
|
247
|
+
|
242
248
|
assert_equal(0, n2.x)
|
243
249
|
assert_equal(2, n2.y)
|
244
250
|
assert_equal("\0"*5, n2.s)
|
245
|
-
|
251
|
+
|
246
252
|
n = NestedPart.new(:x=>4, :y=>1, :s=>"qwert")
|
247
253
|
cont.n1 = n
|
248
254
|
|
249
255
|
assert_equal(4, cont.n1.x)
|
250
256
|
assert_equal(1, cont.n1.y)
|
251
257
|
assert_equal("qwert", cont.n1.s)
|
252
|
-
|
258
|
+
|
253
259
|
assert_raises(ArgumentError) {cont.n2 = Container.new}
|
254
260
|
end
|
255
|
-
|
261
|
+
|
256
262
|
def test_overflow
|
257
263
|
ov = Overflow.new
|
258
264
|
empty = ov.dup
|
@@ -287,21 +293,21 @@ class Test_BitStruct < Minitest::Test
|
|
287
293
|
|
288
294
|
repeat_access_test(@bs_1, 10)
|
289
295
|
end
|
290
|
-
|
296
|
+
|
291
297
|
def test_initial_value
|
292
298
|
bs = @bs
|
293
299
|
bs.class::INITIAL_VALUES.each do |f,v|
|
294
300
|
assert_equal(v, bs.send(f), "In #{f} of a #{bs.class}")
|
295
301
|
end
|
296
302
|
end
|
297
|
-
|
303
|
+
|
298
304
|
def test_inherited_initial_value
|
299
305
|
bs = @bs_1
|
300
306
|
bs.class::INITIAL_VALUES.each do |f,v|
|
301
307
|
assert_equal(v, bs.send(f), "In #{f} of a #{bs.class}")
|
302
308
|
end
|
303
309
|
end
|
304
|
-
|
310
|
+
|
305
311
|
def test_to_h
|
306
312
|
h = @bs_1.to_h(:convert_keys => :to_s)
|
307
313
|
field_names = @bs_1.fields.map{|f|f.name.to_s}
|
@@ -310,7 +316,7 @@ class Test_BitStruct < Minitest::Test
|
|
310
316
|
assert_equal(@bs_1.send(name), h[name])
|
311
317
|
end
|
312
318
|
end
|
313
|
-
|
319
|
+
|
314
320
|
def test_to_a_exclude_rest
|
315
321
|
include_rest = false
|
316
322
|
a = @bs_1.to_a(include_rest)
|
@@ -331,7 +337,7 @@ class Test_BitStruct < Minitest::Test
|
|
331
337
|
assert_equal(@bs_1.send(name), a[i])
|
332
338
|
end
|
333
339
|
end
|
334
|
-
|
340
|
+
|
335
341
|
def test_format_option
|
336
342
|
formatted_fields = @bs.fields.select {|f|f.format}
|
337
343
|
formatted_fields.each do |f|
|
@@ -339,18 +345,18 @@ class Test_BitStruct < Minitest::Test
|
|
339
345
|
assert_equal(f.format % val, f.inspect_in_object(@bs, {}))
|
340
346
|
end
|
341
347
|
end
|
342
|
-
|
348
|
+
|
343
349
|
def test_yaml
|
344
350
|
assert_equal(@bs_1, YAML.load(@bs_1.to_yaml))
|
345
351
|
end
|
346
|
-
|
352
|
+
|
347
353
|
def test_field_by_name
|
348
354
|
name = :f007
|
349
355
|
f = @bs.field_by_name(name)
|
350
356
|
assert(f)
|
351
357
|
assert_equal(f.name, name)
|
352
358
|
end
|
353
|
-
|
359
|
+
|
354
360
|
#--------
|
355
361
|
def repeat_access_test(bs, n)
|
356
362
|
last_set_value = {}
|
@@ -371,7 +377,7 @@ class Test_BitStruct < Minitest::Test
|
|
371
377
|
begin
|
372
378
|
assert_equal(lsv2, bs.send(f2.name))
|
373
379
|
rescue Test::Unit::AssertionFailedError => ex
|
374
|
-
msg =
|
380
|
+
msg =
|
375
381
|
"In #{f2.inspect} after setting #{field.inspect} to" +
|
376
382
|
" #{last_set_value[field].inspect}"
|
377
383
|
raise ex, msg + "\n" + ex.message, ex.backtrace
|
@@ -386,7 +392,7 @@ class Test_BitStruct < Minitest::Test
|
|
386
392
|
|
387
393
|
assert_equal(start_length, finish_length, "Length differs after test!")
|
388
394
|
end
|
389
|
-
|
395
|
+
|
390
396
|
def randomize(bs)
|
391
397
|
bs.fields.each do |f|
|
392
398
|
randomize_field(bs, f)
|
@@ -432,13 +438,13 @@ class Test_BitStruct < Minitest::Test
|
|
432
438
|
value = s * (field.length/8)
|
433
439
|
bs.send "#{field.name}=", value
|
434
440
|
last_set_value = value
|
435
|
-
|
441
|
+
|
436
442
|
when BitStruct::TextField
|
437
443
|
s = (rand(64)+32).chr
|
438
444
|
value = s * rand(field.length*2/8)
|
439
445
|
bs.send "#{field.name}=", value
|
440
446
|
last_set_value = s * [field.length/8, value.length].min
|
441
|
-
|
447
|
+
|
442
448
|
when BitStruct::FloatField
|
443
449
|
value = rand(2**30)
|
444
450
|
bs.send "#{field.name}=", value
|
@@ -446,7 +452,7 @@ class Test_BitStruct < Minitest::Test
|
|
446
452
|
|
447
453
|
else raise
|
448
454
|
end
|
449
|
-
|
455
|
+
|
450
456
|
return last_set_value
|
451
457
|
end
|
452
458
|
end
|