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/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
@@ -1,3 +1,3 @@
1
1
  module Codec
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.4"
3
3
  end
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
- # require 'codec/packed'
8
- # require 'codec/prefixed'
9
- # require 'codec/composed'
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
@@ -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
- end
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