binary_parser 1.0.0
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +239 -0
- data/Rakefile +11 -0
- data/binary_parser.gemspec +33 -0
- data/lib/binary_parser.rb +50 -0
- data/lib/binary_parser/version.rb +3 -0
- data/lib/built_in_template/binary.rb +12 -0
- data/lib/built_in_template/flag.rb +22 -0
- data/lib/built_in_template/uint.rb +9 -0
- data/lib/error.rb +21 -0
- data/lib/general_class/abstract_binary.rb +68 -0
- data/lib/general_class/bit_position.rb +22 -0
- data/lib/general_class/condition.rb +11 -0
- data/lib/general_class/expression.rb +66 -0
- data/lib/loop_list.rb +52 -0
- data/lib/nameless_template.rb +7 -0
- data/lib/scope.rb +87 -0
- data/lib/stream_template_base.rb +129 -0
- data/lib/structure_definition.rb +131 -0
- data/lib/template_base.rb +120 -0
- data/unit_test/general_class/test_abstract_binary.rb +60 -0
- data/unit_test/general_class/test_bit_position.rb +22 -0
- data/unit_test/general_class/test_condition.rb +23 -0
- data/unit_test/general_class/test_expression.rb +22 -0
- data/unit_test/test_scope.rb +191 -0
- data/unit_test/test_stream_template_base.rb +232 -0
- data/unit_test/test_structure_definition.rb +115 -0
- data/unit_test/test_template_base.rb +62 -0
- metadata +108 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
module BinaryParser
|
2
|
+
class StructureDefinition
|
3
|
+
|
4
|
+
DataDefinition = Struct.new(:bit_position, :bit_length, :conditions, :klass)
|
5
|
+
LoopDefinition = Struct.new(:bit_position, :bit_length, :conditions, :structure)
|
6
|
+
|
7
|
+
attr_reader :parent_structure, :bit_at, :names
|
8
|
+
|
9
|
+
def initialize(method_names=[], parent_structure=nil, &init_proc)
|
10
|
+
@method_names = method_names
|
11
|
+
@parent_structure = parent_structure
|
12
|
+
@bit_at = BitPosition.new
|
13
|
+
@data_def, @var = {}, {}
|
14
|
+
@conditions, @names = [], []
|
15
|
+
instance_eval(&init_proc) if init_proc
|
16
|
+
end
|
17
|
+
|
18
|
+
def data(name, klass, bit_length)
|
19
|
+
check_new_def_name(name)
|
20
|
+
unless klass.ancestors.include?(TemplateBase)
|
21
|
+
raise DefinitionError, "Class #{klass} should be TemplateBase."
|
22
|
+
end
|
23
|
+
bit_at, bit_length = process_bit_length(bit_length, name)
|
24
|
+
@data_def[name] = DataDefinition.new(bit_at, bit_length, @conditions.dup, klass)
|
25
|
+
@names << name
|
26
|
+
end
|
27
|
+
|
28
|
+
def SPEND(bit_length, name, &block)
|
29
|
+
check_new_def_name(name)
|
30
|
+
bit_at, bit_length = process_bit_length(bit_length, name)
|
31
|
+
used_method_names = NamelessTemplate.instance_methods + Scope.instance_methods
|
32
|
+
structure = StructureDefinition.new(used_method_names, self, &block)
|
33
|
+
@data_def[name] = LoopDefinition.new(bit_at, bit_length, @conditions.dup, structure)
|
34
|
+
@names << name
|
35
|
+
end
|
36
|
+
|
37
|
+
def TIMES(times, name, &block)
|
38
|
+
check_new_def_name(name)
|
39
|
+
structure = StructureDefinition.new(Scope.instance_methods, self, &block)
|
40
|
+
if structure.bit_at.names.empty?
|
41
|
+
bit_at, bit_length = process_bit_length(times * structure.bit_at.imm, name)
|
42
|
+
@data_def[name] = LoopDefinition.new(bit_at, bit_length, @conditions.dup, structure)
|
43
|
+
else
|
44
|
+
bit_length = Expression.new([0])
|
45
|
+
structure.bit_at.names.each do |bit_at_depending_name|
|
46
|
+
depending_length_exp = structure[bit_at_depending_name].bit_length
|
47
|
+
depending_length_exp.variables.each do |var_name|
|
48
|
+
if structure[var_name]
|
49
|
+
raise DefinitionError, "In '#{name}', same level variable #{var_name} is referenced." +
|
50
|
+
"*** TIMES's inner structure's bit-length must be always same." +
|
51
|
+
"In other words, that bit-length must not rely on same level variables. ***"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
bit_length += depending_length_exp
|
55
|
+
end
|
56
|
+
bit_at, bit_length = process_bit_length(bit_length * times, name)
|
57
|
+
@data_def[name] = LoopDefinition.new(bit_at, bit_length, @conditions.dup, structure)
|
58
|
+
end
|
59
|
+
@names << name
|
60
|
+
end
|
61
|
+
|
62
|
+
def IF(condition, &block)
|
63
|
+
@conditions.push(condition)
|
64
|
+
block.call
|
65
|
+
@conditions.pop
|
66
|
+
end
|
67
|
+
|
68
|
+
def check_new_def_name(name)
|
69
|
+
if name[0..1] == "__"
|
70
|
+
raise DefinitionError, "Name that starts with '__' is system-reserved."
|
71
|
+
end
|
72
|
+
if @method_names.include?(name)
|
73
|
+
raise DefinitionError, "Name '#{name}' is already used as method name." +
|
74
|
+
"You should chanege to other name."
|
75
|
+
end
|
76
|
+
if @data_def[name]
|
77
|
+
raise DefinitionError, "Name #{name} is already defined." +
|
78
|
+
"You should change to other name."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def name_solvable?(name, structure=self)
|
83
|
+
return structure[name] ||
|
84
|
+
(structure.parent_structure && name_solvable?(name, structure.parent_structure))
|
85
|
+
end
|
86
|
+
|
87
|
+
def cond(*var_names, &condition_proc)
|
88
|
+
unless var_names.all?{|name| name_solvable?(name)}
|
89
|
+
raise DefinitionError, "As condition variable, unsolvable variable #{symbol} is used."
|
90
|
+
end
|
91
|
+
return Condition.new(*var_names, &condition_proc)
|
92
|
+
end
|
93
|
+
|
94
|
+
def var(name)
|
95
|
+
return @var[name] ||= Expression.new([name])
|
96
|
+
end
|
97
|
+
|
98
|
+
def rest
|
99
|
+
return var(:__rest)
|
100
|
+
end
|
101
|
+
|
102
|
+
def [](name)
|
103
|
+
return @data_def[name]
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def process_bit_length(bit_length, name)
|
109
|
+
bit_at = @bit_at
|
110
|
+
case bit_length
|
111
|
+
when Integer
|
112
|
+
if @conditions.empty?
|
113
|
+
@bit_at = @bit_at.add_imm(bit_length)
|
114
|
+
else
|
115
|
+
@bit_at = @bit_at.add_name(name)
|
116
|
+
end
|
117
|
+
return bit_at, Expression.new([bit_length])
|
118
|
+
when Expression
|
119
|
+
bit_length.variables.reject{|s| s[0..1] == "__"}.each do |symbol|
|
120
|
+
unless name_solvable?(symbol)
|
121
|
+
raise DefinitionError, "In #{name}, unsolvable variable #{symbol} is used."
|
122
|
+
end
|
123
|
+
end
|
124
|
+
@bit_at = @bit_at.add_name(name)
|
125
|
+
return bit_at, bit_length
|
126
|
+
else
|
127
|
+
raise DefinitionError, "Unknown type of bit_length (#{bit_length.class})."
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module BinaryParser
|
2
|
+
class TemplateBase
|
3
|
+
include BuiltInTemplate
|
4
|
+
|
5
|
+
def self.def_structure(&definition_proc)
|
6
|
+
used_method_names = self.instance_methods + Scope.instance_methods
|
7
|
+
@structure_def = StructureDefinition.new(used_method_names, &definition_proc)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.Def(&definition_proc) def_structure(&definition_proc) end
|
11
|
+
|
12
|
+
def self.structure
|
13
|
+
return @structure_def ||= StructureDefinition.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(binary)
|
17
|
+
@scope = Scope.new(self.class.structure, convert_into_abstract_binary(binary))
|
18
|
+
end
|
19
|
+
|
20
|
+
def convert_into_abstract_binary(object)
|
21
|
+
return object if object.is_a?(AbstractBinary)
|
22
|
+
if object.is_a?(String) && object.encoding == Encoding::BINARY
|
23
|
+
return AbstractBinary.new(object)
|
24
|
+
end
|
25
|
+
raise BadManipulationError, "Argument should be AbstractBinary or BINAY String."
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(name, *args)
|
29
|
+
return @scope.method_missing(name, *args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](name)
|
33
|
+
return @scope.method_missing(name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def names
|
37
|
+
return @scope.names
|
38
|
+
end
|
39
|
+
|
40
|
+
# Convert held binary into unsigned integer.
|
41
|
+
# Special case:
|
42
|
+
# If held binary's length is 0, this method throws BadBinaryManipulationError.
|
43
|
+
def to_i
|
44
|
+
@scope.abstract_binary.to_i
|
45
|
+
end
|
46
|
+
|
47
|
+
# Convert held binary into string encoded in Encoding::BINARY.
|
48
|
+
# Special case:
|
49
|
+
# If held binary's length or start position isn't a multiple of 8,
|
50
|
+
# this method throws BadBinaryManipulationError.
|
51
|
+
def to_s
|
52
|
+
@scope.abstract_binary.to_s
|
53
|
+
end
|
54
|
+
|
55
|
+
# Convert held binary into character-numbers.
|
56
|
+
# Example: If held binary is "ABC" in ascii, this returns [0x41, 0x42, 0x43].
|
57
|
+
# Special case:
|
58
|
+
# If held binary's length or start position isn't a multiple of 8,
|
59
|
+
# this method throws BadBinaryManipulationError.
|
60
|
+
def to_chars
|
61
|
+
@scope.abstract_binary.to_chars
|
62
|
+
end
|
63
|
+
|
64
|
+
# Real length(bit) of held binary
|
65
|
+
def binary_bit_length
|
66
|
+
@scope.abstract_binary.bit_length
|
67
|
+
end
|
68
|
+
|
69
|
+
# Structure-specified length(bit) of binary.
|
70
|
+
# Special case:
|
71
|
+
# If held binary's length is too short to calculate structure-specified length,
|
72
|
+
# this method throws ParsingError.
|
73
|
+
def structure_bit_length
|
74
|
+
@scope.eval_entire_bit_length
|
75
|
+
end
|
76
|
+
|
77
|
+
# Whether real length of held binary is NOT smaller than structure-specified length of binary.
|
78
|
+
# Special case:
|
79
|
+
# If held binary's length is too short to calculate structure-specified length,
|
80
|
+
# this method throws ParsingError.
|
81
|
+
def hold_enough_binary?
|
82
|
+
structure_bit_length <= binary_bit_length
|
83
|
+
end
|
84
|
+
|
85
|
+
# Whether real length of held binary is equal to structure-specified length of binary.
|
86
|
+
# Special case:
|
87
|
+
# If held binary's length is too short to calculate structure-specified length,
|
88
|
+
# this method throws ParsingError.
|
89
|
+
def hold_just_binary?
|
90
|
+
structure_bit_length == binary_bit_length
|
91
|
+
end
|
92
|
+
|
93
|
+
# String that describes this object.
|
94
|
+
# * If you want to print some of this content-description in 'show' method,
|
95
|
+
# override this method.
|
96
|
+
def content_description
|
97
|
+
""
|
98
|
+
end
|
99
|
+
|
100
|
+
# Print all elements' information.
|
101
|
+
# Args:
|
102
|
+
# recursively => Whether print recursively or not. Default is false.
|
103
|
+
# out => Print target. Default is STDOUT.
|
104
|
+
def show(recursively=false, out=STDOUT, depth=0)
|
105
|
+
max_name_length = names.inject(5){|max_len, name| [max_len, name.length].max}
|
106
|
+
if names.size > 0
|
107
|
+
out.puts "#{" " * (depth*2)}*#{"-" * 80}"
|
108
|
+
end
|
109
|
+
names.each do |name|
|
110
|
+
out.puts sprintf("#{" " * (depth*2)}%-#{max_name_length}s Pos: %6s Len: %6s Type: %10s Cont: %s",
|
111
|
+
name.to_s,
|
112
|
+
@scope.eval_bit_position(name),
|
113
|
+
@scope.eval_bit_length(name),
|
114
|
+
self[name].class.name.split("::").last,
|
115
|
+
self[name] ? self[name].content_description : "Nil")
|
116
|
+
self[name].show(true, out, depth + 1) if recursively && self[name]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/general_class/abstract_binary.rb'
|
10
|
+
|
11
|
+
class AbstractBinaryTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_to_i
|
14
|
+
abin = AbstractBinary.new(gen_bin(0b10101010, 0b01010101))
|
15
|
+
assert_equal(0b1010101001010101, abin.to_i)
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_to_chars
|
19
|
+
abin = AbstractBinary.new(gen_bin(0b10101010, 0b01010101))
|
20
|
+
assert_equal(0b10101010, abin.to_chars[0])
|
21
|
+
assert_equal(0b01010101, abin.to_chars[1])
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_to_s
|
25
|
+
abin = AbstractBinary.new(gen_bin(0x48, 0x4f, 0x47, 0x45))
|
26
|
+
assert_equal("HOGE", abin.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_sub
|
30
|
+
abin = AbstractBinary.new(gen_bin(0b11110000, 0b11110000, 0b11110001))
|
31
|
+
assert_equal(0b110, abin.sub(:bit_index => 2, :bit_length => 3).to_i)
|
32
|
+
assert_equal([0b11110000, 0b11110001], abin.sub(:bit_index => 6).sub(:bit_index => 2).to_chars)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_to_chars_error
|
36
|
+
abin = AbstractBinary.new(gen_bin(0b11110000, 0b11111111))
|
37
|
+
sub = abin.sub(:bit_index => 4, :bit_length => 8)
|
38
|
+
assert_equal(0b00001111, sub.to_i)
|
39
|
+
assert_raise(BadBinaryManipulationError) do
|
40
|
+
sub.to_chars
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_sub_error
|
45
|
+
abin = AbstractBinary.new(gen_bin(0b11110000, 0b11111111))
|
46
|
+
assert_raise(BadBinaryManipulationError) do
|
47
|
+
abin.sub(:bit_index => 16)
|
48
|
+
end
|
49
|
+
assert_raise(BadBinaryManipulationError) do
|
50
|
+
abin.sub(:bit_length => 17)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# helper for generating binary
|
55
|
+
def gen_bin(*chars)
|
56
|
+
return chars.pack("C*")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/general_class/bit_position.rb'
|
10
|
+
|
11
|
+
class BitPositionTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
VAL = {:hoge => 10, :fuga => 1000}
|
14
|
+
|
15
|
+
def test_bit_position
|
16
|
+
bp = BitPosition.new
|
17
|
+
pos = bp.add_imm(4).add_name(:hoge).add_imm(3).add_name(:fuga).eval{|name| VAL[name]}
|
18
|
+
assert_equal(1017, pos)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/general_class/condition.rb'
|
10
|
+
|
11
|
+
class ConditionTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
VAL = {:hoge => 10, :fuga => 1000}
|
14
|
+
|
15
|
+
def test_condition
|
16
|
+
cond1 = Condition.new(:hoge, :fuga){|v1, v2| v1 * 100 == v2}
|
17
|
+
cond2 = Condition.new(:hoge, :fuga){|v1, v2| v1 * 10 == v2}
|
18
|
+
assert_equal(true, cond1.eval{|name| VAL[name]})
|
19
|
+
assert_equal(false, cond2.eval{|name| VAL[name]})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.dirname(File.expand_path(File.dirname(__FILE__))))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/general_class/expression.rb'
|
10
|
+
|
11
|
+
class ExpressionTest < Test::Unit::TestCase
|
12
|
+
VAL = {:hoge => 10, :fuga => 1000}
|
13
|
+
|
14
|
+
def test_expression
|
15
|
+
var_exp1 = Expression.new([:hoge])
|
16
|
+
var_exp2 = Expression.new([:fuga])
|
17
|
+
exp = (var_exp1 + 3) * 12 + var_exp2 / 10 - 4
|
18
|
+
assert_equal((10 + 3) * 12 + 1000 / 10 - 4, exp.eval{|name| VAL[name]})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$LIBRARY_ROOT_PATH = File.dirname(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
module BinaryParser
|
5
|
+
module UnitTest
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
# load testing target
|
9
|
+
require $LIBRARY_ROOT_PATH + '/lib/binary_parser.rb'
|
10
|
+
|
11
|
+
class ScopeTest < Test::Unit::TestCase
|
12
|
+
|
13
|
+
# TEST CASE STRUCTURE 1
|
14
|
+
# * roughly test various
|
15
|
+
class ST1 < TemplateBase
|
16
|
+
Def do
|
17
|
+
data :cond_num, UInt, 8
|
18
|
+
IF cond(:cond_num){|v| v.to_i == 1} do
|
19
|
+
data :length, UInt, 8
|
20
|
+
data :data, Binary, var(:length) * 8
|
21
|
+
end
|
22
|
+
|
23
|
+
data :binary_len, UInt, 8
|
24
|
+
SPEND var(:binary_len) * 8, :list do
|
25
|
+
data :length, UInt, 8
|
26
|
+
data :data, Binary, var(:length) * 8
|
27
|
+
end
|
28
|
+
|
29
|
+
data :foot, UInt, 32
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_ST1_CASE1
|
34
|
+
bin = gen_bin(*[0x01, [0x04, [0x48, 0x4f, 0x47, 0x45]],
|
35
|
+
0x06, [0x1, [0x70], 0x3, [0x69, 0x79, 0x6f]],
|
36
|
+
0xff, 0xff, 0xff, 0xff].flatten)
|
37
|
+
|
38
|
+
sc = ST1.new(bin)
|
39
|
+
|
40
|
+
assert_equal(1, sc.cond_num.to_i)
|
41
|
+
assert_equal(4, sc.length.to_i)
|
42
|
+
assert_equal("HOGE", sc.data.to_s)
|
43
|
+
|
44
|
+
assert_equal(6, sc.binary_len.to_i)
|
45
|
+
assert_equal(2, sc.list.size)
|
46
|
+
assert_equal("p", sc.list[0].data.to_s)
|
47
|
+
assert_equal("iyo", sc.list[1].data.to_s)
|
48
|
+
|
49
|
+
assert_equal(0xffffffff, sc.foot.to_i)
|
50
|
+
end
|
51
|
+
|
52
|
+
# TEST CASE STRUCTURE 2
|
53
|
+
# * about IF
|
54
|
+
class ST2 < TemplateBase
|
55
|
+
Def do
|
56
|
+
data :number1, UInt, 8
|
57
|
+
IF cond(:number1){|v| v.to_i == 1} do
|
58
|
+
data :number2, UInt, 8
|
59
|
+
IF cond(:number2){|v| v.to_i == 2} do
|
60
|
+
data :number3, UInt, var(:number2) * 4
|
61
|
+
end
|
62
|
+
end
|
63
|
+
data :number4, UInt, 8
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_ST2_CASE1
|
68
|
+
bin = gen_bin(1, 2, 3, 4)
|
69
|
+
i = ST2.new(bin)
|
70
|
+
|
71
|
+
assert_equal(1, i.number1.to_i)
|
72
|
+
assert_equal(2, i.number2.to_i)
|
73
|
+
assert_equal(3, i.number3.to_i)
|
74
|
+
assert_equal(4, i.number4.to_i)
|
75
|
+
assert(i.hold_just_binary?)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_ST2_CASE2
|
79
|
+
bin = gen_bin(1, 0, 4)
|
80
|
+
i = ST2.new(bin)
|
81
|
+
|
82
|
+
assert_equal(1, i.number1.to_i)
|
83
|
+
assert_equal(0, i.number2.to_i)
|
84
|
+
assert_equal(nil, i.number3)
|
85
|
+
assert_equal(4, i.number4.to_i)
|
86
|
+
assert(i.hold_just_binary?)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_ST2_CASE3
|
90
|
+
bin = gen_bin(0, 4)
|
91
|
+
i = ST2.new(bin)
|
92
|
+
|
93
|
+
assert_equal(0, i.number1.to_i)
|
94
|
+
assert_equal(nil, i.number2)
|
95
|
+
assert_equal(nil, i.number3)
|
96
|
+
assert_equal(4, i.number4.to_i)
|
97
|
+
assert(i.hold_just_binary?)
|
98
|
+
end
|
99
|
+
|
100
|
+
# TEST CASE STRUCTURE 3
|
101
|
+
# * SPEND and TIMES
|
102
|
+
class ST3 < TemplateBase
|
103
|
+
Def do
|
104
|
+
data :size, UInt, 8
|
105
|
+
SPEND var(:size), :l1 do
|
106
|
+
data :dat, UInt, 8
|
107
|
+
end
|
108
|
+
data :times, UInt, 8
|
109
|
+
TIMES var(:times), :l2 do
|
110
|
+
data :dat, UInt, 8
|
111
|
+
end
|
112
|
+
data :dat, UInt, 8
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_ST3_CASE1
|
117
|
+
bin = gen_bin(0, 0, 0xff)
|
118
|
+
i = ST3.new(bin)
|
119
|
+
|
120
|
+
assert_equal(0, i.size.to_i)
|
121
|
+
assert_equal(0, i.l1.size)
|
122
|
+
assert_equal(0, i.times.to_i)
|
123
|
+
assert_equal(0, i.l2.size)
|
124
|
+
assert_equal(0xff, i.dat.to_i)
|
125
|
+
assert(i.hold_just_binary?)
|
126
|
+
end
|
127
|
+
|
128
|
+
# TEST CASE STRUCTURE 4
|
129
|
+
# * Dynamic length test
|
130
|
+
class ST4 < TemplateBase
|
131
|
+
Def do
|
132
|
+
data :v1, UInt, 8
|
133
|
+
data :v2, UInt, var(:v1)
|
134
|
+
data :v3, UInt, var(:v2)
|
135
|
+
data :v4, UInt, rest
|
136
|
+
data :v5, UInt, rest
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_ST4_CASE1
|
141
|
+
bin = gen_bin(8, 0, 0xff, 0xff)
|
142
|
+
i = ST4.new(bin)
|
143
|
+
|
144
|
+
assert_equal(8, i.v1.to_i)
|
145
|
+
assert_equal(0, i.v2.to_i)
|
146
|
+
assert_equal(nil, i.v3)
|
147
|
+
assert_equal(0xffff, i.v4.to_i)
|
148
|
+
assert_equal(nil, i.v5)
|
149
|
+
assert(i.hold_just_binary?)
|
150
|
+
end
|
151
|
+
|
152
|
+
def test_ST4_CASE2
|
153
|
+
bin = gen_bin(8, 8, 0xff)
|
154
|
+
i = ST4.new(bin)
|
155
|
+
|
156
|
+
assert_equal(8, i.v1.to_i)
|
157
|
+
assert_equal(8, i.v2.to_i)
|
158
|
+
assert_equal(0xff, i.v3.to_i)
|
159
|
+
assert_equal(nil, i.v4)
|
160
|
+
assert_equal(nil, i.v5)
|
161
|
+
assert(i.hold_just_binary?)
|
162
|
+
end
|
163
|
+
|
164
|
+
# TEST CASE STRUCTURE 5
|
165
|
+
# * structure size test
|
166
|
+
class ST5 < TemplateBase
|
167
|
+
Def do
|
168
|
+
data :v1, UInt, 8
|
169
|
+
data :v2, UInt, var(:v1)
|
170
|
+
data :v3, UInt, var(:v2)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_ST5_CASE1
|
175
|
+
i1 = ST5.new(gen_bin(8, 8))
|
176
|
+
assert(!i1.hold_enough_binary?)
|
177
|
+
|
178
|
+
i2 = ST5.new(gen_bin(8))
|
179
|
+
assert_raise(ParsingError) do
|
180
|
+
assert(!i2.hold_enough_binary?)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# helpers
|
185
|
+
def gen_bin(*chars)
|
186
|
+
return AbstractBinary.new(chars.pack("C*"))
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|