slow_blink 0.0.7 → 0.0.8
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.
- checksums.yaml +4 -4
- data/ext/slow_blink/ext_schema_parser/extconf.rb +1 -0
- data/ext/slow_blink/ext_schema_parser/lexer.c +6 -8
- data/ext/slow_blink/ext_schema_parser/lexer.h +1 -1
- data/ext/slow_blink/ext_schema_parser/parser.c +3 -1
- data/ext/slow_blink/message/ext_compact_encoder/ext_compact_encoder.c +46 -24
- data/ext/slow_blink/message/ext_compact_encoder/extconf.rb +9 -2
- data/lib/slow_blink/enum.rb +4 -1
- data/lib/slow_blink/field.rb +1 -1
- data/lib/slow_blink/generate_c/model.rb +119 -12
- data/lib/slow_blink/message/binary.rb +9 -1
- data/lib/slow_blink/message/boolean.rb +12 -3
- data/lib/slow_blink/message/date.rb +9 -1
- data/lib/slow_blink/message/decimal.rb +9 -1
- data/lib/slow_blink/message/dynamic_group.rb +132 -0
- data/lib/slow_blink/message/enum.rb +6 -2
- data/lib/slow_blink/message/field.rb +67 -43
- data/lib/slow_blink/message/fixed.rb +5 -1
- data/lib/slow_blink/message/floating_point.rb +9 -1
- data/lib/slow_blink/message/group.rb +54 -197
- data/lib/slow_blink/message/integer.rb +16 -8
- data/lib/slow_blink/message/model.rb +20 -18
- data/lib/slow_blink/message/static_group.rb +63 -0
- data/lib/slow_blink/message/string.rb +9 -1
- data/lib/slow_blink/message/test_data.rb +126 -0
- data/lib/slow_blink/message/time.rb +10 -2
- data/lib/slow_blink/message/time_of_day.rb +18 -2
- data/lib/slow_blink/schema.rb +2 -2
- data/lib/slow_blink/type.rb +3 -3
- data/lib/slow_blink/version.rb +1 -1
- data/test/tc_inputs.rb +34 -25
- data/test/tc_model_enum.rb +47 -0
- data/test/tc_model_inputs.rb +47 -0
- metadata +9 -7
- data/ext/slow_blink/message/ext_compact_encoder/blink_compact.c +0 -642
- data/ext/slow_blink/message/ext_compact_encoder/blink_compact.h +0 -411
- data/ext/slow_blink/message/ext_compact_encoder/blink_debug.h +0 -46
- data/ext/slow_blink/message/ext_compact_encoder/blink_stream.c +0 -314
- data/ext/slow_blink/message/ext_compact_encoder/blink_stream.h +0 -185
@@ -0,0 +1,132 @@
|
|
1
|
+
# @license
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 Cameron Harper
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
# this software and associated documentation files (the "Software"), to deal in
|
7
|
+
# the Software without restriction, including without limitation the rights to
|
8
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
# subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
module SlowBlink::Message
|
23
|
+
|
24
|
+
class DynamicGroup
|
25
|
+
|
26
|
+
def self.taggedGroups
|
27
|
+
@taggedGroups
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.permittedID
|
31
|
+
@permittedID
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.from_compact(input, depth)
|
35
|
+
|
36
|
+
group = nil
|
37
|
+
|
38
|
+
if depth > 0
|
39
|
+
depth = depth - 1
|
40
|
+
else
|
41
|
+
raise RecursionLimit
|
42
|
+
end
|
43
|
+
|
44
|
+
if input.kind_of? String
|
45
|
+
input = StringIO.new(input)
|
46
|
+
end
|
47
|
+
|
48
|
+
buf = input.getBinary
|
49
|
+
|
50
|
+
if buf.nil?
|
51
|
+
|
52
|
+
group = nil
|
53
|
+
|
54
|
+
elsif buf.size == 0
|
55
|
+
|
56
|
+
raise WeakError5.new "W5: Value cannot be null"
|
57
|
+
|
58
|
+
else
|
59
|
+
|
60
|
+
buf = StringIO.new(buf)
|
61
|
+
id = buf.getU64
|
62
|
+
|
63
|
+
if klass = @taggedGroups[id]
|
64
|
+
|
65
|
+
if @permittedID.include? id
|
66
|
+
|
67
|
+
group = klass.from_compact(buf, depth)
|
68
|
+
|
69
|
+
if !buf.eof?
|
70
|
+
size = buf.getU32
|
71
|
+
while group.extension.size < size do
|
72
|
+
group.extension << @anyTaggedGroup.from_compact(buf, depth).get
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if !buf.eof?
|
77
|
+
raise ExtensionPadding
|
78
|
+
end
|
79
|
+
|
80
|
+
else
|
81
|
+
raise WeakError15.new "W15: Group is known but unexpected"
|
82
|
+
end
|
83
|
+
else
|
84
|
+
raise WeakError2.new "W2: Group id #{id} is unknown"
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
depth = depth + 1
|
90
|
+
self.new(group)
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
def set(value)
|
95
|
+
if value.kind_of? Group
|
96
|
+
if self.class.permittedID.include? value.class.id
|
97
|
+
@value = value
|
98
|
+
else
|
99
|
+
raise TypeError.new "incompatible group"
|
100
|
+
end
|
101
|
+
else
|
102
|
+
raise ArgumentError.new "argument must be kind_of Group"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [Group] contained group
|
107
|
+
def get
|
108
|
+
@value.get
|
109
|
+
end
|
110
|
+
|
111
|
+
# @note calls {#set}(value)
|
112
|
+
def initialize(value)
|
113
|
+
set(value)
|
114
|
+
end
|
115
|
+
|
116
|
+
# @private
|
117
|
+
def to_compact(out)
|
118
|
+
@value.encode_compact(out)
|
119
|
+
end
|
120
|
+
|
121
|
+
def extension
|
122
|
+
@value.extension
|
123
|
+
end
|
124
|
+
|
125
|
+
def to_tag
|
126
|
+
"@#{@value.class.name}#{@value.to_tag_value}#{@value.to_tag_extension}"
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
@@ -29,7 +29,7 @@ module SlowBlink::Message
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# @private
|
32
|
-
def self.from_compact(input,
|
32
|
+
def self.from_compact(input, depth)
|
33
33
|
if value = input.getI32
|
34
34
|
if symbol = type.symbol(value)
|
35
35
|
self.new(symbol.name)
|
@@ -68,7 +68,11 @@ module SlowBlink::Message
|
|
68
68
|
|
69
69
|
# @private
|
70
70
|
def to_compact(out)
|
71
|
-
out.putI32(self.class.type.symbol(@value).value)
|
71
|
+
out.putI32(self.class.type.symbol(@value).value)
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_tag
|
75
|
+
@value
|
72
76
|
end
|
73
77
|
|
74
78
|
end
|
@@ -51,70 +51,84 @@ module SlowBlink::Message
|
|
51
51
|
|
52
52
|
# @private
|
53
53
|
# @param input [String] Blink compact form
|
54
|
-
# @param
|
54
|
+
# @param depth [Array]
|
55
55
|
# @return [Field] instance of anonymous subclass of Field
|
56
|
-
def self.from_compact(input,
|
57
|
-
|
58
|
-
if size = input.getU32
|
59
|
-
value = []
|
60
|
-
while value.size < size do
|
61
|
-
value << @type.from_compact(input, stack).get
|
62
|
-
end
|
63
|
-
self.new(value)
|
64
|
-
else
|
65
|
-
nil
|
66
|
-
end
|
67
|
-
elsif optional? and (type.kind_of? StaticGroup or type.kind_of? FIXED)
|
68
|
-
if input.get_present(input)
|
69
|
-
self.new(@type.from_compact(input, stack).get)
|
70
|
-
else
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
else
|
74
|
-
self.new(@type.from_compact(input, stack).get)
|
75
|
-
end
|
56
|
+
def self.from_compact(input, depth)
|
57
|
+
self.new(input, depth)
|
76
58
|
end
|
77
59
|
|
78
|
-
|
79
|
-
|
60
|
+
attr_reader :type
|
61
|
+
|
62
|
+
def sequence?
|
63
|
+
@sequence
|
64
|
+
end
|
65
|
+
def optional?
|
66
|
+
@optional
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize(input=nil, depth=nil)
|
80
70
|
|
81
71
|
@optional = self.class.optional?
|
82
72
|
@sequence = self.class.sequence?
|
83
73
|
@type = self.class.type
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
74
|
+
@value = nil
|
75
|
+
|
76
|
+
if input and depth
|
77
|
+
if @sequence
|
78
|
+
if size = input.getU32
|
79
|
+
@value = []
|
80
|
+
size.times do
|
81
|
+
value = @type.from_compact(input, depth)
|
82
|
+
if value
|
83
|
+
@value << value
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
elsif @optional and (@type.kind_of? StaticGroup or @type.kind_of? FIXED)
|
88
|
+
if input.get_present
|
89
|
+
@value = @type.from_compact(input, depth)
|
90
|
+
end
|
91
|
+
else
|
92
|
+
@value = @type.from_compact(input, depth)
|
93
|
+
end
|
94
|
+
|
89
95
|
end
|
90
|
-
|
96
|
+
|
91
97
|
end
|
92
98
|
|
93
|
-
def set(value)
|
94
|
-
if value.
|
95
|
-
|
99
|
+
def set(value)
|
100
|
+
if value.kind_of? Field
|
101
|
+
self.set(value.get)
|
102
|
+
elsif value.nil?
|
103
|
+
if @optional
|
96
104
|
@value = nil
|
105
|
+
self
|
97
106
|
else
|
98
|
-
raise ArgumentError.new "field is not optional, value cannot be nil"
|
107
|
+
raise ArgumentError.new "field '#{self.class.name}'is not optional, value cannot be nil (sequence: #{@sequence})"
|
99
108
|
end
|
100
|
-
elsif
|
109
|
+
elsif @sequence
|
101
110
|
if value.kind_of? Array
|
102
111
|
@value = []
|
103
112
|
value.each do |v|
|
113
|
+
if v.nil?
|
114
|
+
next
|
115
|
+
end
|
104
116
|
@value << @type.new(v)
|
105
117
|
end
|
118
|
+
self
|
106
119
|
else
|
107
120
|
raise ArgumentError.new "field value must be an array of type"
|
108
121
|
end
|
109
122
|
else
|
110
123
|
@value = @type.new(value)
|
111
|
-
|
124
|
+
self
|
125
|
+
end
|
112
126
|
end
|
113
127
|
|
114
128
|
# @return field value or nil
|
115
129
|
def get
|
116
130
|
if @value
|
117
|
-
if
|
131
|
+
if @sequence
|
118
132
|
@value.map{|v|v.get}
|
119
133
|
else
|
120
134
|
@value.get
|
@@ -129,7 +143,7 @@ module SlowBlink::Message
|
|
129
143
|
# @return [StringIO]
|
130
144
|
def to_compact(out)
|
131
145
|
if @value
|
132
|
-
if
|
146
|
+
if @sequence
|
133
147
|
out.putU32(@value.size)
|
134
148
|
@value.each do |v|
|
135
149
|
v.to_compact(out)
|
@@ -143,16 +157,26 @@ module SlowBlink::Message
|
|
143
157
|
elsif @optional
|
144
158
|
out.putNull
|
145
159
|
else
|
146
|
-
raise IncompleteGroup.new "'#{self.name}' must not be null"
|
160
|
+
raise IncompleteGroup.new "'#{self.class.name}' must not be null"
|
147
161
|
end
|
148
162
|
end
|
149
163
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
164
|
+
def to_tag
|
165
|
+
if @value
|
166
|
+
if @value.is_a? Array
|
167
|
+
@value.inject("|#{self.class.name}=[") do |out,v|
|
168
|
+
if @value.first != v
|
169
|
+
out << ";"
|
170
|
+
end
|
171
|
+
out << v.to_tag
|
172
|
+
end << "]"
|
173
|
+
else
|
174
|
+
"|#{self.class.name}=#{@value.to_tag}"
|
175
|
+
end
|
176
|
+
else
|
177
|
+
""
|
155
178
|
end
|
179
|
+
end
|
156
180
|
|
157
181
|
end
|
158
182
|
|
@@ -24,8 +24,12 @@ module SlowBlink::Message
|
|
24
24
|
# @abstract
|
25
25
|
class FIXED
|
26
26
|
|
27
|
+
def self.type
|
28
|
+
@type
|
29
|
+
end
|
30
|
+
|
27
31
|
# @private
|
28
|
-
def self.from_compact(input,
|
32
|
+
def self.from_compact(input, depth)
|
29
33
|
if value = input.getFixed(size)
|
30
34
|
self.new(value)
|
31
35
|
else
|
@@ -24,8 +24,12 @@ module SlowBlink::Message
|
|
24
24
|
# @abstract
|
25
25
|
class FLOATING_POINT
|
26
26
|
|
27
|
+
def self.type
|
28
|
+
@type
|
29
|
+
end
|
30
|
+
|
27
31
|
# @private
|
28
|
-
def self.from_compact(input,
|
32
|
+
def self.from_compact(input, depth)
|
29
33
|
if value = input.getF64
|
30
34
|
self.new(value)
|
31
35
|
else
|
@@ -58,6 +62,10 @@ module SlowBlink::Message
|
|
58
62
|
out.putF64(@value)
|
59
63
|
end
|
60
64
|
|
65
|
+
def to_tag
|
66
|
+
@value.to_s
|
67
|
+
end
|
68
|
+
|
61
69
|
end
|
62
70
|
|
63
71
|
end
|
@@ -21,7 +21,9 @@
|
|
21
21
|
|
22
22
|
module SlowBlink::Message
|
23
23
|
|
24
|
-
class
|
24
|
+
class Group
|
25
|
+
|
26
|
+
attr_reader :extension
|
25
27
|
|
26
28
|
# @private
|
27
29
|
# @return [Array<Field>] group fields
|
@@ -41,30 +43,37 @@ module SlowBlink::Message
|
|
41
43
|
@name
|
42
44
|
end
|
43
45
|
|
46
|
+
def self.ancestorID
|
47
|
+
@ancestorID
|
48
|
+
end
|
49
|
+
|
44
50
|
# @private
|
45
|
-
|
46
|
-
# @param stack [Array] used to measure depth of recursion
|
47
|
-
# @return [Group, nil]
|
48
|
-
# @raise [Error] recursion depth limit
|
49
|
-
def self.from_compact(input, stack)
|
51
|
+
def self.from_compact(input, depth)
|
50
52
|
|
51
|
-
|
53
|
+
value = {}
|
52
54
|
|
53
|
-
if
|
54
|
-
|
55
|
+
if depth > 0
|
56
|
+
depth = depth - 1
|
55
57
|
else
|
56
58
|
raise RecursionLimit
|
57
59
|
end
|
58
60
|
|
59
61
|
@fields.each do |f|
|
60
|
-
|
62
|
+
value[f.name] = f.from_compact(input, depth)
|
61
63
|
end
|
62
64
|
|
63
|
-
|
64
|
-
|
65
|
-
self.new(
|
65
|
+
depth = depth + 1
|
66
|
+
|
67
|
+
self.new(value)
|
66
68
|
|
67
69
|
end
|
70
|
+
|
71
|
+
def initialize(fields={}, *extension)
|
72
|
+
@value = {}
|
73
|
+
self.class.fields.each{|f|@value[f.name] = f.new}
|
74
|
+
set(fields)
|
75
|
+
@extension = extension
|
76
|
+
end
|
68
77
|
|
69
78
|
# @api user
|
70
79
|
# Finds Field by name and calls {Field#set}(value)
|
@@ -74,7 +83,7 @@ module SlowBlink::Message
|
|
74
83
|
# @raise [IndexError, TypeError]
|
75
84
|
def []=(name, value)
|
76
85
|
if field = @value[name]
|
77
|
-
field.set(value)
|
86
|
+
@value[name] = field.set(value)
|
78
87
|
else
|
79
88
|
raise IndexError.new "field #{name} is not defined in this group"
|
80
89
|
end
|
@@ -95,219 +104,67 @@ module SlowBlink::Message
|
|
95
104
|
end
|
96
105
|
end
|
97
106
|
|
98
|
-
# Get this group
|
99
|
-
# @return [self]
|
100
|
-
def get
|
101
|
-
self
|
102
|
-
end
|
103
|
-
|
104
|
-
# Set the contents of this group
|
105
|
-
#
|
106
|
-
# @overload set(value)
|
107
|
-
# @param value [Hash{String=>Field,Numeric,String,Time,nil}] Hash of {Field} objects or literal values
|
108
|
-
# @overload set(value)
|
109
|
-
# @param value [Group] a Hash of {Field} objects will be extracted from a Group object by calling {Group#fields}
|
110
|
-
# @return [self]
|
111
|
-
# @raise [IndexError, TypeError]
|
112
107
|
def set(value)
|
113
|
-
|
114
108
|
if value.kind_of? Hash
|
115
109
|
value.each do |fn, fv|
|
116
110
|
if @value[fn]
|
117
|
-
|
118
|
-
if fv.is_a? @value[fn].class
|
119
|
-
@value[fn] = fv
|
120
|
-
# set value of field
|
121
|
-
else
|
122
|
-
@value[fn].set(fv)
|
123
|
-
end
|
111
|
+
@value[fn] = @value[fn].set(fv)
|
124
112
|
else
|
125
113
|
raise IndexError.new "field '#{fn}' is unknown"
|
126
114
|
end
|
127
|
-
end
|
128
|
-
# replace @value with value from another instance of self.class
|
129
|
-
elsif value.kind_of? self.class
|
130
|
-
@value = value.fields.to_h
|
115
|
+
end
|
131
116
|
else
|
132
|
-
raise TypeError.new "expecting a Hash
|
117
|
+
raise TypeError.new "expecting a Hash instance"
|
133
118
|
end
|
134
119
|
self
|
135
120
|
end
|
136
121
|
|
137
|
-
|
138
|
-
|
139
|
-
#
|
140
|
-
# @note calls {#set}(fields)
|
141
|
-
# @param fields [Hash]
|
142
|
-
def initialize(fields={})
|
143
|
-
@value = {}
|
144
|
-
self.class.fields.each do |f|
|
145
|
-
@value[f.name] = f.new(nil)
|
146
|
-
end
|
147
|
-
set(fields)
|
148
|
-
end
|
149
|
-
|
150
|
-
# @return [String] Blink Protocol compact form
|
151
|
-
def encode_compact
|
152
|
-
if self.class.id
|
153
|
-
to_compact("")
|
154
|
-
else
|
155
|
-
raise UntaggedGroup.new "cannot encode a group without an ID"
|
156
|
-
end
|
122
|
+
def get
|
123
|
+
self
|
157
124
|
end
|
158
125
|
|
159
126
|
# @private
|
160
127
|
def to_compact(out)
|
161
|
-
@value.each
|
162
|
-
fv.to_compact(out)
|
163
|
-
end
|
128
|
+
@value.values.each{|f|f.to_compact(out)}
|
164
129
|
end
|
165
130
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
131
|
+
def encode_compact(out="".force_encoding("ASCII-8BIT"))
|
132
|
+
if self.class.id
|
133
|
+
groupOut = String.new.putU64(self.class.id)
|
134
|
+
to_compact(groupOut)
|
135
|
+
if @extension.size > 0
|
136
|
+
groupOut.putU32(@extension.size)
|
137
|
+
@extension.each{|e|e.encode_compact(groupOut)}
|
138
|
+
end
|
139
|
+
|
140
|
+
out.putU32(groupOut.size)
|
141
|
+
out << groupOut
|
142
|
+
else
|
143
|
+
raise UntaggedGroup.new "cannot encode a group without an ID"
|
172
144
|
end
|
173
|
-
|
174
|
-
end
|
175
|
-
|
176
|
-
class Group < StaticGroup
|
177
|
-
|
178
|
-
attr_reader :extension
|
179
|
-
|
180
|
-
def self.ancestorID
|
181
|
-
@ancestorID
|
182
145
|
end
|
183
146
|
|
184
|
-
def
|
185
|
-
|
186
|
-
@extension = extension
|
147
|
+
def to_tag_value
|
148
|
+
@value.values.inject(""){|out,f|out << f.to_tag}
|
187
149
|
end
|
188
150
|
|
189
|
-
|
190
|
-
def to_compact(out)
|
191
|
-
|
192
|
-
groupOut = String.new.putU64(self.class.id)
|
193
|
-
super(groupOut)
|
151
|
+
def to_tag_extension
|
194
152
|
if @extension.size > 0
|
195
|
-
|
153
|
+
out = "|["
|
196
154
|
@extension.each do |e|
|
197
|
-
e.
|
198
|
-
|
199
|
-
end
|
200
|
-
|
201
|
-
out.putU32(groupOut.size)
|
202
|
-
out << groupOut
|
203
|
-
|
204
|
-
end
|
205
|
-
|
206
|
-
end
|
207
|
-
|
208
|
-
class DynamicGroup
|
209
|
-
|
210
|
-
def self.taggedGroups
|
211
|
-
@taggedGroups
|
212
|
-
end
|
213
|
-
|
214
|
-
def self.permittedID
|
215
|
-
@permittedID
|
216
|
-
end
|
217
|
-
|
218
|
-
# @private
|
219
|
-
# @param input [StringIO] Blink compact form
|
220
|
-
# @param stack [Array] used to measure depth of recursion
|
221
|
-
# @return [Group, nil]
|
222
|
-
# @raise [Error] recursion depth limit
|
223
|
-
def self.from_compact(input, stack)
|
224
|
-
|
225
|
-
group = nil
|
226
|
-
|
227
|
-
if stack.size < @maxRecursion
|
228
|
-
stack << self
|
229
|
-
else
|
230
|
-
raise RecursionLimit
|
231
|
-
end
|
232
|
-
|
233
|
-
if input.kind_of? String
|
234
|
-
input = StringIO.new(input)
|
235
|
-
end
|
236
|
-
|
237
|
-
buf = input.getBinary
|
238
|
-
|
239
|
-
if buf.size > 0
|
240
|
-
|
241
|
-
buf = StringIO.new(buf)
|
242
|
-
id = buf.getU64
|
243
|
-
|
244
|
-
if klass = @taggedGroups[id]
|
245
|
-
|
246
|
-
if @permittedID.include? id
|
247
|
-
|
248
|
-
group = klass.from_compact(buf, stack)
|
249
|
-
|
250
|
-
if !buf.eof?
|
251
|
-
size = buf.getU32
|
252
|
-
while group.extension.size < size do
|
253
|
-
group.extension << @anyTaggedGroup.from_compact(buf, stack)
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
if !buf.eof?
|
258
|
-
raise ExtensionPadding
|
259
|
-
end
|
260
|
-
|
261
|
-
else
|
262
|
-
raise WeakError15.new "W15: Group is known but unexpected"
|
155
|
+
if e != @extension.first
|
156
|
+
out << ";"
|
263
157
|
end
|
264
|
-
|
265
|
-
raise WeakError2.new "W2: Group id #{id} is unknown"
|
266
|
-
end
|
267
|
-
|
268
|
-
elsif stack.size == 1
|
269
|
-
raise WeakError5.new "W??: top level cannot be null"
|
270
|
-
else
|
271
|
-
raise WeakError5.new "W5: Value cannot be null"
|
272
|
-
end
|
273
|
-
|
274
|
-
stack.pop
|
275
|
-
group
|
276
|
-
|
277
|
-
end
|
278
|
-
|
279
|
-
def set(value)
|
280
|
-
if value.kind_of? Group
|
281
|
-
if self.class.permittedID.include? value.class.id
|
282
|
-
@value = value
|
283
|
-
else
|
284
|
-
raise TypeError.new "incompatible group"
|
158
|
+
out << e.to_tag
|
285
159
|
end
|
286
|
-
|
287
|
-
elsif value.kind_of? Hash
|
288
|
-
@value.set(value)
|
160
|
+
out << "]"
|
289
161
|
else
|
290
|
-
|
291
|
-
end
|
292
|
-
end
|
293
|
-
|
294
|
-
# @return [Group] contained group
|
295
|
-
def get
|
296
|
-
@value.get
|
297
|
-
end
|
298
|
-
|
299
|
-
# @note calls {#set}(value)
|
300
|
-
def initialize(value)
|
301
|
-
set(value)
|
302
|
-
end
|
303
|
-
|
304
|
-
# @private
|
305
|
-
def to_compact(out)
|
306
|
-
@value.to_compact(out)
|
162
|
+
out = ""
|
163
|
+
end
|
307
164
|
end
|
308
165
|
|
309
|
-
def
|
310
|
-
|
166
|
+
def to_tag
|
167
|
+
"@#{self.class.name}#{to_tag_value}#{to_tag_extension}"
|
311
168
|
end
|
312
169
|
|
313
170
|
end
|