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.
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
- return Uint.new.encode(mappedInteger)
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 value, rest
165
+ return value, rest
40
166
  end
41
167
  end
42
168
 
43
169
  class Void < BarePrimitive
44
- def encode(msg)
45
- return "".b
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
- return [msg].pack("E")
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
- bytes = Uint.new.encode(encodedString.size)
82
- bytes << encodedString
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 length
257
- return @length
222
+ def to_schema(buffer)
223
+ buffer << "data<#{@length}>"
258
224
  end
259
225
 
260
- def finalize_references(schema)
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
- bytes = Uint.new.encode(msg.size)
287
- bytes << msg
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
- return bytes
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
- return [msg].pack("C")
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
- return [msg].pack("v")
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
- return [msg].pack("V")
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
- return [msg].pack("Q")
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
- return [msg].pack("c")
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
- return [msg].pack("s<")
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
- return [msg].pack("l<")
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
- return [msg].pack("q<")
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
- return msg ? "\xFF\xFF".b : "\x00\x00".b
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
- return (msg == "\x00\x00" ? false : true), msg[1..msg.size]
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
- return @mapping[key]
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
- return true
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
- bytes << @mapping[symbol].encode(msg[symbol])
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
- return otherType.class == BareTypes::Array && otherType.type == self.type
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
- return @type
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
- bytes = Uint.new.encode(msg.size)
700
+ def encode(msg, buffer)
701
+ Uint.new.encode(msg.size, buffer)
516
702
  msg.each do |item|
517
- bytes << @type.encode(item)
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("FixedLenArray size must be > 0") if size < 1
748
+ raise MinimumSizeError.new("ArrayFixedLen size must be > 0") if size < 1
556
749
  end
557
750
 
558
- def type
559
- @type
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
- bytes << @type.encode(item)
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
- def finalize_references(schema)
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
- encoded = BareTypes::Uint.new.encode(integerRep)
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