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/.travis.yml
ADDED
data/codec.gemspec
CHANGED
data/lib/codec/base.rb
CHANGED
@@ -6,47 +6,45 @@ module Codec
|
|
6
6
|
@id = id
|
7
7
|
end
|
8
8
|
|
9
|
-
def build_field
|
9
|
+
def build_field(buf,length)
|
10
10
|
f = Field.new(@id)
|
11
|
-
f.set_value(
|
11
|
+
f.set_value(buf[0,length])
|
12
12
|
return f
|
13
13
|
end
|
14
14
|
|
15
15
|
def decode_with_length(buf,length)
|
16
|
-
|
17
|
-
return build_field
|
16
|
+
l = eval_length(buf,length)
|
17
|
+
return build_field(buf,l),buf[l,buf.length]
|
18
18
|
end
|
19
19
|
|
20
20
|
def decode(buf)
|
21
|
-
|
22
|
-
return build_field
|
21
|
+
l = eval_length(buf,@length)
|
22
|
+
return build_field(buf,l),buf[l,buf.length]
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def eval_length(buf,length)
|
26
26
|
length = 0 if length.nil?
|
27
27
|
if(length != 0)
|
28
28
|
if buf.length < length
|
29
29
|
raise BufferUnderflow, "Not enough data for parsing #{@id} (#{length}/#{buf.length})"
|
30
30
|
end
|
31
|
-
|
32
|
-
@remain = buf[length,buf.length]
|
31
|
+
return length
|
33
32
|
else
|
34
|
-
|
35
|
-
@remain = ""
|
33
|
+
return buf.length
|
36
34
|
end
|
37
35
|
end
|
38
36
|
|
39
|
-
def
|
40
|
-
if
|
41
|
-
raise InitializeException, "Invalid codec reference in
|
37
|
+
def add_sub_codec(id_field,codec)
|
38
|
+
if codec.nil?
|
39
|
+
raise InitializeException, "Invalid codec reference in subcodec #{id_field} for codec #{@id}"
|
42
40
|
end
|
43
|
-
if @
|
44
|
-
@
|
41
|
+
if @subCodecs.kind_of? Hash
|
42
|
+
@subCodecs[id_field] = codec
|
45
43
|
end
|
46
44
|
end
|
47
45
|
|
48
|
-
def
|
49
|
-
return @
|
46
|
+
def get_sub_codecs
|
47
|
+
return @subCodecs
|
50
48
|
end
|
51
49
|
end
|
52
50
|
end
|
data/lib/codec/bitmap.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module Codec
|
2
|
+
class Bitmap < Base
|
3
|
+
NB_BITS_BY_BYTE = 8
|
4
|
+
def initialize(id,length)
|
5
|
+
super(id,length)
|
6
|
+
@num_extended_bitmaps=[]
|
7
|
+
@subCodecs = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def bitmap_length
|
11
|
+
@length * NB_BITS_BY_BYTE
|
12
|
+
end
|
13
|
+
def add_extended_bitmap(num_extention)
|
14
|
+
@num_extended_bitmaps << num_extention.to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def decodeBitmap(buffer,first_field_num)
|
18
|
+
fieldsList = []
|
19
|
+
|
20
|
+
bitmapBuffer = buffer[0,@length].unpack("B*").first
|
21
|
+
buf = buffer[@length,buffer.length]
|
22
|
+
field_num = first_field_num
|
23
|
+
while(bitmapBuffer.length > 0)
|
24
|
+
fieldsList << field_num if bitmapBuffer.start_with?('1')
|
25
|
+
bitmapBuffer.slice!(0)
|
26
|
+
field_num += 1
|
27
|
+
end
|
28
|
+
return fieldsList, buf
|
29
|
+
end
|
30
|
+
|
31
|
+
def encode_bitmap(fields_list,bitmap_index)
|
32
|
+
offset = bitmap_index * bitmap_length
|
33
|
+
bitmap = ""
|
34
|
+
((offset + 1)..(offset + bitmap_length)).each do |i|
|
35
|
+
if fields_list.include?(i)
|
36
|
+
bitmap += "1"
|
37
|
+
else
|
38
|
+
bitmap += "0"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
return [bitmap].pack("B*")
|
42
|
+
end
|
43
|
+
|
44
|
+
def encode(field)
|
45
|
+
fields = field.get_value
|
46
|
+
encoded_fields = []
|
47
|
+
fields_list = fields.collect{|id,sf| id.to_i}
|
48
|
+
# Add field for bitmaps
|
49
|
+
bitmap_fields = @num_extended_bitmaps[0,(fields_list.last - 1) / bitmap_length]
|
50
|
+
fields_list += bitmap_fields
|
51
|
+
fields += bitmap_fields.collect {|id| [id,nil]}
|
52
|
+
fields.sort!{|a,b| a.first.to_i <=> b.first.to_i}
|
53
|
+
# Encode first bitmap
|
54
|
+
out = encode_bitmap(fields_list,0)
|
55
|
+
bitmap_index = 1
|
56
|
+
fields.each do |id,sf|
|
57
|
+
codec = @subCodecs[id]
|
58
|
+
if @num_extended_bitmaps.include?(id)
|
59
|
+
out += encode_bitmap(fields_list,bitmap_index)
|
60
|
+
bitmap_index += 1
|
61
|
+
elsif codec.nil?
|
62
|
+
raise EncodingException, "unknown codec for subfield #{id}"
|
63
|
+
elsif encoded_fields.include?(id.to_i)
|
64
|
+
raise EncodingException, "Multiple subfield #{id} is invalid for Codec::Bitmap"
|
65
|
+
else
|
66
|
+
out += codec.encode(sf)
|
67
|
+
end
|
68
|
+
encoded_fields << id.to_i
|
69
|
+
end
|
70
|
+
return out
|
71
|
+
end
|
72
|
+
|
73
|
+
def decode(buffer)
|
74
|
+
msg = Field.new(@id)
|
75
|
+
field_num = 1
|
76
|
+
# 1. read bitmap
|
77
|
+
fields_list,buf = decodeBitmap(buffer,field_num)
|
78
|
+
field_num += bitmap_length
|
79
|
+
# 2. decode each field present
|
80
|
+
while fields_list.length > 0
|
81
|
+
# get next field number in bitmap
|
82
|
+
field_id = fields_list.slice!(0)
|
83
|
+
field_tag = field_id.to_s
|
84
|
+
if @num_extended_bitmaps.include?(field_id)
|
85
|
+
nextFields,buf = decodeBitmap(buf,field_num)
|
86
|
+
fields_list = fields_list + nextFields
|
87
|
+
elsif @subCodecs[field_tag].respond_to?(:decode)
|
88
|
+
Logger.debug "Parsing bitmap field #{field_tag}"
|
89
|
+
f,buf = @subCodecs[field_tag].decode(buf)
|
90
|
+
f.set_id(field_tag)
|
91
|
+
msg.add_sub_field(f)
|
92
|
+
else
|
93
|
+
f = Field.new("ERR")
|
94
|
+
f.set_value(buf.unpack("H*").first)
|
95
|
+
msg.add_sub_field(f)
|
96
|
+
raise ParsingException,msg.to_yaml + "\nError unknown field #{field_tag} : "
|
97
|
+
end
|
98
|
+
end
|
99
|
+
return msg,buf
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Codec
|
2
|
+
class BaseComposed < Base
|
3
|
+
def initialize(id)
|
4
|
+
@id = id
|
5
|
+
@subCodecs = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def decode(buf)
|
9
|
+
return build_each_field(buf,buf.length)
|
10
|
+
end
|
11
|
+
|
12
|
+
def encode(field)
|
13
|
+
subfields = field.get_value
|
14
|
+
composed_encoder = subfields.zip(@subCodecs).collect {|sf,sc|
|
15
|
+
if sf.first != sc.first
|
16
|
+
raise EncodingException, "subfield #{sf.first} not correspond to subcodec #{sc.first}"
|
17
|
+
end
|
18
|
+
[sc.last,sf.last]
|
19
|
+
}
|
20
|
+
out = ""
|
21
|
+
composed_encoder.each do |subcodec,subfield|
|
22
|
+
out += subcodec.encode(subfield)
|
23
|
+
end
|
24
|
+
return out
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_each_field(buf,length)
|
28
|
+
msg = Field.new(@id)
|
29
|
+
working_buf = buf[0,length]
|
30
|
+
@subCodecs.each{|id,codec|
|
31
|
+
Logger.debug "Parsing struct field #{@id} : #{id}"
|
32
|
+
if working_buf.length == 0
|
33
|
+
Logger.debug "Not enough data to decode #{@id} : #{id}"
|
34
|
+
else
|
35
|
+
f,working_buf = codec.decode(working_buf)
|
36
|
+
f.set_id(id)
|
37
|
+
msg.add_sub_field(f)
|
38
|
+
end
|
39
|
+
}
|
40
|
+
return msg,working_buf
|
41
|
+
end
|
42
|
+
|
43
|
+
def build_field(buf,length)
|
44
|
+
msg,working_buf = build_each_field(buf,length)
|
45
|
+
|
46
|
+
if working_buf.length > 0
|
47
|
+
if @length_unknown
|
48
|
+
@remain = working_buf
|
49
|
+
else
|
50
|
+
f = Field.new("PADDING")
|
51
|
+
f.set_value(working_buf.unpack("H*").first)
|
52
|
+
msg.add_sub_field(f)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
return msg
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_sub_codec(id_field,codec)
|
59
|
+
if codec.nil?
|
60
|
+
raise InitializeException, "Invalid codec reference in subcodec #{id_field} for codec #{@id}"
|
61
|
+
end
|
62
|
+
@subCodecs << [id_field, codec]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class CompleteComposed < BaseComposed
|
67
|
+
def build_each_field(buf,length)
|
68
|
+
f,r = super(buf,length)
|
69
|
+
# Check if all struct's fields have been parsed
|
70
|
+
if f.get_value.size < @subCodecs.size
|
71
|
+
raise BufferUnderflow, "Not enough data for parsing Struct #{@id}"
|
72
|
+
end
|
73
|
+
return f,r
|
74
|
+
end
|
75
|
+
|
76
|
+
def encode(field)
|
77
|
+
if @subCodecs.size != field.get_value.size
|
78
|
+
raise EncodingException, "Not enough subfields to encode #{@id}"
|
79
|
+
end
|
80
|
+
super(field)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/codec/exceptions.rb
CHANGED
data/lib/codec/field.rb
CHANGED
@@ -8,11 +8,28 @@ module Codec
|
|
8
8
|
end
|
9
9
|
|
10
10
|
class Field
|
11
|
-
def initialize(id="*")
|
11
|
+
def initialize(id="*",value="")
|
12
12
|
@id = (id.nil? ? "*" : id)
|
13
|
-
@value =
|
13
|
+
@value = value
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
|
+
def self.from_array(id,fields_array)
|
17
|
+
f = Field.new(id)
|
18
|
+
fields_array.each do |id,value|
|
19
|
+
if value.kind_of?(Array)
|
20
|
+
sf = Field.from_array(id,value)
|
21
|
+
else
|
22
|
+
sf = Field.new(id,value)
|
23
|
+
end
|
24
|
+
f.add_sub_field(sf)
|
25
|
+
end
|
26
|
+
return f
|
27
|
+
end
|
28
|
+
|
29
|
+
def ==(other)
|
30
|
+
(@id == other.get_id && @value == other.get_value)
|
31
|
+
end
|
32
|
+
|
16
33
|
def get_id ; @id; end
|
17
34
|
|
18
35
|
def set_id id ; @id = id ; end
|
@@ -22,6 +39,7 @@ module Codec
|
|
22
39
|
def set_value(value)
|
23
40
|
raise "Error can not set value that is instance of Array" if value.kind_of? Array
|
24
41
|
@value = value
|
42
|
+
return self
|
25
43
|
end
|
26
44
|
|
27
45
|
def add_sub_field(sf)
|
data/lib/codec/fix.rb
CHANGED
@@ -1,48 +1,88 @@
|
|
1
1
|
module Codec
|
2
2
|
class Numbin < Base
|
3
|
-
def build_field
|
3
|
+
def build_field(buf,length)
|
4
4
|
f = Field.new(@id)
|
5
5
|
res = 0
|
6
|
-
|
6
|
+
buf[0,length].unpack("C*").each{ |ubyte|
|
7
7
|
res *= 256
|
8
8
|
res += ubyte
|
9
9
|
}
|
10
10
|
f.set_value(res)
|
11
11
|
return f
|
12
12
|
end
|
13
|
+
|
14
|
+
def encode(field)
|
15
|
+
val = field.get_value.to_i
|
16
|
+
out = Numbin.numbin(val,@length)
|
17
|
+
return out
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.numbin(number,maxlength)
|
21
|
+
out = ""
|
22
|
+
while number > 0
|
23
|
+
out << (number % 256).chr
|
24
|
+
number /= 256
|
25
|
+
end
|
26
|
+
|
27
|
+
# handle length if defined
|
28
|
+
if maxlength > 0
|
29
|
+
while out.length < maxlength
|
30
|
+
out << 0.chr
|
31
|
+
end
|
32
|
+
out = out[0,maxlength]
|
33
|
+
end
|
34
|
+
return out.reverse
|
35
|
+
end
|
13
36
|
end
|
14
37
|
|
15
|
-
|
16
|
-
|
17
|
-
class Numstr < Base
|
18
|
-
def build_field
|
38
|
+
class Numasc < Base
|
39
|
+
def build_field(buf,length)
|
19
40
|
f = Field.new(@id)
|
20
|
-
|
21
|
-
if IsEbcdic(@data)
|
22
|
-
@data = Ebcdic2Ascii(@data)
|
23
|
-
end
|
24
|
-
|
25
|
-
f.set_value(@data.to_i)
|
41
|
+
f.set_value(buf[0,length].to_i)
|
26
42
|
return f
|
27
43
|
end
|
44
|
+
|
45
|
+
def encode(field)
|
46
|
+
out = field.get_value.to_s
|
47
|
+
if @length > 0
|
48
|
+
out = out.rjust(@length,"0")
|
49
|
+
raise TooLongDataException if out.length > @length
|
50
|
+
end
|
51
|
+
return out
|
52
|
+
end
|
28
53
|
end
|
29
54
|
|
30
55
|
class String < Base
|
31
|
-
def build_field
|
56
|
+
def build_field(buf,length)
|
32
57
|
f = Field.new(@id)
|
33
|
-
|
34
|
-
@data = Ebcdic2Ascii(@data)
|
35
|
-
end
|
36
|
-
f.set_value(@data)
|
58
|
+
f.set_value(buf[0,length])
|
37
59
|
return f
|
38
60
|
end
|
61
|
+
|
62
|
+
def encode(f)
|
63
|
+
out = f.get_value
|
64
|
+
if @length > 0
|
65
|
+
raise TooLongDataException if out.length > @length
|
66
|
+
out = out.ljust(@length," ")
|
67
|
+
end
|
68
|
+
return out
|
69
|
+
end
|
39
70
|
end
|
40
71
|
|
41
72
|
class Binary < Base
|
42
|
-
def build_field
|
73
|
+
def build_field(buf,length)
|
43
74
|
f = Field.new(@id)
|
44
|
-
f.set_value(
|
75
|
+
f.set_value(buf[0,length].unpack("H*").first.upcase)
|
45
76
|
return f
|
46
77
|
end
|
78
|
+
|
79
|
+
def encode(f)
|
80
|
+
out = [f.get_value].pack("H*")
|
81
|
+
if @length > 0
|
82
|
+
raise TooLongDataException if out.length > @length
|
83
|
+
out = out.ljust(@length,0.chr)
|
84
|
+
end
|
85
|
+
return out
|
86
|
+
end
|
47
87
|
end
|
48
88
|
end
|
data/lib/codec/packed.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Codec
|
2
|
+
class Packed < Base
|
3
|
+
def get_pck_length(length)
|
4
|
+
((length + 1) / 2)
|
5
|
+
end
|
6
|
+
|
7
|
+
def eval_pck_length(field)
|
8
|
+
if @length > 0
|
9
|
+
return @length
|
10
|
+
else
|
11
|
+
return field.get_value.to_s.length
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def decode_with_length(buf,length)
|
16
|
+
l = eval_length(buf,get_pck_length(length))
|
17
|
+
return build_field(buf,l),buf[l,buf.length]
|
18
|
+
end
|
19
|
+
|
20
|
+
def decode(buf)
|
21
|
+
return decode_with_length(buf,@length)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Numpck < Packed
|
26
|
+
def build_field(buf,length)
|
27
|
+
f = Field.new(@id)
|
28
|
+
f.set_value(buf[0,length].unpack("H*").first.to_i)
|
29
|
+
return f
|
30
|
+
end
|
31
|
+
|
32
|
+
def encode(field)
|
33
|
+
out = field.get_value.to_s
|
34
|
+
if @length > 0
|
35
|
+
out = out.rjust(@length,"0")
|
36
|
+
raise TooLongDataException if out.length > @length
|
37
|
+
end
|
38
|
+
l = out.length
|
39
|
+
out.prepend("0") if out.length.odd?
|
40
|
+
out = [out].pack("H*")
|
41
|
+
return out
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class Strpck < Packed
|
46
|
+
def build_field(buf,length)
|
47
|
+
f = Field.new(@id)
|
48
|
+
val = buf[0,length].unpack("H*").first
|
49
|
+
# TODO : handle odd length for packed field with prefixed length
|
50
|
+
val.chop! if @length.odd?
|
51
|
+
f.set_value(val)
|
52
|
+
return f
|
53
|
+
end
|
54
|
+
|
55
|
+
def encode(field)
|
56
|
+
out = field.get_value.to_s
|
57
|
+
if @length > 0
|
58
|
+
out = out.ljust(@length,"F")
|
59
|
+
raise TooLongDataException if out.length > @length
|
60
|
+
end
|
61
|
+
l = out.length
|
62
|
+
out += "F" if out.length.odd?
|
63
|
+
out = [out].pack("H*")
|
64
|
+
return out
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/lib/codec/prefix.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
module Codec
|
2
|
+
class Prefixedlength < Base
|
3
|
+
def initialize(id,length,content)
|
4
|
+
# TODO : Check that value_codec has a null length attribute
|
5
|
+
@length_codec = length
|
6
|
+
@value_codec = content
|
7
|
+
@id = id
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_length(length_field)
|
11
|
+
length_field.get_value.to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def decode(buffer)
|
15
|
+
l, buf = @length_codec.decode(buffer)
|
16
|
+
len = get_length(l)
|
17
|
+
if len == 0
|
18
|
+
f = Field.new
|
19
|
+
f.set_id(@id)
|
20
|
+
f.set_value(nil)
|
21
|
+
return f,buf
|
22
|
+
else
|
23
|
+
begin
|
24
|
+
f,remain = @value_codec.decode_with_length(buf,len)
|
25
|
+
rescue => e
|
26
|
+
Logger.error "Error in #{@id} decoder \n #{e.message}\n#{e.backtrace.join(10.chr)}"
|
27
|
+
raise ParsingException, e.message
|
28
|
+
end
|
29
|
+
|
30
|
+
f.set_id(@id)
|
31
|
+
return f,remain
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_field(buf,length)
|
36
|
+
begin
|
37
|
+
f,r = decode(buf[0,length])
|
38
|
+
rescue ErrorBufferUnderflow => e
|
39
|
+
raise ParsingException, e.message
|
40
|
+
end
|
41
|
+
Logger.error "Error remain data in Prefixedlength" if r != ""
|
42
|
+
return f
|
43
|
+
end
|
44
|
+
|
45
|
+
def encode(field)
|
46
|
+
val = @value_codec.encode(field)
|
47
|
+
length = @length_codec.encode(Field.new.set_value(val.length))
|
48
|
+
out = length + val
|
49
|
+
return out
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Headerlength < Prefixedlength
|
54
|
+
def initialize(id,header,content,length_path)
|
55
|
+
@path = length_path # length attribute contain the path for length field in header
|
56
|
+
@separator = @path.slice!(0).chr # first character contain the separator
|
57
|
+
super(id,header,content)
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_length(header_field)
|
61
|
+
return header_field.get_value.to_i if @path.length == 0 # Handle simple numeric header field
|
62
|
+
length_field = header_field.get_deep_field(@path,@separator)
|
63
|
+
if length_field.nil?
|
64
|
+
return 0
|
65
|
+
else
|
66
|
+
length_field.get_value.to_i
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def decode(buffer)
|
71
|
+
f = Field.new
|
72
|
+
f.set_id(@id)
|
73
|
+
head, buf = @length_codec.decode(buffer)
|
74
|
+
head.set_id(@length_codec.id)
|
75
|
+
f.add_sub_field(head)
|
76
|
+
len = get_length(head)
|
77
|
+
if len == 0
|
78
|
+
return f,buf
|
79
|
+
else
|
80
|
+
len -= (buffer.length - buf.length) if @header_length_include
|
81
|
+
val,remain = @value_codec.decode_with_length(buf,len)
|
82
|
+
val.set_id(@value_codec.id)
|
83
|
+
f.add_sub_field(val)
|
84
|
+
return f,remain
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def encode(field)
|
89
|
+
# encode content
|
90
|
+
content = @value_codec.encode(field.get_sub_field(@value_codec.id))
|
91
|
+
head_field = field.get_sub_field(@length_codec.id)
|
92
|
+
length_field = head_field.get_deep_field(@path,@separator)
|
93
|
+
if length_field.nil?
|
94
|
+
raise EncodingException,"Length field #{@path} is not present in header for encoding #{@id} =>
|
95
|
+
#{field.to_yaml}"
|
96
|
+
end
|
97
|
+
# update length field in header
|
98
|
+
length_field.set_value(content.length)
|
99
|
+
# encode header
|
100
|
+
header = @length_codec.encode(head_field)
|
101
|
+
return header + content
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Headerfulllength < Headerlength
|
106
|
+
# TODO : to implement
|
107
|
+
end
|
108
|
+
|
109
|
+
class Tagged < Base
|
110
|
+
def initialize(id,tag_codec)
|
111
|
+
@subCodecs = {}
|
112
|
+
@tag_codec = tag_codec
|
113
|
+
@id = id
|
114
|
+
end
|
115
|
+
|
116
|
+
def decode(buffer)
|
117
|
+
tag,buf = @tag_codec.decode(buffer)
|
118
|
+
if @subCodecs[tag.get_value.to_s].nil?
|
119
|
+
raise ParsingException, "Unknown tag #{tag.get_value.to_s} for #{@id} decoder"
|
120
|
+
end
|
121
|
+
f,buf = @subCodecs[tag.get_value.to_s].decode(buf)
|
122
|
+
f.set_id(tag.get_value.to_s)
|
123
|
+
return f,buf
|
124
|
+
end
|
125
|
+
|
126
|
+
def encode(field)
|
127
|
+
head = Field.new(@tag_codec.id, field.get_id)
|
128
|
+
out = @tag_codec.encode(head)
|
129
|
+
if @subCodecs[field.get_id].nil?
|
130
|
+
raise EncodingException, "Unknown tag #{field.get_id} for #{@id} encoder"
|
131
|
+
end
|
132
|
+
out += @subCodecs[field.get_id].encode(field)
|
133
|
+
return out
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|