bare-rb 0.1.5 → 0.2.3
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/lib/bare-rb.rb +43 -47
- data/lib/dfs.rb +14 -0
- data/lib/exceptions.rb +18 -0
- data/lib/generative_testing/gen.rb +26 -0
- data/lib/generative_testing/grammar_util.rb +22 -0
- data/lib/generative_testing/monkey_patch.rb +262 -0
- data/lib/lexer.rb +3 -2
- data/lib/parser.rb +1 -1
- data/lib/types.rb +442 -249
- metadata +8 -4
data/lib/types.rb
CHANGED
@@ -7,6 +7,128 @@ class BareTypes
|
|
7
7
|
@finalized = false
|
8
8
|
super
|
9
9
|
end
|
10
|
+
def cycle_search(seen)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Schema
|
15
|
+
attr_accessor :types
|
16
|
+
|
17
|
+
def initialize(types)
|
18
|
+
@types = types.map { |k, v| [k.to_sym, v] }.to_h
|
19
|
+
@types.each do |k, v|
|
20
|
+
unless k.is_a?(Symbol)
|
21
|
+
raise("Keys to a schema must be symbols")
|
22
|
+
end
|
23
|
+
if v.nil?
|
24
|
+
raise("Schema values cannot be nil")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Resolve references in schema
|
29
|
+
# type A u8
|
30
|
+
# type B A
|
31
|
+
# type C B
|
32
|
+
# first loop would find B and make it a reference to A
|
33
|
+
# second loop would find C and make it a reference to B
|
34
|
+
progress = true
|
35
|
+
remaining = @types.keys.to_a
|
36
|
+
while progress
|
37
|
+
progress = false
|
38
|
+
remaining.each do |key|
|
39
|
+
val = @types[key]
|
40
|
+
if val.is_a?(Symbol) && !@types[val].is_a?(Symbol)
|
41
|
+
@types[key.to_sym] = BareTypes::Reference.new(key, @types[val])
|
42
|
+
progress = true
|
43
|
+
else
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
@types.each do |key, val|
|
49
|
+
if val.is_a?(Symbol)
|
50
|
+
raise ReferenceException.new("Your types contain an unresolved reference '#{val}'.")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@types.values.each do |val|
|
55
|
+
val.finalize_references(@types)
|
56
|
+
end
|
57
|
+
|
58
|
+
@types.each do |key, val|
|
59
|
+
val.cycle_search(SeenList.new)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def ==(otherSchema)
|
64
|
+
return false unless otherSchema.is_a?(BareTypes::Schema)
|
65
|
+
@types == otherSchema.types
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
buffer = ""
|
70
|
+
@types.each do |name, type|
|
71
|
+
if type.is_a?(BareTypes::Enum)
|
72
|
+
buffer << "enum #{name} "
|
73
|
+
type.to_schema(buffer)
|
74
|
+
buffer << "\n"
|
75
|
+
else
|
76
|
+
buffer << "type #{name} "
|
77
|
+
type.to_schema(buffer)
|
78
|
+
buffer << "\n"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
buffer
|
82
|
+
end
|
83
|
+
|
84
|
+
def [](key)
|
85
|
+
return @types[key]
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Used to represent a Type reference in a schema.
|
90
|
+
# eg. test8.schema's address field on Customer contains 'Address'
|
91
|
+
# a reference to the Address type defined earlier.
|
92
|
+
class Reference < BaseType
|
93
|
+
attr_accessor :name
|
94
|
+
attr_accessor :ref
|
95
|
+
|
96
|
+
def cycle_search(seen)
|
97
|
+
seen.add(self)
|
98
|
+
@ref.cycle_search(seen)
|
99
|
+
seen.pop
|
100
|
+
end
|
101
|
+
|
102
|
+
def ==(other)
|
103
|
+
other.is_a?(Reference) && @name == other.name && @ref == other.ref
|
104
|
+
end
|
105
|
+
|
106
|
+
def initialize(name, reference)
|
107
|
+
@name = name
|
108
|
+
@ref = reference
|
109
|
+
@finalized = false
|
110
|
+
unless reference.is_a?(BareTypes::BaseType)
|
111
|
+
raise ReferenceException.new("Reference must be to bare types")
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def finalize_references(schema)
|
116
|
+
return if @finalized
|
117
|
+
@finalized = true
|
118
|
+
self.ref.finalize_references(schema)
|
119
|
+
end
|
120
|
+
|
121
|
+
def encode(msg, buffer)
|
122
|
+
@ref.encode(msg, buffer)
|
123
|
+
end
|
124
|
+
|
125
|
+
def decode(msg)
|
126
|
+
@ref.decode(msg)
|
127
|
+
end
|
128
|
+
|
129
|
+
def to_schema(buffer)
|
130
|
+
buffer << @name.to_s
|
131
|
+
end
|
10
132
|
end
|
11
133
|
|
12
134
|
class BarePrimitive < BaseType
|
@@ -20,29 +142,33 @@ class BareTypes
|
|
20
142
|
self.class == other.class
|
21
143
|
end
|
22
144
|
|
23
|
-
def finalize_references(schema)
|
145
|
+
def finalize_references(schema) end
|
146
|
+
|
147
|
+
def to_schema(buffer)
|
148
|
+
buffer << self.class.name.split('::').last.downcase
|
24
149
|
end
|
25
150
|
|
26
151
|
end
|
27
152
|
|
153
|
+
#region Primitives
|
28
154
|
class Int < BarePrimitive
|
29
155
|
# https://developers.google.com/protocol-buffers/docs/encoding
|
30
156
|
# Easy to just convert to signed and re-use uint code
|
31
|
-
def encode(msg)
|
157
|
+
def encode(msg, buffer)
|
32
158
|
mappedInteger = msg < 0 ? -2 * msg - 1 : msg * 2
|
33
|
-
|
159
|
+
Uint.new.encode(mappedInteger, buffer)
|
34
160
|
end
|
35
161
|
|
36
162
|
def decode(msg)
|
37
163
|
value, rest = Uint.new.decode(msg)
|
38
164
|
value = value.odd? ? (value + 1) / -2 : value / 2
|
39
|
-
return
|
165
|
+
return value, rest
|
40
166
|
end
|
41
167
|
end
|
42
168
|
|
43
169
|
class Void < BarePrimitive
|
44
|
-
def encode(msg)
|
45
|
-
|
170
|
+
def encode(msg, buffer)
|
171
|
+
buffer << "".b
|
46
172
|
end
|
47
173
|
|
48
174
|
def decode(msg)
|
@@ -51,8 +177,8 @@ class BareTypes
|
|
51
177
|
end
|
52
178
|
|
53
179
|
class F32 < BarePrimitive
|
54
|
-
def encode(msg)
|
55
|
-
[msg].pack("e")
|
180
|
+
def encode(msg, buffer)
|
181
|
+
buffer << [msg].pack("e")
|
56
182
|
end
|
57
183
|
|
58
184
|
def decode(msg)
|
@@ -61,8 +187,8 @@ class BareTypes
|
|
61
187
|
end
|
62
188
|
|
63
189
|
class F64 < BarePrimitive
|
64
|
-
def encode(msg)
|
65
|
-
|
190
|
+
def encode(msg, buffer)
|
191
|
+
buffer << [msg].pack("E")
|
66
192
|
end
|
67
193
|
|
68
194
|
def decode(msg)
|
@@ -71,16 +197,14 @@ class BareTypes
|
|
71
197
|
end
|
72
198
|
|
73
199
|
class String < BarePrimitive
|
74
|
-
def encode(msg)
|
75
|
-
encodedString = nil
|
200
|
+
def encode(msg, buffer)
|
76
201
|
begin
|
77
202
|
encodedString = msg.encode("UTF-8").b
|
78
203
|
rescue Encoding::UndefinedConversionError => error
|
79
204
|
raise error.class, "Unable to convert string to UTF-8=, BARE strings are encoded as UTF8. If you can't convert your string to UTF-8 you can encode it with binary data"
|
80
205
|
end
|
81
|
-
|
82
|
-
|
83
|
-
return bytes
|
206
|
+
Uint.new.encode(encodedString.size, buffer)
|
207
|
+
buffer << encodedString
|
84
208
|
end
|
85
209
|
|
86
210
|
def decode(msg)
|
@@ -90,202 +214,45 @@ class BareTypes
|
|
90
214
|
end
|
91
215
|
end
|
92
216
|
|
93
|
-
class Optional < BaseType
|
94
|
-
def ==(otherType)
|
95
|
-
return otherType.class == BareTypes::Optional && otherType.optionalType == @optionalType
|
96
|
-
end
|
97
|
-
|
98
|
-
def finalize_references(schema)
|
99
|
-
return if @finalized
|
100
|
-
@finalized = true
|
101
|
-
if @optionalType.is_a?(Symbol)
|
102
|
-
@optionalType = schema[@optionalType]
|
103
|
-
else
|
104
|
-
@optionalType.finalize_references(schema)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def optionalType
|
109
|
-
@optionalType
|
110
|
-
end
|
111
|
-
|
112
|
-
def initialize(optionalType)
|
113
|
-
raise VoidUsedOutsideTaggedSet() if optionalType.class == BareTypes::Void
|
114
|
-
@optionalType = optionalType
|
115
|
-
end
|
116
|
-
|
117
|
-
def encode(msg)
|
118
|
-
if msg.nil?
|
119
|
-
return "\x00".b
|
120
|
-
else
|
121
|
-
bytes = "\x01".b
|
122
|
-
bytes << @optionalType.encode(msg)
|
123
|
-
return bytes
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def decode(msg)
|
128
|
-
if msg.unpack("C")[0] == 0
|
129
|
-
return nil, msg[1..msg.size]
|
130
|
-
else
|
131
|
-
return @optionalType.decode(msg[1..msg.size])
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
class Map < BaseType
|
137
|
-
def ==(otherType)
|
138
|
-
return otherType.class == BareTypes::Map && otherType.from == @from && otherType.to == @to
|
139
|
-
end
|
140
|
-
|
141
|
-
def finalize_references(schema)
|
142
|
-
return if @finalized
|
143
|
-
@finalized = true
|
144
|
-
if @from.is_a?(Symbol)
|
145
|
-
@to = schema[@to]
|
146
|
-
else
|
147
|
-
@to.finalize_references(schema)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def initialize(fromType, toType)
|
152
|
-
raise VoidUsedOutsideTaggedSet if fromType.class == BareTypes::Void or toType.class == BareTypes::Void
|
153
|
-
if !fromType.class.ancestors.include?(BarePrimitive) ||
|
154
|
-
fromType.is_a?(BareTypes::Data) ||
|
155
|
-
fromType.is_a?(BareTypes::DataFixedLen)
|
156
|
-
raise MapKeyError("Map keys must use a primitive type which is not data or data<length>.")
|
157
|
-
end
|
158
|
-
@from = fromType
|
159
|
-
@to = toType
|
160
|
-
end
|
161
|
-
|
162
|
-
def from
|
163
|
-
@from
|
164
|
-
end
|
165
|
-
|
166
|
-
def to
|
167
|
-
@to
|
168
|
-
end
|
169
|
-
|
170
|
-
def encode(msg)
|
171
|
-
bytes = Uint.new.encode(msg.size)
|
172
|
-
msg.each do |from, to|
|
173
|
-
bytes << @from.encode(from)
|
174
|
-
bytes << @to.encode(to)
|
175
|
-
end
|
176
|
-
return bytes
|
177
|
-
end
|
178
|
-
|
179
|
-
def decode(msg)
|
180
|
-
hash = Hash.new
|
181
|
-
mapSize, rest = Uint.new.decode(msg)
|
182
|
-
(mapSize - 1).to_i.downto(0) do
|
183
|
-
key, rest = @from.decode(rest)
|
184
|
-
value, rest = @to.decode(rest)
|
185
|
-
hash[key] = value
|
186
|
-
end
|
187
|
-
return hash, rest
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
class Union < BarePrimitive
|
192
|
-
|
193
|
-
def intToType
|
194
|
-
@intToType
|
195
|
-
end
|
196
|
-
|
197
|
-
def finalize_references(schema)
|
198
|
-
return if @finalized
|
199
|
-
@finalized = true
|
200
|
-
@intToType.keys.each do |key|
|
201
|
-
if @intToType[key].is_a?(Symbol)
|
202
|
-
@intToType[key] = schema[@intToType[key]]
|
203
|
-
else
|
204
|
-
@intToType[key].finalize_references(schema)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def ==(otherType)
|
210
|
-
return false unless otherType.is_a?(BareTypes::Union)
|
211
|
-
@intToType.each do |int, type|
|
212
|
-
return false unless type == otherType.intToType[int]
|
213
|
-
end
|
214
|
-
return true
|
215
|
-
end
|
216
|
-
|
217
|
-
def initialize(intToType)
|
218
|
-
intToType.keys.each do |i|
|
219
|
-
raise MinimumSizeError("Union's integer representations must be > 0, instead got: #{i}") if i < 0 or !i.is_a?(Integer)
|
220
|
-
end
|
221
|
-
raise MinimumSizeError("Union must have at least one type") if intToType.keys.size < 1
|
222
|
-
@intToType = intToType
|
223
|
-
end
|
224
|
-
|
225
|
-
def encode(msg)
|
226
|
-
type = msg[:type]
|
227
|
-
value = msg[:value]
|
228
|
-
unionTypeInt = nil
|
229
|
-
unionType = nil
|
230
|
-
@intToType.each do |int, typ|
|
231
|
-
if type.class == typ.class
|
232
|
-
unionTypeInt = int
|
233
|
-
unionType = typ
|
234
|
-
break
|
235
|
-
end
|
236
|
-
end
|
237
|
-
raise SchemaMismatch("Unable to find given type in union: #{@intToType.inspect}, type: #{type}") if unionType.nil? || unionTypeInt.nil?
|
238
|
-
bytes = Uint.new.encode(unionTypeInt)
|
239
|
-
encoded = unionType.encode(value)
|
240
|
-
bytes << encoded
|
241
|
-
end
|
242
|
-
|
243
|
-
def decode(msg)
|
244
|
-
int, rest = Uint.new.decode(msg)
|
245
|
-
type = @intToType[int]
|
246
|
-
value, rest = type.decode(rest)
|
247
|
-
return {value: value, type: type}, rest
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
217
|
class DataFixedLen < BaseType
|
252
218
|
def ==(otherType)
|
253
219
|
return otherType.class == BareTypes::DataFixedLen && otherType.length == self.length
|
254
220
|
end
|
255
221
|
|
256
|
-
def
|
257
|
-
|
222
|
+
def to_schema(buffer)
|
223
|
+
buffer << "data<#{@length}>"
|
258
224
|
end
|
259
225
|
|
260
|
-
def
|
226
|
+
def length
|
227
|
+
@length
|
261
228
|
end
|
262
229
|
|
230
|
+
def finalize_references(schema) end
|
231
|
+
|
263
232
|
def initialize(length)
|
264
|
-
raise MinimumSizeError("DataFixedLen must have a length greater than 0, got: #{length.inspect}") if length < 1
|
233
|
+
raise MinimumSizeError.new("DataFixedLen must have a length greater than 0, got: #{length.inspect}") if length < 1
|
265
234
|
@length = length
|
266
235
|
end
|
267
236
|
|
268
|
-
def encode(msg)
|
237
|
+
def encode(msg, buffer)
|
269
238
|
if msg.size != @length
|
270
239
|
raise FixedDataSizeWrong.new("Message is not proper sized for DataFixedLen should have been #{@length} but was #{msg.size}")
|
271
240
|
end
|
272
|
-
msg
|
241
|
+
buffer << msg
|
273
242
|
end
|
274
243
|
|
275
244
|
def decode(msg)
|
276
|
-
return msg[0..@length], msg[@length..msg.size]
|
245
|
+
return msg[0..@length-1], msg[@length..msg.size]
|
277
246
|
end
|
278
247
|
end
|
279
248
|
|
280
249
|
class Data < BarePrimitive
|
281
250
|
|
282
|
-
def finalize_references(schema)
|
283
|
-
end
|
251
|
+
def finalize_references(schema) end
|
284
252
|
|
285
|
-
def encode(msg)
|
286
|
-
|
287
|
-
|
288
|
-
return bytes
|
253
|
+
def encode(msg, buffer)
|
254
|
+
Uint.new.encode(msg.size, buffer)
|
255
|
+
buffer << msg
|
289
256
|
end
|
290
257
|
|
291
258
|
def decode(msg)
|
@@ -296,10 +263,9 @@ class BareTypes
|
|
296
263
|
|
297
264
|
class Uint < BarePrimitive
|
298
265
|
|
299
|
-
def finalize_references(schema)
|
300
|
-
end
|
266
|
+
def finalize_references(schema) end
|
301
267
|
|
302
|
-
def encode(msg)
|
268
|
+
def encode(msg, buffer)
|
303
269
|
bytes = "".b
|
304
270
|
_get_next_7_bits_as_byte(msg, 128) do |byte|
|
305
271
|
bytes << byte
|
@@ -312,8 +278,8 @@ class BareTypes
|
|
312
278
|
end
|
313
279
|
end
|
314
280
|
bytes[bytes.size - 1] = [bytes.bytes[bytes.size - 1] & 127].pack('C')[0]
|
315
|
-
raise MaximumSizeError("Maximum u/int allowed is 64 bit precision") if bytes.size > 9
|
316
|
-
|
281
|
+
raise MaximumSizeError.new("Maximum u/int allowed is 64 bit precision") if bytes.size > 9
|
282
|
+
buffer << bytes
|
317
283
|
end
|
318
284
|
|
319
285
|
def decode(msg)
|
@@ -334,8 +300,8 @@ class BareTypes
|
|
334
300
|
end
|
335
301
|
|
336
302
|
class U8 < BarePrimitive
|
337
|
-
def encode(msg)
|
338
|
-
|
303
|
+
def encode(msg, buffer)
|
304
|
+
buffer << [msg].pack("C")
|
339
305
|
end
|
340
306
|
|
341
307
|
def decode(msg)
|
@@ -344,8 +310,8 @@ class BareTypes
|
|
344
310
|
end
|
345
311
|
|
346
312
|
class U16 < BarePrimitive
|
347
|
-
def encode(msg)
|
348
|
-
|
313
|
+
def encode(msg, buffer)
|
314
|
+
buffer << [msg].pack("v")
|
349
315
|
end
|
350
316
|
|
351
317
|
def decode(msg)
|
@@ -354,8 +320,8 @@ class BareTypes
|
|
354
320
|
end
|
355
321
|
|
356
322
|
class U32 < BarePrimitive
|
357
|
-
def encode(msg)
|
358
|
-
|
323
|
+
def encode(msg, buffer)
|
324
|
+
buffer << [msg].pack("V")
|
359
325
|
end
|
360
326
|
|
361
327
|
def decode(msg)
|
@@ -364,8 +330,8 @@ class BareTypes
|
|
364
330
|
end
|
365
331
|
|
366
332
|
class U64 < BarePrimitive
|
367
|
-
def encode(msg)
|
368
|
-
|
333
|
+
def encode(msg, buffer)
|
334
|
+
buffer << [msg].pack("Q")
|
369
335
|
end
|
370
336
|
|
371
337
|
def decode(msg)
|
@@ -374,8 +340,8 @@ class BareTypes
|
|
374
340
|
end
|
375
341
|
|
376
342
|
class I8 < BarePrimitive
|
377
|
-
def encode(msg)
|
378
|
-
|
343
|
+
def encode(msg, buffer)
|
344
|
+
buffer << [msg].pack("c")
|
379
345
|
end
|
380
346
|
|
381
347
|
def decode(msg)
|
@@ -384,8 +350,8 @@ class BareTypes
|
|
384
350
|
end
|
385
351
|
|
386
352
|
class I16 < BarePrimitive
|
387
|
-
def encode(msg)
|
388
|
-
|
353
|
+
def encode(msg, buffer)
|
354
|
+
buffer << [msg].pack("s<")
|
389
355
|
end
|
390
356
|
|
391
357
|
def decode(msg)
|
@@ -394,8 +360,8 @@ class BareTypes
|
|
394
360
|
end
|
395
361
|
|
396
362
|
class I32 < BarePrimitive
|
397
|
-
def encode(msg)
|
398
|
-
|
363
|
+
def encode(msg, buffer)
|
364
|
+
buffer << [msg].pack("l<")
|
399
365
|
end
|
400
366
|
|
401
367
|
def decode(msg)
|
@@ -404,8 +370,8 @@ class BareTypes
|
|
404
370
|
end
|
405
371
|
|
406
372
|
class I64 < BarePrimitive
|
407
|
-
def encode(msg)
|
408
|
-
|
373
|
+
def encode(msg, buffer)
|
374
|
+
buffer << [msg].pack("q<")
|
409
375
|
end
|
410
376
|
|
411
377
|
def decode(msg)
|
@@ -414,19 +380,219 @@ class BareTypes
|
|
414
380
|
end
|
415
381
|
|
416
382
|
class Bool < BarePrimitive
|
417
|
-
def encode(msg)
|
418
|
-
|
383
|
+
def encode(msg, buffer)
|
384
|
+
buffer << (msg ? "\x00".b : "\x01".b)
|
385
|
+
end
|
386
|
+
|
387
|
+
def decode(msg)
|
388
|
+
if msg != "\x00" && msg != "\x01"
|
389
|
+
raise InvalidBool.new("Expected a bool but found #{msg.inspect}. Standard requires bool to be 0x00 or 0x01")
|
390
|
+
end
|
391
|
+
return (msg == "\x00" ? true : false), msg[1..msg.size]
|
392
|
+
end
|
393
|
+
end
|
394
|
+
#endregion
|
395
|
+
|
396
|
+
class Optional < BaseType
|
397
|
+
def ==(otherType)
|
398
|
+
return otherType.class == BareTypes::Optional && otherType.optionalType == @optionalType
|
399
|
+
end
|
400
|
+
|
401
|
+
def to_schema(buffer)
|
402
|
+
buffer << "optional<"
|
403
|
+
@optionalType.to_schema(buffer)
|
404
|
+
buffer << ">"
|
405
|
+
end
|
406
|
+
|
407
|
+
def finalize_references(schema)
|
408
|
+
return if @finalized
|
409
|
+
@finalized = true
|
410
|
+
if @optionalType.is_a?(Symbol)
|
411
|
+
@optionalType = Reference.new(@optionalType, schema[@optionalType])
|
412
|
+
else
|
413
|
+
@optionalType.finalize_references(schema)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
def optionalType
|
418
|
+
@optionalType
|
419
|
+
end
|
420
|
+
|
421
|
+
def initialize(optionalType)
|
422
|
+
raise VoidUsedOutsideTaggedSet() if optionalType.class == BareTypes::Void
|
423
|
+
@optionalType = optionalType
|
424
|
+
end
|
425
|
+
|
426
|
+
def encode(msg, buffer)
|
427
|
+
if msg.nil?
|
428
|
+
buffer << "\x00".b
|
429
|
+
else
|
430
|
+
buffer << "\x01".b
|
431
|
+
@optionalType.encode(msg, buffer)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def decode(msg)
|
436
|
+
if msg.unpack("C")[0] == 0
|
437
|
+
return nil, msg[1..msg.size]
|
438
|
+
else
|
439
|
+
return @optionalType.decode(msg[1..msg.size])
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
class Map < BaseType
|
445
|
+
def ==(otherType)
|
446
|
+
return otherType.class == BareTypes::Map && otherType.from == @from && otherType.to == @to
|
447
|
+
end
|
448
|
+
|
449
|
+
def to_schema(buffer)
|
450
|
+
buffer << "map["
|
451
|
+
@from.to_schema(buffer)
|
452
|
+
buffer << "]"
|
453
|
+
@to.to_schema(buffer)
|
454
|
+
end
|
455
|
+
|
456
|
+
def finalize_references(schema)
|
457
|
+
return if @finalized
|
458
|
+
@finalized = true
|
459
|
+
if @from.is_a?(Symbol)
|
460
|
+
@to = Reference.new(@from, schema[@to])
|
461
|
+
else
|
462
|
+
@to.finalize_references(schema)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
def initialize(fromType, toType)
|
467
|
+
raise VoidUsedOutsideTaggedSet if fromType.class == BareTypes::Void or toType.class == BareTypes::Void
|
468
|
+
if !fromType.class.ancestors.include?(BarePrimitive) ||
|
469
|
+
fromType.is_a?(BareTypes::Data) ||
|
470
|
+
fromType.is_a?(BareTypes::DataFixedLen)
|
471
|
+
raise MapKeyError("Map keys must use a primitive type which is not data or data<length>.")
|
472
|
+
end
|
473
|
+
@from = fromType
|
474
|
+
@to = toType
|
475
|
+
end
|
476
|
+
|
477
|
+
def from
|
478
|
+
@from
|
479
|
+
end
|
480
|
+
|
481
|
+
def to
|
482
|
+
@to
|
483
|
+
end
|
484
|
+
|
485
|
+
def encode(msg, buffer)
|
486
|
+
Uint.new.encode(msg.size, buffer)
|
487
|
+
msg.each do |from, to|
|
488
|
+
@from.encode(from, buffer)
|
489
|
+
@to.encode(to, buffer)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def decode(msg)
|
494
|
+
hash = Hash.new
|
495
|
+
mapSize, rest = Uint.new.decode(msg)
|
496
|
+
# (0..mapSize).each do
|
497
|
+
(mapSize - 1).to_i.downto(0) do
|
498
|
+
key, rest = @from.decode(rest)
|
499
|
+
value, rest = @to.decode(rest)
|
500
|
+
hash[key] = value
|
501
|
+
end
|
502
|
+
return hash, rest
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
class Union < BaseType
|
507
|
+
attr_accessor :intToType
|
508
|
+
|
509
|
+
def cycle_search(seen)
|
510
|
+
if @intToType.size == 1
|
511
|
+
seen.add(self)
|
512
|
+
@intToType.values.each do |type|
|
513
|
+
type.cycle_search(seen)
|
514
|
+
end
|
515
|
+
seen.pop
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
def finalize_references(schema)
|
520
|
+
return if @finalized
|
521
|
+
@finalized = true
|
522
|
+
@intToType.keys.each do |key|
|
523
|
+
if @intToType[key].is_a?(Symbol)
|
524
|
+
@intToType[key] = Reference.new(@intToType[key], schema[@intToType[key]])
|
525
|
+
else
|
526
|
+
@intToType[key].finalize_references(schema)
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
def ==(otherType)
|
532
|
+
return false unless otherType.is_a?(BareTypes::Union)
|
533
|
+
@intToType.each do |int, type|
|
534
|
+
return false unless type == otherType.intToType[int]
|
535
|
+
end
|
536
|
+
true
|
537
|
+
end
|
538
|
+
|
539
|
+
def initialize(intToType)
|
540
|
+
intToType.keys.each do |i|
|
541
|
+
raise MinimumSizeError("Union's integer representations must be > 0, instead got: #{i}") if i < 0 or !i.is_a?(Integer)
|
542
|
+
end
|
543
|
+
raise MinimumSizeError("Union must have at least one type") if intToType.keys.size < 1
|
544
|
+
@intToType = intToType
|
545
|
+
end
|
546
|
+
|
547
|
+
def to_schema(buffer)
|
548
|
+
buffer << "("
|
549
|
+
strs = []
|
550
|
+
@intToType.size.times do
|
551
|
+
strs << ""
|
552
|
+
end
|
553
|
+
@intToType.values.each_with_index.map { |type, i| type.to_schema(strs[i]) }
|
554
|
+
buffer << strs.join(" | ")
|
555
|
+
buffer << ")"
|
556
|
+
end
|
557
|
+
|
558
|
+
def encode(msg, buffer)
|
559
|
+
type = msg[:type]
|
560
|
+
value = msg[:value]
|
561
|
+
unionTypeInt = nil
|
562
|
+
unionType = nil
|
563
|
+
@intToType.each do |int, typ|
|
564
|
+
if type.class == typ.class
|
565
|
+
unionTypeInt = int
|
566
|
+
unionType = typ
|
567
|
+
break
|
568
|
+
end
|
569
|
+
end
|
570
|
+
raise SchemaMismatch("Unable to find given type in union: #{@intToType.inspect}, type: #{type}") if unionType.nil? || unionTypeInt.nil?
|
571
|
+
Uint.new.encode(unionTypeInt, buffer)
|
572
|
+
unionType.encode(value, buffer)
|
419
573
|
end
|
420
574
|
|
421
575
|
def decode(msg)
|
422
|
-
|
576
|
+
int, rest = Uint.new.decode(msg)
|
577
|
+
type = @intToType[int]
|
578
|
+
value, rest = type.decode(rest)
|
579
|
+
return { value: value, type: type }, rest
|
423
580
|
end
|
424
581
|
end
|
425
582
|
|
426
583
|
class Struct < BaseType
|
584
|
+
attr_accessor :mapping
|
585
|
+
|
586
|
+
def cycle_search(seen)
|
587
|
+
seen.add(self)
|
588
|
+
@mapping.values.each do |val|
|
589
|
+
val.cycle_search(seen)
|
590
|
+
end
|
591
|
+
seen.pop
|
592
|
+
end
|
427
593
|
|
428
594
|
def [](key)
|
429
|
-
|
595
|
+
@mapping[key]
|
430
596
|
end
|
431
597
|
|
432
598
|
def ==(otherType)
|
@@ -434,7 +600,7 @@ class BareTypes
|
|
434
600
|
@mapping.each do |k, v|
|
435
601
|
return false unless otherType.mapping[k] == v
|
436
602
|
end
|
437
|
-
|
603
|
+
true
|
438
604
|
end
|
439
605
|
|
440
606
|
def finalize_references(schema)
|
@@ -442,17 +608,18 @@ class BareTypes
|
|
442
608
|
@finalized = true
|
443
609
|
@mapping.each do |key, val|
|
444
610
|
if val.is_a?(Symbol)
|
445
|
-
@mapping[key] = schema[val]
|
611
|
+
@mapping[key] = Reference.new(val, schema[val])
|
612
|
+
begin
|
613
|
+
@mapping[key].ref.finalize_references(schema)
|
614
|
+
rescue NoMethodError => e
|
615
|
+
puts "err"
|
616
|
+
end
|
446
617
|
else
|
447
618
|
val.finalize_references(schema)
|
448
619
|
end
|
449
620
|
end
|
450
621
|
end
|
451
622
|
|
452
|
-
def mapping
|
453
|
-
@mapping
|
454
|
-
end
|
455
|
-
|
456
623
|
def initialize(symbolToType)
|
457
624
|
# Mapping from symbols to Bare types (or possibly symbols before finalizing)
|
458
625
|
symbolToType.keys.each do |k|
|
@@ -467,13 +634,11 @@ class BareTypes
|
|
467
634
|
@mapping = symbolToType
|
468
635
|
end
|
469
636
|
|
470
|
-
def encode(msg)
|
471
|
-
bytes = "".b
|
637
|
+
def encode(msg, buffer)
|
472
638
|
@mapping.keys.each do |symbol|
|
473
639
|
raise SchemaMismatch.new("All struct fields must be specified, missing: #{symbol.inspect}") unless msg.keys.include?(symbol)
|
474
|
-
|
640
|
+
@mapping[symbol].encode(msg[symbol], buffer)
|
475
641
|
end
|
476
|
-
return bytes
|
477
642
|
end
|
478
643
|
|
479
644
|
def decode(msg)
|
@@ -485,22 +650,43 @@ class BareTypes
|
|
485
650
|
end
|
486
651
|
return hash, rest
|
487
652
|
end
|
653
|
+
|
654
|
+
def to_schema(buffer)
|
655
|
+
buffer << "{"
|
656
|
+
@mapping.each do |symbol, type|
|
657
|
+
buffer << " #{symbol}: "
|
658
|
+
type.to_schema(buffer)
|
659
|
+
buffer << "\n"
|
660
|
+
end
|
661
|
+
buffer << "}"
|
662
|
+
end
|
488
663
|
end
|
489
664
|
|
490
665
|
class Array < BaseType
|
491
666
|
def ==(otherType)
|
492
|
-
|
667
|
+
otherType.class == BareTypes::Array && otherType.type == self.type
|
668
|
+
end
|
669
|
+
|
670
|
+
def cycle_search(seen)
|
671
|
+
seen.add(self)
|
672
|
+
@type.cycle_search(seen)
|
673
|
+
seen.pop
|
493
674
|
end
|
494
675
|
|
495
676
|
def type
|
496
|
-
|
677
|
+
@type
|
678
|
+
end
|
679
|
+
|
680
|
+
def to_schema(buffer)
|
681
|
+
buffer << "[]"
|
682
|
+
@type.to_schema(buffer)
|
497
683
|
end
|
498
684
|
|
499
685
|
def finalize_references(schema)
|
500
686
|
return if @finalized
|
501
687
|
@finalized = true
|
502
688
|
if @type.is_a?(Symbol)
|
503
|
-
@type = schema[@type]
|
689
|
+
@type = Reference.new(@type, schema[@type])
|
504
690
|
else
|
505
691
|
@type.finalize_references(schema)
|
506
692
|
end
|
@@ -511,12 +697,11 @@ class BareTypes
|
|
511
697
|
@type = type
|
512
698
|
end
|
513
699
|
|
514
|
-
def encode(msg)
|
515
|
-
|
700
|
+
def encode(msg, buffer)
|
701
|
+
Uint.new.encode(msg.size, buffer)
|
516
702
|
msg.each do |item|
|
517
|
-
|
703
|
+
@type.encode(item, buffer)
|
518
704
|
end
|
519
|
-
return bytes
|
520
705
|
end
|
521
706
|
|
522
707
|
def decode(msg)
|
@@ -534,6 +719,14 @@ class BareTypes
|
|
534
719
|
end
|
535
720
|
|
536
721
|
class ArrayFixedLen < BaseType
|
722
|
+
attr_accessor :type, :size
|
723
|
+
|
724
|
+
def cycle_search(seen)
|
725
|
+
seen.add(self)
|
726
|
+
@type.cycle_search(seen)
|
727
|
+
seen.pop
|
728
|
+
end
|
729
|
+
|
537
730
|
def ==(otherType)
|
538
731
|
return otherType.class == BareTypes::ArrayFixedLen && otherType.type == @type && otherType.size == @size
|
539
732
|
end
|
@@ -542,7 +735,7 @@ class BareTypes
|
|
542
735
|
return if @finalized
|
543
736
|
@finalized = true
|
544
737
|
if @type.is_a?(Symbol)
|
545
|
-
@type = schema[@type]
|
738
|
+
@type = Reference.new(@type, schema[@type])
|
546
739
|
else
|
547
740
|
@type.finalize_references(schema)
|
548
741
|
end
|
@@ -552,24 +745,14 @@ class BareTypes
|
|
552
745
|
@type = type
|
553
746
|
@size = size
|
554
747
|
raise VoidUsedOutsideTaggedSet.new("Void type may not be used as type of fixed length array.") if type.class == BareTypes::Void
|
555
|
-
raise MinimumSizeError.new("
|
748
|
+
raise MinimumSizeError.new("ArrayFixedLen size must be > 0") if size < 1
|
556
749
|
end
|
557
750
|
|
558
|
-
def
|
559
|
-
@
|
560
|
-
end
|
561
|
-
|
562
|
-
def size
|
563
|
-
@size
|
564
|
-
end
|
565
|
-
|
566
|
-
def encode(arr)
|
567
|
-
raise SchemaMismatch.new("This FixLenArray is of length #{@size.to_s} but you passed an array of length #{arr.size}") if arr.size != @size
|
568
|
-
bytes = ""
|
751
|
+
def encode(arr, buffer)
|
752
|
+
raise SchemaMismatch.new("This ArrayFixedLen is of length #{@size.to_s} but you passed an array of length #{arr.size}") if arr.size != @size
|
569
753
|
arr.each do |item|
|
570
|
-
|
754
|
+
@type.encode(item, buffer)
|
571
755
|
end
|
572
|
-
return bytes
|
573
756
|
end
|
574
757
|
|
575
758
|
def decode(rest)
|
@@ -580,6 +763,11 @@ class BareTypes
|
|
580
763
|
end
|
581
764
|
return array, rest
|
582
765
|
end
|
766
|
+
|
767
|
+
def to_schema(buffer)
|
768
|
+
buffer << "[#{@size}]"
|
769
|
+
@type.to_schema(buffer)
|
770
|
+
end
|
583
771
|
end
|
584
772
|
|
585
773
|
class Enum < BaseType
|
@@ -591,10 +779,16 @@ class BareTypes
|
|
591
779
|
return true
|
592
780
|
end
|
593
781
|
|
594
|
-
|
595
|
-
|
782
|
+
def to_schema(buffer)
|
783
|
+
buffer << "{\n"
|
784
|
+
@valToInt.each do |name, repr|
|
785
|
+
buffer << " #{name} = #{repr}\n"
|
786
|
+
end
|
787
|
+
buffer << "}"
|
596
788
|
end
|
597
789
|
|
790
|
+
def finalize_references(schema) end
|
791
|
+
|
598
792
|
def intToVal
|
599
793
|
@intToVal
|
600
794
|
end
|
@@ -612,11 +806,10 @@ class BareTypes
|
|
612
806
|
end
|
613
807
|
end
|
614
808
|
|
615
|
-
def encode(msg)
|
809
|
+
def encode(msg, buffer)
|
616
810
|
raise SchemaMismatch.new("#{msg.inspect} is not part of this enum: #{@intToVal}") if !@valToInt.keys.include?(msg)
|
617
811
|
integerRep = @valToInt[msg]
|
618
|
-
|
619
|
-
return encoded
|
812
|
+
BareTypes::Uint.new.encode(integerRep, buffer)
|
620
813
|
end
|
621
814
|
|
622
815
|
def decode(msg)
|
@@ -637,4 +830,4 @@ def _get_next_7_bits_as_byte(integer, base = 128)
|
|
637
830
|
end
|
638
831
|
yield(byte)
|
639
832
|
end
|
640
|
-
end
|
833
|
+
end
|