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/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