codec 0.0.2 → 0.0.4
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.
- 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
|