codec 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -0
- data/codec.gemspec +1 -0
- data/lib/codec/base.rb +16 -18
- data/lib/codec/bitmap.rb +102 -0
- data/lib/codec/composed.rb +83 -0
- data/lib/codec/exceptions.rb +7 -0
- data/lib/codec/factory.rb +4 -0
- data/lib/codec/field.rb +21 -3
- data/lib/codec/fix.rb +59 -19
- data/lib/codec/packed.rb +68 -0
- data/lib/codec/prefix.rb +136 -0
- data/lib/codec/tlv.rb +176 -0
- data/lib/codec/version.rb +1 -1
- data/lib/codec.rb +5 -4
- data/test/lib/codec/bitmap_test.rb +71 -0
- data/test/lib/codec/composed_test.rb +79 -0
- data/test/lib/codec/field_test.rb +60 -0
- data/test/lib/codec/fix_test.rb +86 -1
- data/test/lib/codec/pckd_test.rb +71 -0
- data/test/lib/codec/prefix_test.rb +104 -0
- data/test/lib/codec/tlv_test.rb +82 -0
- metadata +37 -3
- data/lib/codec/protocols/core.rb +0 -0
data/lib/codec/tlv.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
module Codec
|
2
|
+
class Tlv < Prefixedlength
|
3
|
+
def initialize(id,length,header,content)
|
4
|
+
super(id,length,content)
|
5
|
+
@tag_codec = header
|
6
|
+
@subCodecs = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def decode_with_length(buf,length)
|
10
|
+
l = eval_length(buf,length)
|
11
|
+
f,r = decode(buf[0,l])
|
12
|
+
Logger.warn("Remain data in a tlv buffer :[#{r.unpack("H*").first}]") if r.length > 0
|
13
|
+
return f,buf[l,buf.length]
|
14
|
+
end
|
15
|
+
|
16
|
+
def encode(field)
|
17
|
+
out = ""
|
18
|
+
fields = field.get_value
|
19
|
+
fields.each do |id,sf|
|
20
|
+
out += @tag_codec.encode(Field.new(id,id))
|
21
|
+
if @subCodecs[id]
|
22
|
+
content = @subCodecs[id].encode(sf)
|
23
|
+
length_buffer = @length_codec.encode(Field.new('*',content.length))
|
24
|
+
out += length_buffer + content
|
25
|
+
else
|
26
|
+
out += super(sf)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
return out
|
30
|
+
end
|
31
|
+
|
32
|
+
def decode(buffer)
|
33
|
+
msg = Field.new(@id)
|
34
|
+
while(buffer.length > 0)
|
35
|
+
begin
|
36
|
+
tag,buffer = @tag_codec.decode(buffer)
|
37
|
+
rescue
|
38
|
+
val = Field.new("ERR")
|
39
|
+
val.set_value("Error on parsing tag for TLV with following data [#{buffer.unpack("H*").first}]")
|
40
|
+
msg.add_sub_field(val)
|
41
|
+
return msg
|
42
|
+
end
|
43
|
+
begin
|
44
|
+
if @subCodecs[tag.get_value.to_s].nil?
|
45
|
+
val,buffer = super(buffer)
|
46
|
+
else
|
47
|
+
l,buf = @length_codec.decode(buffer)
|
48
|
+
val,buffer = @subCodecs[tag.get_value.to_s].decode_with_length(buf,l.get_value.to_i)
|
49
|
+
end
|
50
|
+
rescue BufferUnderflow => e
|
51
|
+
val = Field.new
|
52
|
+
val.set_value("Buffer underflow when parsing this tag : #{e.message} [#{buffer.unpack("H*").first}]")
|
53
|
+
buffer = ""
|
54
|
+
rescue
|
55
|
+
val = Field.new
|
56
|
+
val.set_value("Parsing error [#{buffer.unpack("H*").first}]")
|
57
|
+
buffer = ""
|
58
|
+
end
|
59
|
+
|
60
|
+
val.set_id(tag.get_value.to_s)
|
61
|
+
msg.add_sub_field(val)
|
62
|
+
end
|
63
|
+
return msg,buffer
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Bertlv < Base
|
68
|
+
def initialize(id)
|
69
|
+
@id = id
|
70
|
+
@length = 0
|
71
|
+
end
|
72
|
+
|
73
|
+
def tag_decode(buffer)
|
74
|
+
buf = buffer.dup
|
75
|
+
# removing trailling bytes
|
76
|
+
begin ; b = buf.slice!(0).getbyte(0) ; end while (b == 0 || b == 255)
|
77
|
+
tag = b.chr
|
78
|
+
if (b & 0x1F == 0x1F)
|
79
|
+
begin
|
80
|
+
nb = buf.slice!(0).getbyte(0)
|
81
|
+
tag += nb.chr
|
82
|
+
end while nb & 0x80 == 0x80
|
83
|
+
end
|
84
|
+
return tag.unpack("H*").first.upcase, buf
|
85
|
+
end
|
86
|
+
|
87
|
+
def tag_encode(tag)
|
88
|
+
buf = [tag].pack("H*")
|
89
|
+
check_tag, remain = tag_decode(buf)
|
90
|
+
if tag != check_tag || remain != ""
|
91
|
+
raise EncodingException, "Invalid BER tag [#{tag}]"
|
92
|
+
end
|
93
|
+
return buf
|
94
|
+
end
|
95
|
+
|
96
|
+
def length_decode(buffer)
|
97
|
+
buf = buffer.dup
|
98
|
+
b = buf.slice!(0).getbyte(0)
|
99
|
+
if b & 0x80 == 0x80
|
100
|
+
# Compute lenght of encoding length sample if first byte is 83 then lenth is encode
|
101
|
+
# on 3 bytes
|
102
|
+
loencl = b & 0x7F
|
103
|
+
lb = buf[0,loencl]
|
104
|
+
buf = buf[loencl,buf.length]
|
105
|
+
length = 0
|
106
|
+
while(lb.length > 0)
|
107
|
+
length *= 256
|
108
|
+
length += lb.slice!(0).getbyte(0)
|
109
|
+
end
|
110
|
+
return length,buf
|
111
|
+
else
|
112
|
+
return b,buf
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def length_encode(length)
|
117
|
+
out = Numbin.numbin(length,0)
|
118
|
+
if out.length > 127
|
119
|
+
raise EncodingException,"Invalid length for BER Tlv #{length}"
|
120
|
+
elsif out.length > 1
|
121
|
+
out = (128 + out.length).chr + out
|
122
|
+
end
|
123
|
+
return out
|
124
|
+
end
|
125
|
+
|
126
|
+
def value_decode(buf,length)
|
127
|
+
if length > buf.length
|
128
|
+
raise ErrorBufferUnderflow,"Not enough data for parsing BER TLV
|
129
|
+
#{@id} length value #{length} remaining only #{buf.length}"
|
130
|
+
end
|
131
|
+
value = buf[0,length]
|
132
|
+
buf = buf[length,buf.length]
|
133
|
+
return value.unpack("H*").first.upcase,buf
|
134
|
+
end
|
135
|
+
|
136
|
+
def value_encode(unpack_buffer)
|
137
|
+
[unpack_buffer].pack("H*")
|
138
|
+
end
|
139
|
+
|
140
|
+
def build_field(buf,length)
|
141
|
+
msg = Field.new(@id)
|
142
|
+
buffer = buf[0,length]
|
143
|
+
while buffer.length > 0
|
144
|
+
tag,buffer = tag_decode(buffer)
|
145
|
+
f = Field.new(tag)
|
146
|
+
value_length,buffer = length_decode(buffer)
|
147
|
+
value, buffer = value_decode(buffer,value_length)
|
148
|
+
f.set_value(value)
|
149
|
+
msg.add_sub_field(f)
|
150
|
+
end
|
151
|
+
return msg
|
152
|
+
end
|
153
|
+
|
154
|
+
def decode(buffer)
|
155
|
+
return build_field(buffer,buffer.length),""
|
156
|
+
end
|
157
|
+
|
158
|
+
def encode(field)
|
159
|
+
out = ""
|
160
|
+
subfields = field.get_value
|
161
|
+
unless subfields.kind_of?(Array)
|
162
|
+
raise EncodingException, "Invalid field #{field.to_yaml} for BER Tlv encoding"
|
163
|
+
end
|
164
|
+
|
165
|
+
while subfields.size > 0
|
166
|
+
subfield = subfields.shift
|
167
|
+
out += tag_encode(subfield.first)
|
168
|
+
# TODO : Handle value that is not String
|
169
|
+
value = value_encode(subfield.last.get_value)
|
170
|
+
out += length_encode(value.length)
|
171
|
+
out += value
|
172
|
+
end
|
173
|
+
return out
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
data/lib/codec/version.rb
CHANGED
data/lib/codec.rb
CHANGED
@@ -4,10 +4,11 @@ require 'codec/field'
|
|
4
4
|
require 'codec/exceptions'
|
5
5
|
require 'codec/base'
|
6
6
|
require 'codec/fix'
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
require 'codec/packed'
|
8
|
+
require 'codec/prefix'
|
9
|
+
require 'codec/composed'
|
10
|
+
require 'codec/bitmap'
|
11
|
+
require 'codec/tlv'
|
11
12
|
|
12
13
|
module Codec
|
13
14
|
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Codec::Bitmap do
|
4
|
+
|
5
|
+
subject { Codec::Bitmap.new('Bitmap',2) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
subject.add_sub_codec('1',Codec::Numasc.new('*',3))
|
9
|
+
subject.add_sub_codec('2', Codec::String.new('*',5))
|
10
|
+
subject.add_sub_codec('3', Codec::String.new('*',3))
|
11
|
+
subject.add_sub_codec('15', Codec::Numbin.new('*',2))
|
12
|
+
@buffer = ["1100000000000010","012ABCDE","0012"].pack("B*A*H*")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "must be a BaseComposed codec" do
|
16
|
+
subject.must_be_instance_of(Codec::Bitmap)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "must generate composed field from buffer" do
|
20
|
+
subject.decode(@buffer).first.
|
21
|
+
get_value.collect{ |id,f|
|
22
|
+
[id,f.get_value]
|
23
|
+
}.must_equal([['1',12],['2',"ABCDE"],['15',18]])
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Codec::Bitmap do
|
29
|
+
|
30
|
+
subject { Codec::Bitmap.new('MultipleBitmap',2) }
|
31
|
+
|
32
|
+
before do
|
33
|
+
subject.add_extended_bitmap('1')
|
34
|
+
subject.add_sub_codec('2',Codec::Numasc.new('*',3))
|
35
|
+
subject.add_sub_codec('3', Codec::String.new('*',5))
|
36
|
+
subject.add_sub_codec('4', Codec::String.new('*',3))
|
37
|
+
subject.add_sub_codec('18', Codec::Numbin.new('*',2))
|
38
|
+
subject.add_sub_codec('21', Codec::String.new('*',5))
|
39
|
+
@buffer_1 = ["11000000000000000100100000000000","012","0012","ABCDE"].pack("B*A*H*A*")
|
40
|
+
@buffer2 = ["0110000000000000","012","ABCDE"].pack("B*A3A5")
|
41
|
+
@field_1 = Codec::Field.from_array('MultipleBitmap',[['2',12],['18',18],['21',"ABCDE"]])
|
42
|
+
@field_2 = Codec::Field.from_array('MultipleBitmap',[['2',12],['41',18],['21',"ABCDE"]])
|
43
|
+
end
|
44
|
+
|
45
|
+
it "must be a Bitmap codec" do
|
46
|
+
subject.must_be_instance_of(Codec::Bitmap)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "must generate composed field from buffer with extended bitmap" do
|
50
|
+
subject.decode(@buffer_1).first.
|
51
|
+
get_value.collect{ |id,f|
|
52
|
+
[id,f.get_value]
|
53
|
+
}.must_equal([['2',12],['18',18],['21',"ABCDE"]])
|
54
|
+
end
|
55
|
+
|
56
|
+
it "must generate composed field from buffer without extended bitmap" do
|
57
|
+
subject.decode(@buffer2).first.
|
58
|
+
get_value.collect{ |id,f|
|
59
|
+
[id,f.get_value]
|
60
|
+
}.must_equal([['2',12],['3',"ABCDE"]])
|
61
|
+
end
|
62
|
+
|
63
|
+
it "must generate buffer from composed field" do
|
64
|
+
subject.encode(@field_1).must_equal(@buffer_1)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "must raise Encoding exception if subfield is unknown" do
|
68
|
+
proc { subject.encode(@field_2) }.must_raise(Codec::EncodingException)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Codec::BaseComposed do
|
4
|
+
subject { Codec::BaseComposed.new('BaseComposed') }
|
5
|
+
|
6
|
+
before do
|
7
|
+
subject.add_sub_codec('CHP1', Codec::Numasc.new('CHP1',3))
|
8
|
+
subject.add_sub_codec('CHP2', Codec::String.new('CHP2',5))
|
9
|
+
subject.add_sub_codec('CHP3', Codec::String.new('CHP3',4))
|
10
|
+
subject.add_sub_codec('CHP4', Codec::Numasc.new('CH4',4))
|
11
|
+
field_array = [['CHP1',12],['CHP2','ABCDE'],['CHP3','WXYZ'],['CHP4',23]]
|
12
|
+
@buffer_test1 = "012ABCDEWXYZ0023"
|
13
|
+
@field_test1 = Codec::Field.from_array('BaseComposed', field_array)
|
14
|
+
@buffer_test2 = "012ABCDEWXYZ"
|
15
|
+
@field_test2 = Codec::Field.from_array('BaseComposed', field_array[0,3])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "must be a BaseComposed codec" do
|
19
|
+
subject.must_be_instance_of(Codec::BaseComposed)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must generate a field with computed value" do
|
23
|
+
subject.decode(@buffer_test1).first.must_equal(@field_test1)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "must encode buffer with composed field" do
|
27
|
+
subject.encode(@field_test1).must_equal(@buffer_test1)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "must encode buffer with composed field without codec's last field " do
|
31
|
+
subject.encode(@field_test2).must_equal(@buffer_test2)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must handle remaining data" do
|
35
|
+
subject.decode("012ABCDEWXYZ0023123").last.must_equal("123")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe Codec::CompleteComposed do
|
40
|
+
subject { Codec::CompleteComposed.new('CompleteComposed') }
|
41
|
+
|
42
|
+
before do
|
43
|
+
test_1 = [['CHP1',Codec::Numasc.new('*',3),12],
|
44
|
+
['CHP2',Codec::String.new('*',5),"ABCDE"],
|
45
|
+
['CHP3',Codec::String.new('*',4),"WXYZ"]]
|
46
|
+
field_array = test_1.collect{|id,codec,value| [id,value]}
|
47
|
+
@field_1 = Codec::Field.from_array('CompleteComposed',field_array)
|
48
|
+
test_1.each { |id,codec,value| subject.add_sub_codec(id,codec) }
|
49
|
+
@buffer_1 = "012ABCDEWXYZ123"
|
50
|
+
@buffer_2 = "012ABCDEWXYZ"
|
51
|
+
@buffer_3 = "012ABCDE"
|
52
|
+
@field_2 = Codec::Field.from_array('CompleteComposed',field_array[0,2])
|
53
|
+
end
|
54
|
+
|
55
|
+
it "must be a CompleteComposed codec" do
|
56
|
+
subject.must_be_instance_of(Codec::CompleteComposed)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "must generate a field with computed value" do
|
60
|
+
subject.decode(@buffer_1).first.must_equal(@field_1)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "must handle remaining data" do
|
64
|
+
subject.decode(@buffer_1).last.must_equal("123")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "must raise BufferUnderflow if missing field" do
|
68
|
+
proc { subject.decode(@buffer_3)}.must_raise(Codec::BufferUnderflow)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "must encode expected buffer" do
|
72
|
+
subject.encode(@field_1).must_equal(@buffer_2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "must raise EncodingException if missing field" do
|
76
|
+
proc { subject.encode(@field_2)}.must_raise(Codec::EncodingException)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Codec::Field do
|
4
|
+
subject { f = Codec::Field.new('Test')
|
5
|
+
sf1 = Codec::Field.new('SF1')
|
6
|
+
sf1.set_value("123")
|
7
|
+
f.add_sub_field(sf1)
|
8
|
+
sf2 = Codec::Field.new('SF2')
|
9
|
+
sf2.set_value("321")
|
10
|
+
f.add_sub_field(sf2)
|
11
|
+
f
|
12
|
+
}
|
13
|
+
|
14
|
+
it "must be a Field" do
|
15
|
+
subject.must_be_instance_of(Codec::Field)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "must respond to set_value" do
|
19
|
+
subject.must_respond_to :set_value
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must equal field create with from_array builder" do
|
23
|
+
subject.must_equal(Codec::Field.from_array('Test',[['SF1',"123"],['SF2',"321"]]))
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Codec::Field do
|
29
|
+
subject { f = Codec::Field.new('Test')
|
30
|
+
sf1 = Codec::Field.new('SF1')
|
31
|
+
sf1.set_value("123")
|
32
|
+
f.add_sub_field(sf1)
|
33
|
+
sf2 = Codec::Field.new('SF2')
|
34
|
+
sf2.set_value("321")
|
35
|
+
f.add_sub_field(sf2)
|
36
|
+
sf3 = Codec::Field.new('SF3')
|
37
|
+
sf31 = Codec::Field.new('SF31')
|
38
|
+
sf31.set_value("456")
|
39
|
+
sf3.add_sub_field(sf31)
|
40
|
+
sf32 = Codec::Field.new('SF32')
|
41
|
+
sf32.set_value("789")
|
42
|
+
sf3.add_sub_field(sf32)
|
43
|
+
f.add_sub_field(sf3)
|
44
|
+
f
|
45
|
+
}
|
46
|
+
|
47
|
+
it "must be a Field" do
|
48
|
+
subject.must_be_instance_of(Codec::Field)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "must respond to set_value" do
|
52
|
+
subject.must_respond_to :set_value
|
53
|
+
end
|
54
|
+
|
55
|
+
it "must equal field create with from_array builder" do
|
56
|
+
subject.must_equal(Codec::Field.from_array('Test',
|
57
|
+
[['SF1',"123"],['SF2',"321"],['SF3',[['SF31',"456"],['SF32','789']]]]))
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/test/lib/codec/fix_test.rb
CHANGED
@@ -2,6 +2,11 @@ require_relative '../../test_helper'
|
|
2
2
|
|
3
3
|
describe Codec::Numbin do
|
4
4
|
subject { Codec::Numbin.new('Test',4) }
|
5
|
+
|
6
|
+
before do
|
7
|
+
@f256 = Codec::Field.new
|
8
|
+
@f256.set_value(256)
|
9
|
+
end
|
5
10
|
|
6
11
|
it "must be a codec" do
|
7
12
|
subject.must_be_instance_of(Codec::Numbin)
|
@@ -10,7 +15,87 @@ describe Codec::Numbin do
|
|
10
15
|
it "must generate a field with computed value" do
|
11
16
|
subject.decode(["00000100"].pack("H*")).first.get_value.to_i.must_equal(256)
|
12
17
|
end
|
18
|
+
|
13
19
|
it "must generate a field with computed value" do
|
14
20
|
subject.decode(["00000100"].pack("H*")).last.size.must_equal(0)
|
15
|
-
|
21
|
+
end
|
22
|
+
|
23
|
+
it "must generate a field with computed value" do
|
24
|
+
subject.encode(@f256).must_equal(["00000100"].pack("H*"))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Codec::Numasc do
|
29
|
+
subject { Codec::Numasc.new('Test',4) }
|
30
|
+
|
31
|
+
before do
|
32
|
+
@f12 = Codec::Field.new
|
33
|
+
@f12.set_value(12)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "must be a codec" do
|
37
|
+
subject.must_be_instance_of(Codec::Numasc)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "must generate a field with computed value" do
|
41
|
+
subject.decode("0012").first.get_value.to_i.must_equal(12)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "must generate a field with computed value" do
|
45
|
+
subject.decode("0012").last.size.must_equal(0)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "must generate a field with computed value" do
|
49
|
+
subject.encode(@f12).must_equal("0012")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe Codec::String do
|
54
|
+
subject { Codec::String.new('Test',10) }
|
55
|
+
before do
|
56
|
+
@fstring = Codec::Field.new
|
57
|
+
@fstring.set_value("TEST")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "must be a codec" do
|
61
|
+
subject.must_be_instance_of(Codec::String)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "must generate a field with computed value" do
|
65
|
+
subject.decode("Testing string").first.get_value.must_equal("Testing st")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "must also return remaining data" do
|
69
|
+
subject.decode("Testing string").last.must_equal("ring")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "must generate a buffer with corresponding value padded with space" do
|
73
|
+
subject.encode(@fstring).must_equal("TEST ")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe Codec::Binary do
|
78
|
+
subject { Codec::Binary.new('Test',8) }
|
79
|
+
before do
|
80
|
+
@unpack_buffer = "ABCDEF0123456789"
|
81
|
+
@bin_buffer = [@unpack_buffer].pack("H*")
|
82
|
+
@fbin = Codec::Field.new
|
83
|
+
@fbin.set_value(@unpack_buffer)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "must be a codec" do
|
87
|
+
subject.must_be_instance_of(Codec::Binary)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "must generate a field with computed value" do
|
91
|
+
subject.decode(@bin_buffer).first.get_value.must_equal(@unpack_buffer)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "must return no remaining data" do
|
95
|
+
subject.decode(@bin_buffer).last.must_equal("")
|
96
|
+
end
|
97
|
+
|
98
|
+
it "must regenerate corresponding buffer" do
|
99
|
+
subject.encode(@fbin).must_equal(@bin_buffer)
|
100
|
+
end
|
16
101
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Codec::Packed do
|
4
|
+
subject { Codec::Packed.new('Test',6) }
|
5
|
+
|
6
|
+
before do
|
7
|
+
@f_pck = Codec::Field.new
|
8
|
+
@f_pck.set_value("123")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "must be a codec" do
|
12
|
+
subject.must_be_instance_of(Codec::Packed)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "must retrieve field length" do
|
16
|
+
subject.eval_pck_length(@f_pck).must_equal(6)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Codec::Numpck do
|
22
|
+
subject { Codec::Numpck.new('Test',5) }
|
23
|
+
|
24
|
+
before do
|
25
|
+
@f12 = Codec::Field.new
|
26
|
+
@f12.set_value(12)
|
27
|
+
@pck_buff = ["000012"].pack("H*")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "must be a codec" do
|
31
|
+
subject.must_be_instance_of(Codec::Numpck)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must generate a field with computed value" do
|
35
|
+
subject.decode(@pck_buff).first.get_value.to_i.must_equal(12)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "must not remain data" do
|
39
|
+
subject.decode(@pck_buff).last.size.must_equal(0)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "must generate a field with computed value" do
|
43
|
+
subject.encode(@f12).must_equal(@pck_buff)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Codec::Strpck do
|
48
|
+
subject { Codec::Strpck.new('Test',11) }
|
49
|
+
before do
|
50
|
+
@unpack_buffer = "497011D9010"
|
51
|
+
@bin_buffer = [@unpack_buffer + "F"].pack("H*")
|
52
|
+
@fbin = Codec::Field.new
|
53
|
+
@fbin.set_value(@unpack_buffer)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "must be a codec" do
|
57
|
+
subject.must_be_instance_of(Codec::Strpck)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "must generate a field with computed value" do
|
61
|
+
subject.decode(@bin_buffer).first.get_value.upcase.must_equal(@unpack_buffer)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "must return no remaining data" do
|
65
|
+
subject.decode(@bin_buffer).last.must_equal("")
|
66
|
+
end
|
67
|
+
|
68
|
+
it "must regenerate corresponding buffer" do
|
69
|
+
subject.encode(@fbin).must_equal(@bin_buffer)
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
describe Codec::Prefixedlength do
|
4
|
+
before do
|
5
|
+
@length = Codec::Numasc.new('length',3)
|
6
|
+
@content = Codec::String.new('content',0)
|
7
|
+
@field = Codec::Field.new
|
8
|
+
@field.set_value("0012AB")
|
9
|
+
@buffer = "0060012AB"
|
10
|
+
end
|
11
|
+
|
12
|
+
subject { Codec::Prefixedlength.new('Test_lvar',@length,@content) }
|
13
|
+
|
14
|
+
it "must be a Prefixedlength codec" do
|
15
|
+
subject.must_be_instance_of(Codec::Prefixedlength)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "must generate a field with computed value" do
|
19
|
+
subject.decode(@buffer).first.get_value.must_equal("0012AB")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must also return remaining data" do
|
23
|
+
subject.decode(@buffer).last.must_equal("")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "must encode value prefixed with length" do
|
27
|
+
subject.encode(@field).must_equal("0060012AB")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Codec::Headerlength do
|
32
|
+
before do
|
33
|
+
tag = Codec::Binary.new('T',1)
|
34
|
+
length = Codec::Numbin.new('L',1)
|
35
|
+
value = Codec::Numbin.new('V',0)
|
36
|
+
tlv = Codec::Tlv.new('TAG',length,tag,value)
|
37
|
+
@header = Codec::BaseComposed.new('HEADER')
|
38
|
+
@header.add_sub_codec('H_TAG',tag)
|
39
|
+
@header.add_sub_codec('H_TLV',Codec::Prefixedlength.new('*',length,tlv))
|
40
|
+
@content = Codec::String.new('CONTENT',0)
|
41
|
+
len = 6
|
42
|
+
field_array = [['HEADER', [['H_TAG','AA'],['H_TLV',[['01',25],['02',len]]]]],
|
43
|
+
['CONTENT','STRING']]
|
44
|
+
@field_with_length = Codec::Field.from_array('Test_Headerlength',field_array)
|
45
|
+
len = 0
|
46
|
+
field_array = [['HEADER', [['H_TAG','AA'],['H_TLV',[['01',25],['02',len]]]]],
|
47
|
+
['CONTENT','STRING']]
|
48
|
+
@field_without_length = Codec::Field.from_array('Test_Headerlength',field_array)
|
49
|
+
@buffer = ["AA06010119020106","STRING"].pack("H*A*")
|
50
|
+
end
|
51
|
+
|
52
|
+
subject { Codec::Headerlength.new('Test_Headerlength',@header,@content,'.H_TLV.02') }
|
53
|
+
|
54
|
+
it "must be a Headerlength codec" do
|
55
|
+
subject.must_be_instance_of(Codec::Headerlength)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "must decode a field with computed value" do
|
59
|
+
subject.decode(@buffer).first.must_equal(@field_with_length)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "must also return remaining data" do
|
63
|
+
subject.decode(@buffer + "REMAIN").last.must_equal("REMAIN")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "must encode buffer with composed field [header,content]" do
|
67
|
+
subject.encode(@field_without_length).must_equal(@buffer)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe Codec::Tagged do
|
72
|
+
before do
|
73
|
+
@field1 = Codec::Field.new('01',12)
|
74
|
+
@field2 = Codec::Field.new('02','ABC')
|
75
|
+
@buffer1 = "01012"
|
76
|
+
@buffer2 = "02ABC"
|
77
|
+
end
|
78
|
+
|
79
|
+
subject { c = Codec::Tagged.new('Test_tagged',Codec::String.new('*',2))
|
80
|
+
c.add_sub_codec('01',Codec::Numasc.new('*',3))
|
81
|
+
c.add_sub_codec('02',Codec::String.new('*',3))
|
82
|
+
c
|
83
|
+
}
|
84
|
+
|
85
|
+
it "must be a Tagged codec" do
|
86
|
+
subject.must_be_instance_of(Codec::Tagged)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "must generate a field with computed value" do
|
90
|
+
subject.decode(@buffer1).first.must_equal(@field1)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "must generate a field with computed value" do
|
94
|
+
subject.decode(@buffer2).first.must_equal(@field2)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "must encode value prefixed with length" do
|
98
|
+
subject.encode(@field1).must_equal(@buffer1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "must encode value prefixed with length" do
|
102
|
+
subject.encode(@field2).must_equal(@buffer2)
|
103
|
+
end
|
104
|
+
end
|