slow_blink 0.0.4 → 0.0.5
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/lexer.c +168 -177
- data/ext/slow_blink/ext_schema_parser/lexer.h +1 -1
- data/ext/slow_blink/ext_schema_parser/parser.c +303 -306
- data/ext/slow_blink/ext_schema_parser/parser.h +11 -12
- data/ext/slow_blink/{ext_compact_encoder → message/ext_compact_encoder}/ext_compact_encoder.c +3 -1
- data/ext/slow_blink/message/ext_compact_encoder/extconf.rb +4 -0
- data/lib/slow_blink/error.rb +1 -1
- data/lib/slow_blink/message/binary.rb +19 -26
- data/lib/slow_blink/message/boolean.rb +17 -17
- data/lib/slow_blink/message/date.rb +24 -0
- data/lib/slow_blink/message/decimal.rb +34 -0
- data/lib/slow_blink/message/enumeration.rb +24 -23
- data/lib/slow_blink/message/field.rb +45 -6
- data/lib/slow_blink/message/fixed.rb +35 -25
- data/lib/slow_blink/message/floating_point.rb +16 -17
- data/lib/slow_blink/message/group.rb +242 -136
- data/lib/slow_blink/message/integer.rb +77 -51
- data/lib/slow_blink/message/model.rb +121 -85
- data/lib/slow_blink/message/sequence.rb +43 -28
- data/lib/slow_blink/message/string.rb +17 -31
- data/lib/slow_blink/message/time.rb +55 -17
- data/lib/slow_blink/message/time_of_day.rb +40 -50
- data/lib/slow_blink/schema.rb +17 -6
- data/lib/slow_blink/version.rb +1 -1
- data/rakefile +12 -7
- data/test/tc_incr_annote.rb +16 -0
- data/test/tc_inputs.rb +2 -2
- data/test/tc_model_dynamic_group.rb +105 -0
- data/test/tc_model_extension.rb +143 -0
- data/test/tc_model_static_group.rb +27 -36
- data/test/tc_model_think_blink.rb +18 -35
- metadata +12 -9
- data/ext/slow_blink/ext_compact_encoder/extconf.rb +0 -4
- /data/ext/slow_blink/{ext_compact_encoder → message/ext_compact_encoder}/compact_encoder.c +0 -0
- /data/ext/slow_blink/{ext_compact_encoder → message/ext_compact_encoder}/compact_encoder.h +0 -0
@@ -19,142 +19,281 @@
|
|
19
19
|
|
20
20
|
module SlowBlink::Message
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
def self.implements
|
25
|
-
@implements
|
26
|
-
end
|
22
|
+
# A Group may form a complete message or be nested as a {DynamicGroup}
|
23
|
+
class Group
|
27
24
|
|
25
|
+
# @return [Hash<Field>] group fields
|
28
26
|
def self.fields
|
29
27
|
@fields
|
30
28
|
end
|
31
29
|
|
32
|
-
|
33
|
-
@opt
|
34
|
-
end
|
35
|
-
|
30
|
+
# @return [Integer,nil] group identifier
|
36
31
|
def self.id
|
37
32
|
@id
|
38
33
|
end
|
39
34
|
|
35
|
+
# @return [String] name of group
|
40
36
|
def self.name
|
41
37
|
@name
|
42
38
|
end
|
43
39
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
40
|
+
# @param input [String] Blink compact form
|
41
|
+
# @param stack [Array] used to measure depth of recursion
|
42
|
+
# @return [Group, nil]
|
43
|
+
# @raise [Error] recursion depth limit
|
44
|
+
def self.from_compact!(input, stack)
|
45
|
+
|
46
|
+
fields = {}
|
47
|
+
extensions = []
|
48
|
+
|
49
|
+
if stack.size < @maxRecursion
|
50
|
+
stack << self
|
55
51
|
else
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
52
|
+
raise Error.new "stack limit"
|
53
|
+
end
|
54
|
+
|
55
|
+
@fields.each do |fn, fd|
|
56
|
+
fields[fn] = fd.from_compact!(input, stack)
|
57
|
+
end
|
58
|
+
|
59
|
+
if input.size > 0
|
60
|
+
expected = input.getU32!
|
61
|
+
while extensions.size != expected do
|
62
|
+
extensions << @extensionObject.from_compact!(input, stack)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if input.size != 0
|
67
|
+
raise Error.new "extra bytes at end of group after extensions"
|
68
|
+
end
|
69
|
+
|
70
|
+
group = self.new(fields)
|
71
|
+
|
72
|
+
extensions.each do |e|
|
73
|
+
group.extension << group
|
74
|
+
end
|
75
|
+
|
76
|
+
stack.pop
|
77
|
+
|
78
|
+
group
|
79
|
+
|
62
80
|
end
|
63
81
|
|
82
|
+
# @return [Array<Group>] group extension objects
|
83
|
+
attr_reader :extension
|
84
|
+
|
85
|
+
# set a field value
|
86
|
+
#
|
87
|
+
# @param name [String] name of field
|
88
|
+
# @param value [Object]
|
89
|
+
# @raise [IndexError, TypeError]
|
64
90
|
def []=(name, value)
|
65
91
|
if @value[name]
|
66
92
|
@value[name].set(value)
|
93
|
+
self
|
67
94
|
else
|
68
|
-
raise "field #{name} is not defined in this group"
|
69
|
-
end
|
95
|
+
raise IndexError.new "field #{name} is not defined in this group"
|
96
|
+
end
|
70
97
|
end
|
71
98
|
|
72
|
-
|
99
|
+
# Get a field value
|
100
|
+
#
|
101
|
+
# @param name [String] name of field
|
102
|
+
# @return [Object]
|
103
|
+
# @raise [IndexError, TypeError]
|
104
|
+
def [](name)
|
73
105
|
if @value[name]
|
74
|
-
@value[name].get
|
106
|
+
@value[name].get
|
75
107
|
else
|
76
|
-
raise "field #{name} is not defined in this group"
|
77
|
-
end
|
108
|
+
raise IndexError.new "field #{name} is not defined in this group"
|
109
|
+
end
|
78
110
|
end
|
79
111
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
112
|
+
# Get this group
|
113
|
+
# @return [Group] self
|
114
|
+
def get
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
# Get the value hash directly
|
119
|
+
# @return [Hash]
|
120
|
+
def fields
|
121
|
+
@value
|
122
|
+
end
|
123
|
+
|
124
|
+
# Set the contents of this group
|
125
|
+
#
|
126
|
+
# This method accepts one of two options:
|
127
|
+
#
|
128
|
+
# First option is a Hash of fields. Values may be literals to be set to fields objects,
|
129
|
+
# or instances of the field objects to completely replace existing field objects
|
130
|
+
#
|
131
|
+
# Second option is a {Group} where #{Group#fields} will be used in the same manner as the first option.
|
132
|
+
#
|
133
|
+
# @param value [Hash, Group] fields to set
|
134
|
+
# @raise [IndexError, TypeError]
|
135
|
+
def set(value)
|
136
|
+
if value.kind_of? Hash
|
137
|
+
value.each do |fn, fv|
|
138
|
+
if @value[fn]
|
139
|
+
# replace entire field
|
140
|
+
if fv.is_a? @value[fn].class
|
141
|
+
@value[fn] = fv
|
142
|
+
# set value of field
|
143
|
+
else
|
144
|
+
@value[fn].set(fv)
|
145
|
+
end
|
146
|
+
else
|
147
|
+
raise IndexError.new "field '#{fn}' is unknown"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
# replace @value with value from another instance of self.class
|
151
|
+
elsif value.is_a? self.class
|
152
|
+
@value = value.fields.to_h
|
88
153
|
else
|
89
|
-
raise "
|
154
|
+
raise TypeError.new "expecting a Hash or a StaticGroup instance"
|
90
155
|
end
|
91
156
|
end
|
92
157
|
|
93
|
-
|
94
|
-
|
158
|
+
# Create a Group
|
159
|
+
#
|
160
|
+
# @param fields [Hash] associative array of slow blink objects or native values
|
161
|
+
def initialize(fields={})
|
162
|
+
@extension = []
|
163
|
+
@fields = self.class.fields
|
164
|
+
@value = {}
|
165
|
+
self.class.fields.each do |fn, fd|
|
166
|
+
@value[fn] = fd.new(nil)
|
167
|
+
end
|
168
|
+
set(fields)
|
169
|
+
end
|
170
|
+
|
171
|
+
def encode_compact
|
172
|
+
if self.class.id
|
173
|
+
to_compact("")
|
174
|
+
else
|
175
|
+
raise Error.new "cannot encode a group without an ID"
|
176
|
+
end
|
95
177
|
end
|
96
178
|
|
97
|
-
def
|
98
|
-
|
99
|
-
@value
|
100
|
-
|
101
|
-
end
|
102
|
-
if fields
|
103
|
-
set(fields.to_h)
|
179
|
+
def to_compact(out)
|
180
|
+
group = "".putU64(self.class.id)
|
181
|
+
@value.each do |fn, fv|
|
182
|
+
fv.to_compact(group)
|
104
183
|
end
|
184
|
+
if @extension.size > 0
|
185
|
+
group.putU32(@extension.size)
|
186
|
+
@extension.each do |e|
|
187
|
+
#if e.is_a? @extensionObject
|
188
|
+
e.to_compact(group)
|
189
|
+
#else
|
190
|
+
# raise Error.new "cannot convert unknown extension object to compact form"
|
191
|
+
#end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
out.putU32(group.size)
|
195
|
+
out << group
|
105
196
|
end
|
106
197
|
|
107
|
-
|
108
|
-
|
198
|
+
end
|
199
|
+
|
200
|
+
# A StaticGroup is a kind of {Group} that can only exist as the contents of a {Field}
|
201
|
+
class StaticGroup < Group
|
202
|
+
|
203
|
+
# @note optionality affects how instances of this type are encoded
|
204
|
+
#
|
205
|
+
# @return [true,false] is optional
|
206
|
+
def self.opt?
|
207
|
+
@opt
|
109
208
|
end
|
209
|
+
|
210
|
+
# @param input [String] Blink compact form
|
211
|
+
# @param stack [Array] used to measure depth of recursion
|
212
|
+
# @return [Group, nil]
|
213
|
+
# @raise [Error] recursion depth limit
|
214
|
+
def self.from_compact!(input, stack)
|
110
215
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
216
|
+
if stack.size < @maxRecursion
|
217
|
+
stack << self
|
218
|
+
else
|
219
|
+
raise Error.new "stack limit"
|
220
|
+
end
|
221
|
+
|
222
|
+
if @opt
|
223
|
+
present = input.getPresent
|
224
|
+
else
|
225
|
+
present = true
|
226
|
+
end
|
227
|
+
if present
|
228
|
+
fields = {}
|
229
|
+
@fields.each do |fn, fd|
|
230
|
+
fields[fn] = fd.from_compact!(input, stack)
|
124
231
|
end
|
232
|
+
result = self.new(fields)
|
125
233
|
else
|
126
|
-
|
234
|
+
nil
|
127
235
|
end
|
236
|
+
|
237
|
+
stack.pop
|
238
|
+
result
|
239
|
+
|
128
240
|
end
|
129
241
|
|
130
|
-
|
131
|
-
|
242
|
+
# @note {StaticGroup} cannot have extensions therefore this method will raise a NoMethodError
|
243
|
+
# @raise [NoMethodError]
|
244
|
+
def extension
|
245
|
+
raise NoMethodError.new "static groups cannot have extensions"
|
246
|
+
end
|
247
|
+
|
248
|
+
def to_compact(out)
|
249
|
+
if self.class.opt?
|
250
|
+
out.putPresent
|
251
|
+
end
|
252
|
+
@value.each do |fn, fv|
|
253
|
+
fv.to_compact(out)
|
254
|
+
end
|
255
|
+
out
|
132
256
|
end
|
133
257
|
|
134
258
|
end
|
135
259
|
|
260
|
+
# A DynamicGroup has a {Group} which has a {Group.id} that appears in {DynamicGroup.permitted} list
|
136
261
|
class DynamicGroup
|
137
|
-
|
262
|
+
|
263
|
+
# @return [Hash] Hash of all groups referenced by name
|
138
264
|
def self.groups
|
139
265
|
@groups
|
140
266
|
end
|
141
267
|
|
268
|
+
# @return [Hash] Hash of all tagged groups referenced by ID
|
269
|
+
def self.taggedGroups
|
270
|
+
@taggedGroups
|
271
|
+
end
|
272
|
+
|
273
|
+
# @return [Array<Integer>] Array of group IDs that can be encapsulated by this DynamicGroup
|
142
274
|
def self.permitted
|
143
275
|
@permitted
|
144
276
|
end
|
145
277
|
|
146
|
-
|
147
|
-
|
148
|
-
|
278
|
+
# @param input [String] Blink compact form
|
279
|
+
# @param stack [Array] used to measure depth of recursion
|
280
|
+
# @return [Group, nil]
|
281
|
+
# @raise [Error] recursion depth limit
|
282
|
+
def self.from_compact!(input, stack)
|
149
283
|
|
150
|
-
|
284
|
+
if stack.size < @maxRecursion
|
285
|
+
stack << self
|
286
|
+
else
|
287
|
+
raise Error.new "stack limit"
|
288
|
+
end
|
289
|
+
|
151
290
|
buf = input.getBinary!
|
152
291
|
if buf.size > 0
|
153
292
|
id = buf.getU64!
|
154
|
-
group = @
|
293
|
+
group = @taggedGroups[id]
|
155
294
|
if group
|
156
295
|
if @permitted.include? group.id
|
157
|
-
self.new(group.from_compact!(buf))
|
296
|
+
result = self.new(group.from_compact!(buf, stack))
|
158
297
|
else
|
159
298
|
raise Error.new "W15: Group is known but unexpected"
|
160
299
|
end
|
@@ -162,84 +301,51 @@ module SlowBlink::Message
|
|
162
301
|
raise Error.new "W2: Group id #{group.id} is unknown"
|
163
302
|
end
|
164
303
|
else
|
165
|
-
|
166
|
-
raise Error.new "W1: Top level group cannot be null"
|
167
|
-
elsif @opt
|
168
|
-
self.new(nil)
|
169
|
-
else
|
170
|
-
raise Error.new "W5: Value cannot be null"
|
171
|
-
end
|
304
|
+
raise Error.new "W5: Value cannot be null"
|
172
305
|
end
|
173
|
-
end
|
174
306
|
|
175
|
-
|
176
|
-
|
177
|
-
@value[name] = value
|
178
|
-
else
|
179
|
-
raise "undefined dynamic group"
|
180
|
-
end
|
181
|
-
end
|
307
|
+
stack.pop
|
308
|
+
result
|
182
309
|
|
183
|
-
def [](name)
|
184
|
-
if @value
|
185
|
-
@value[name]
|
186
|
-
else
|
187
|
-
raise "undefined dynamic group"
|
188
|
-
end
|
189
310
|
end
|
190
311
|
|
191
|
-
def set(value)
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
else
|
200
|
-
raise "value is not a group instance"
|
312
|
+
def set(value)
|
313
|
+
# is group one of the groups we understand?
|
314
|
+
if self.class.taggedGroups.values.detect{|g| value.is_a? g}
|
315
|
+
# is this group permitted?
|
316
|
+
if self.class.permitted.include? value.class.id
|
317
|
+
@value = value
|
318
|
+
else
|
319
|
+
raise "group valid but not expected"
|
201
320
|
end
|
202
|
-
|
203
|
-
|
321
|
+
# native values
|
322
|
+
elsif value.kind_of? Hash
|
323
|
+
@value.set(value)
|
204
324
|
else
|
205
325
|
raise
|
206
|
-
end
|
326
|
+
end
|
207
327
|
end
|
208
328
|
|
329
|
+
# @return [Group] contained group
|
209
330
|
def get
|
210
|
-
@value
|
331
|
+
@value.get
|
211
332
|
end
|
212
333
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
end
|
219
|
-
end
|
334
|
+
# Calls {Group#extension}
|
335
|
+
# @return [Array]
|
336
|
+
def extension
|
337
|
+
@value.extension
|
338
|
+
end
|
220
339
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
out.putU32(group.size)
|
225
|
-
out << group
|
226
|
-
else
|
227
|
-
out.putU32(nil)
|
228
|
-
end
|
340
|
+
# @param value [Group, Hash]
|
341
|
+
def initialize(value)
|
342
|
+
set(value)
|
229
343
|
end
|
230
344
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
#
|
235
|
-
# @return [String]
|
236
|
-
#
|
237
|
-
def encode_compact
|
238
|
-
to_compact
|
239
|
-
end
|
345
|
+
def to_compact(out)
|
346
|
+
@value.to_compact(out)
|
347
|
+
end
|
240
348
|
|
241
349
|
end
|
242
350
|
|
243
|
-
|
244
|
-
|
245
351
|
end
|
@@ -21,70 +21,66 @@ module SlowBlink::Message
|
|
21
21
|
|
22
22
|
class INTEGER
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.opt?
|
29
|
-
@opt
|
30
|
-
end
|
31
|
-
|
24
|
+
# @param value [Integer]
|
25
|
+
# @return [true,false] integer value is within permitted range
|
32
26
|
def self.in_range?(value)
|
33
27
|
@type.class::RANGE.cover? value
|
34
28
|
end
|
35
29
|
|
30
|
+
# @return [Integer]
|
31
|
+
def get
|
32
|
+
@value
|
33
|
+
end
|
34
|
+
|
35
|
+
# Set an Integer value
|
36
|
+
# @param value [Integer]
|
37
|
+
# @raise [RangeError] value is outside of range according to {::in_range?}
|
38
|
+
# @raise [TypeError]
|
36
39
|
def set(value)
|
37
|
-
if value
|
38
|
-
if
|
39
|
-
|
40
|
-
@value = value.to_i
|
41
|
-
else
|
42
|
-
raise Error.new "value out of range"
|
43
|
-
end
|
40
|
+
if value.kind_of? Integer
|
41
|
+
if self.class.in_range?(value)
|
42
|
+
@value = value.to_i
|
44
43
|
else
|
45
|
-
raise
|
44
|
+
raise RangeError.new
|
46
45
|
end
|
47
|
-
elsif self.class.opt?
|
48
|
-
@value = nil
|
49
46
|
else
|
50
|
-
raise
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def get
|
55
|
-
@value
|
47
|
+
raise TypeError.new "value must be an integer"
|
48
|
+
end
|
56
49
|
end
|
57
50
|
|
58
|
-
# @
|
59
|
-
def initialize(value)
|
60
|
-
|
61
|
-
set(value)
|
62
|
-
else
|
63
|
-
@value = nil
|
64
|
-
end
|
51
|
+
# @note calls {#set}(value)
|
52
|
+
def initialize(value)
|
53
|
+
set(value)
|
65
54
|
end
|
66
55
|
|
67
|
-
|
68
56
|
end
|
69
57
|
|
70
58
|
class U8 < INTEGER
|
71
59
|
|
72
|
-
|
73
|
-
|
74
|
-
|
60
|
+
def self.from_compact!(input, stack)
|
61
|
+
value = input.getU8!
|
62
|
+
if value
|
63
|
+
self.new(value)
|
64
|
+
else
|
65
|
+
value
|
66
|
+
end
|
75
67
|
end
|
76
68
|
|
77
69
|
def to_compact(out)
|
78
70
|
out.putU8(@value)
|
79
|
-
end
|
80
|
-
|
71
|
+
end
|
81
72
|
|
82
73
|
end
|
83
74
|
|
84
75
|
class U16 < INTEGER
|
85
76
|
|
86
|
-
def self.from_compact!(input)
|
87
|
-
|
77
|
+
def self.from_compact!(input, stack)
|
78
|
+
value = input.getU16!
|
79
|
+
if value
|
80
|
+
self.new(value)
|
81
|
+
else
|
82
|
+
value
|
83
|
+
end
|
88
84
|
end
|
89
85
|
|
90
86
|
def to_compact(out)
|
@@ -95,8 +91,13 @@ module SlowBlink::Message
|
|
95
91
|
|
96
92
|
class U32 < INTEGER
|
97
93
|
|
98
|
-
def self.from_compact!(input)
|
99
|
-
|
94
|
+
def self.from_compact!(input, stack)
|
95
|
+
value = input.getU32!
|
96
|
+
if value
|
97
|
+
self.new(value)
|
98
|
+
else
|
99
|
+
value
|
100
|
+
end
|
100
101
|
end
|
101
102
|
|
102
103
|
def to_compact(out)
|
@@ -107,8 +108,13 @@ module SlowBlink::Message
|
|
107
108
|
|
108
109
|
class U64 < INTEGER
|
109
110
|
|
110
|
-
def self.from_compact!(input)
|
111
|
-
|
111
|
+
def self.from_compact!(input, stack)
|
112
|
+
value = input.getU64!
|
113
|
+
if value
|
114
|
+
self.new(value)
|
115
|
+
else
|
116
|
+
value
|
117
|
+
end
|
112
118
|
end
|
113
119
|
|
114
120
|
def to_compact(out)
|
@@ -119,8 +125,13 @@ module SlowBlink::Message
|
|
119
125
|
|
120
126
|
class I8 < INTEGER
|
121
127
|
|
122
|
-
def self.from_compact!(input)
|
123
|
-
|
128
|
+
def self.from_compact!(input, stack)
|
129
|
+
value = input.getI8!
|
130
|
+
if value
|
131
|
+
self.new(value)
|
132
|
+
else
|
133
|
+
value
|
134
|
+
end
|
124
135
|
end
|
125
136
|
|
126
137
|
def to_compact(out)
|
@@ -131,8 +142,13 @@ module SlowBlink::Message
|
|
131
142
|
|
132
143
|
class I16 < INTEGER
|
133
144
|
|
134
|
-
def self.from_compact!(input)
|
135
|
-
|
145
|
+
def self.from_compact!(input, stack)
|
146
|
+
value = input.getI16!
|
147
|
+
if value
|
148
|
+
self.new(value)
|
149
|
+
else
|
150
|
+
value
|
151
|
+
end
|
136
152
|
end
|
137
153
|
|
138
154
|
def to_compact(out)
|
@@ -143,8 +159,13 @@ module SlowBlink::Message
|
|
143
159
|
|
144
160
|
class I32 < INTEGER
|
145
161
|
|
146
|
-
def self.from_compact!(input)
|
147
|
-
|
162
|
+
def self.from_compact!(input, stack)
|
163
|
+
value = input.getI32!
|
164
|
+
if value
|
165
|
+
self.new(value)
|
166
|
+
else
|
167
|
+
value
|
168
|
+
end
|
148
169
|
end
|
149
170
|
|
150
171
|
def to_compact(out)
|
@@ -155,8 +176,13 @@ module SlowBlink::Message
|
|
155
176
|
|
156
177
|
class I64 < INTEGER
|
157
178
|
|
158
|
-
def self.from_compact!(input)
|
159
|
-
|
179
|
+
def self.from_compact!(input, stack)
|
180
|
+
value = input.getI64!
|
181
|
+
if value
|
182
|
+
self.new(value)
|
183
|
+
else
|
184
|
+
value
|
185
|
+
end
|
160
186
|
end
|
161
187
|
|
162
188
|
def to_compact(out)
|