slow_blink 0.0.6 → 0.0.7

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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/ext/slow_blink/ext_schema_parser/lexer.c +2793 -839
  3. data/ext/slow_blink/ext_schema_parser/lexer.h +14 -137
  4. data/ext/slow_blink/ext_schema_parser/parser.c +616 -670
  5. data/ext/slow_blink/ext_schema_parser/parser.h +6 -4
  6. data/ext/slow_blink/message/ext_compact_encoder/blink_compact.c +642 -0
  7. data/ext/slow_blink/message/ext_compact_encoder/blink_compact.h +411 -0
  8. data/ext/slow_blink/message/ext_compact_encoder/blink_debug.h +46 -0
  9. data/ext/slow_blink/message/ext_compact_encoder/blink_stream.c +314 -0
  10. data/ext/slow_blink/message/ext_compact_encoder/blink_stream.h +185 -0
  11. data/ext/slow_blink/message/ext_compact_encoder/ext_compact_encoder.c +382 -269
  12. data/lib/slow_blink/definition.rb +18 -53
  13. data/lib/slow_blink/dynamic_group.rb +8 -0
  14. data/lib/slow_blink/enum.rb +101 -0
  15. data/lib/slow_blink/field.rb +63 -33
  16. data/lib/slow_blink/generate_c/model.rb +89 -0
  17. data/lib/slow_blink/group.rb +119 -100
  18. data/lib/slow_blink/message/binary.rb +3 -4
  19. data/lib/slow_blink/message/boolean.rb +3 -4
  20. data/lib/slow_blink/message/date.rb +3 -4
  21. data/lib/slow_blink/message/decimal.rb +3 -5
  22. data/lib/slow_blink/message/{enumeration.rb → enum.rb} +17 -17
  23. data/lib/slow_blink/message/field.rb +77 -27
  24. data/lib/slow_blink/message/fixed.rb +5 -21
  25. data/lib/slow_blink/message/floating_point.rb +3 -4
  26. data/lib/slow_blink/message/group.rb +90 -161
  27. data/lib/slow_blink/message/integer.rb +24 -32
  28. data/lib/slow_blink/message/model.rb +50 -110
  29. data/lib/slow_blink/message/string.rb +3 -4
  30. data/lib/slow_blink/message/time.rb +5 -5
  31. data/lib/slow_blink/message/time_of_day.rb +5 -12
  32. data/lib/slow_blink/ref.rb +22 -71
  33. data/lib/slow_blink/schema.rb +64 -85
  34. data/lib/slow_blink/schema_buffer.rb +1 -4
  35. data/lib/slow_blink/static_group.rb +37 -0
  36. data/lib/slow_blink/string.rb +4 -5
  37. data/lib/slow_blink/sym.rb +8 -28
  38. data/lib/slow_blink/type.rb +10 -19
  39. data/lib/slow_blink/version.rb +1 -1
  40. data/lib/slow_blink.rb +1 -0
  41. data/test/tc_compact_encoder.rb +114 -147
  42. data/test/tc_inputs.rb +2 -4
  43. data/test/tc_model_string.rb +29 -0
  44. data/test/tc_schema_new.rb +212 -0
  45. metadata +17 -26
  46. data/ext/slow_blink/ext_schema_parser/common.h +0 -27
  47. data/ext/slow_blink/message/ext_compact_encoder/compact_encoder.c +0 -258
  48. data/ext/slow_blink/message/ext_compact_encoder/compact_encoder.h +0 -92
  49. data/lib/slow_blink/annotatable.rb +0 -48
  50. data/lib/slow_blink/annotation.rb +0 -47
  51. data/lib/slow_blink/enumeration.rb +0 -90
  52. data/lib/slow_blink/incremental_annotation.rb +0 -151
  53. data/lib/slow_blink/log.rb +0 -51
  54. data/lib/slow_blink/message/sequence.rb +0 -98
  55. data/lib/slow_blink/name_with_id.rb +0 -49
  56. data/lib/slow_blink/namespace.rb +0 -143
  57. data/lib/slow_blink/sequence.rb +0 -57
  58. data/test/tc_field.rb +0 -94
  59. data/test/tc_group.rb +0 -114
  60. data/test/tc_incr_annote.rb +0 -22
  61. data/test/tc_namespace.rb +0 -8
  62. data/test/tc_types.rb +0 -218
@@ -24,68 +24,33 @@ module SlowBlink
24
24
 
25
25
  class Definition
26
26
 
27
- include Annotatable
28
-
29
- def self.===(other)
30
- self == other
31
- end
27
+ # @return [Type] defined type
28
+ attr_reader :type
32
29
 
33
30
  # @macro location
34
31
  attr_reader :location
35
32
 
36
- # @return [NameWithID]
37
- attr_reader :nameWithID
33
+ # @return [String]
34
+ attr_reader :name
38
35
 
39
- # @return [Type,ENUMERATION]
40
- attr_reader :type
36
+ # @return [Integer,nil]
37
+ attr_reader :id
41
38
 
42
- # @param namespace [Namespace]
43
- def namespace=(namespace)
44
- @ns = namespace
45
- end
46
-
47
- # @param nameWithID [NameWithID]
48
- # @param type [ENUMERATION, Type]
49
- # @param location [String]
50
- def initialize(nameWithID, type, location)
51
- @annotes = {}
52
- @type = type
53
- @location = location
54
- @nameWithID = nameWithID
55
- @ns = nil
39
+ def self.===(other)
40
+ self == other
56
41
  end
57
42
 
58
- # @api private
59
- # Resolve references, enforce constraints, and detect cycles
60
- #
61
- # @param schema [Schema] schema this definition belongs to
62
- # @param stack [nil, Array] objects that depend on this object
63
- # @return [true,false] linked?
64
- def link(schema, stack=[])
65
-
66
- # a definition can resolve to a definition only if there is a dynamic
67
- # link somewhere in the chain
68
- sf = stack.each
69
- begin
70
- loop do
71
- if sf.next == self
72
- loop do
73
- begin
74
- f = sf.next
75
- if f.respond_to? "dynamic?".to_sym and f.dynamic?
76
- return schema
77
- end
78
- rescue StopIteration
79
- raise ParseError.new "#{self.location}: error: invalid cycle detected"
80
- end
81
- end
82
- end
83
- end
84
- rescue StopIteration
43
+ # @private
44
+ def initialize(attr)
45
+ @location = attr[:loc].freeze
46
+ @ns = attr[:ns].freeze
47
+ @name = attr[:name][:name].dup
48
+ if @ns
49
+ @name.prepend "#{@ns}::"
85
50
  end
86
-
87
- @type.link(schema, @ns, stack << self)
88
-
51
+ @name.freeze
52
+ @id = attr[:name][:id]
53
+ @type = SlowBlink.const_get(attr[:type][:class]).new(attr[:type].merge({:table => attr[:table], :ns => attr[:ns], :name => @name}))
89
54
  end
90
55
 
91
56
  end
@@ -0,0 +1,8 @@
1
+ module SlowBlink
2
+ class DynamicGroup < StaticGroup
3
+ # @return [Array<Group>] groups that are compatible with this dynamic group
4
+ def groups
5
+ @table.values.select{|d|d.is_a? Group and d.id and (d.ancestors.include? @group or d == @group)}
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,101 @@
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
23
+
24
+ class ENUM < Type
25
+
26
+ def self.===(other)
27
+ self == other
28
+ end
29
+
30
+ # @return [Array<Sym>]
31
+ def symbols
32
+ @symbols.values
33
+ end
34
+
35
+ # @return [String]
36
+ attr_reader :name
37
+
38
+ # @private
39
+ def initialize(attr)
40
+
41
+ @location = attr[:loc]
42
+ @symbols = {}
43
+ @name = attr[:name].dup.freeze
44
+
45
+ attr[:syms].each do |s|
46
+
47
+ if @symbols[s[:name]]
48
+ raise ParseError.new "#{s[:loc]}: duplicate symbol name"
49
+ else
50
+ if s[:value]
51
+ if s[:value] < 2147483647 and s[:value] > -2147483648
52
+ if @symbols.values.last
53
+ if @symbols.values.map{|sym|sym.value}.include? s[:value]
54
+ raise ParseError.new "#{s[:loc]}: ambiguous enum value"
55
+ else
56
+ @symbols[s[:name]] = Sym.new(s)
57
+ end
58
+ else
59
+ @symbols[s[:name]] = Sym.new(s)
60
+ end
61
+ else
62
+ raise ParseError.new "#{s[:loc]}: value out of range for an enum"
63
+ end
64
+ else
65
+ if @symbols.values.last
66
+ if (@symbols.values.last.value + 1) < 2147483647
67
+ if @symbols.values.map{|sym|sym.value}.include? s[:value]
68
+ raise ParseError.new "#{s[:loc]}: ambiguous enum value"
69
+ else
70
+ @symbols[s[:name]] = Sym.new(s.merge({:implicit => true, :value => @symbols.values.last.value + 1}))
71
+ end
72
+ else
73
+ raise ParseError.new "#{s[:loc]}: implicit value out of range for an enum"
74
+ end
75
+ else
76
+ @symbols[s[:name]] = Sym.new(s.merge({:implicit => true, :value => 0}))
77
+ end
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ # @param nameOrVal [String,Integer]
86
+ # @raise [RangeError] nameOrVal does not resolve to a symbol
87
+ # @return [Sym]
88
+ def symbol(nameOrVal)
89
+ if nameOrVal.kind_of? String
90
+ if (result = @symbols[nameOrVal]).nil?
91
+ raise RangeError
92
+ end
93
+ else
94
+ if (result = @symbols.values.detect{|s|s.value == nameOrVal.to_i}).nil?
95
+ raise RangeError
96
+ end
97
+ end
98
+ end
99
+
100
+ end
101
+ end
@@ -23,50 +23,80 @@
23
23
  module SlowBlink
24
24
 
25
25
  class Field
26
-
27
- include Annotatable
26
+
27
+ # @param [Integer]
28
+ attr_reader :id
29
+
30
+ # @param [String]
31
+ attr_reader :name
28
32
 
29
33
  # @macro location
30
34
  attr_reader :location
31
35
 
32
36
  # @return [Type]
33
- attr_reader :type
37
+ def type
38
+ result = nil
39
+ if @type.is_a? REF
40
+
41
+ ptr = @type.resolve
42
+ stack = []
43
+ sequence = @type.sequence?
44
+ dynamic = @type.dynamic?
34
45
 
35
- # @return [NameWithID]
36
- attr_reader :nameWithID
46
+ while ptr and ptr.is_a? Definition and ptr.type.is_a? REF do
37
47
 
38
- # @return [true] field is optional
39
- # @return [false] field is mandatory
40
- def opt?
41
- @opt
48
+ if stack.include? ptr
49
+ raise ParseError.new "#{ptr.location}: circular reference detected"
50
+ else
51
+ if ptr.type.dynamic?
52
+ # assumption: double dynamic is still dynamic
53
+ dynamic = true
54
+ end
55
+ if ptr.type.sequence?
56
+ if sequence
57
+ raise ParseError.new "#{ptr.location}: sequence of sequences detected while resolving from '#{@type.location}'"
58
+ end
59
+ sequence = true
60
+ end
61
+ stack << ptr
62
+ ptr = ptr.type.resolve
63
+ end
64
+ end
65
+
66
+ if ptr.nil?
67
+ if stack.size == 0
68
+ stack << @type
69
+ end
70
+ raise ParseError.new "#{stack.last.location}: reference does not resolve"
71
+ elsif ptr.is_a? Group
72
+ if dynamic
73
+ result = DynamicGroup.new(:group => ptr, :sequence => sequence, :table => @table)
74
+ else
75
+ result = StaticGroup.new(:group => ptr, :sequence => sequence, :table => @table)
76
+ end
77
+ else
78
+ result = ptr.type
79
+ end
80
+ else
81
+ result = @type
82
+ end
83
+
84
+ result
42
85
  end
43
86
 
44
- # @param nameWithID [NameWithID]
45
- # @param type [Type]
46
- # @param opt [true,false] field is optional?
47
- # @param location [String]
48
- def initialize(nameWithID, type, opt, location)
49
- @annotes = {}
50
- @schema = nil
51
- @type = type
52
- @opt = opt
53
- @location = location
54
- @nameWithID = nameWithID
87
+ # @return [true,false]
88
+ def optional?
89
+ @optional
55
90
  end
56
91
 
57
- # @api private
58
- #
59
- # Resolve references, enforce constraints, and detect cycles
60
- #
61
- # @param schema [Schema] schema this definition belongs to
62
- # @param ns [Namespace] namespace this definition belongs to
63
- # @param stack [nil, Array] objects that depend on this object
64
- # @return [true,false] linked?
65
- def link(schema,ns, stack=[])
66
- if @schema.nil?
67
- @schema = @type.link(schema, ns, stack << self)
68
- end
69
- @schema
92
+ # @private
93
+ def initialize(attr)
94
+ @name = attr[:name][:name].freeze
95
+ @id = attr[:name][:id]
96
+ @optional = attr[:opt]
97
+ @location = attr[:location].freeze
98
+ @type = SlowBlink.const_get(attr[:type][:class]).new(attr[:type].merge({:table => attr[:table], :ns => attr[:ns]}))
99
+ @table = attr[:table]
70
100
  end
71
101
 
72
102
  end
@@ -0,0 +1,89 @@
1
+ require 'erb'
2
+
3
+ module SlowBlink
4
+
5
+ module GenerateC
6
+
7
+ include SlowBlink
8
+
9
+ class Model
10
+
11
+ def initialize(schema)
12
+ @schema = schema
13
+ @prefix = ""
14
+ @options = {}
15
+ end
16
+
17
+ def render
18
+ header = put("groups.h.erb")
19
+ source = put("groups.c.erb")
20
+
21
+ File.write("groups.h", header)
22
+ File.write("groups.c", source)
23
+ end
24
+
25
+ private
26
+
27
+ def put(filename)
28
+ f = File.read(File.expand_path(File.join(File.dirname(__FILE__), filename)))
29
+ erb = ERB.new(f, nil, "<>-")
30
+ erb.filename = filename
31
+ erb.result(binding)
32
+ end
33
+
34
+ def gname(g)
35
+ "#{@prefix}#{g.name.gsub("::","_")}"
36
+ end
37
+
38
+ def fname(f)
39
+ "_#{f.name}"
40
+ end
41
+
42
+ def value_type(type)
43
+
44
+ out = ""
45
+
46
+ case type.class
47
+ when BINARY, STRING, FIXED
48
+ out << "struct blink_string"
49
+ when U8
50
+ out << "uint8_t"
51
+ when U16
52
+ out << "uint16_t"
53
+ when U32
54
+ out << "uint32_t"
55
+ when U64
56
+ out << "uint64_t"
57
+ when I8
58
+ out << "int8_t"
59
+ when I16
60
+ out << "int16_t"
61
+ when I32
62
+ out << "int32_t"
63
+ when I64
64
+ out << "int64_t"
65
+ when ENUM
66
+ out << "const char *"
67
+ when FLOATING_POINT
68
+ out << "double"
69
+ when DECIMAL
70
+ out << "struct blink_decimal"
71
+ when BOOLEAN
72
+ out << "bool"
73
+ when StaticGroup
74
+ out << "struct #{cname(type.name)} *"
75
+ when OBJECT, DynamicGroup
76
+ out << "struct base_group *"
77
+ else
78
+ raise
79
+ end
80
+
81
+ out
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+
89
+ end
@@ -24,133 +24,152 @@ module SlowBlink
24
24
 
25
25
  class Group
26
26
 
27
- include Annotatable
28
-
29
27
  def self.===(other)
30
28
  self == other
31
29
  end
32
30
 
33
- # @macro location
34
- attr_reader :location
31
+ # @return [Integer,nil]
32
+ attr_reader :id
35
33
 
36
- # @return [NameWithID]
37
- attr_reader :nameWithID
34
+ # @return [String] qualified name
35
+ attr_reader :name
38
36
 
37
+ # @macro location
38
+ attr_reader :location
39
+
39
40
  # @return [Array<Field>]
40
41
  def fields
41
- @fields.values
42
- end
43
42
 
44
- # @param namespace [Namespace]
45
- def namespace=(namespace)
46
- @ns = namespace
43
+ # collect all ancestors
44
+ ancestors = []
45
+ ptr = superGroup
46
+ while ptr do
47
+ ancestors.unshift ptr
48
+ ptr = ptr.superGroup
49
+ end
50
+
51
+ result = {}
52
+
53
+ ancestors.each do |g|
54
+ g.rawFields.each do |f|
55
+ result[f.name] = f
56
+ end
57
+ end
58
+
59
+ @fields.each do |fn, fv|
60
+ if result[fn]
61
+ raise ParseError.new "#{fv.location}: field name shadowed by supergroup"
62
+ else
63
+ result[fn] = fv
64
+ end
65
+ end
66
+
67
+ result.values
47
68
  end
48
69
 
49
- # @param nameWithID [NameWithID]
50
- # @param superGroup [REF, nil]
51
- # @param fields [Array<Field>]
52
- # @param location [String]
53
- def initialize(nameWithID, superGroup, fields, location)
54
- @annotes = {}
55
- @schema = nil
56
- @superGroup = superGroup
57
- @rawFields = fields
58
- @location = location
59
- @fields = []
60
- @nameWithID = nameWithID
61
- @ns = nil
70
+ # @return [Array<Group>] super groups in order of most super
71
+ def ancestors
72
+ result = []
73
+ ptr = superGroup
74
+ while ptr do
75
+ result << ptr
76
+ ptr = ptr.superGroup
77
+ end
78
+ result
62
79
  end
63
80
 
64
- # @api private
65
- #
66
- # Resolve references, enforce constraints, and detect cycles
67
- #
68
- # @param schema [Schema] schema this definition belongs to
69
- # @param stack [nil, Array] objects that depend on this object
70
- # @return [true,false] linked?
71
- def link(schema,stack=[])
72
-
73
- if @schema.nil?
74
-
75
- # a definition can resolve to a definition only if there is a dynamic
76
- # link somewhere in the chain
77
- sf = stack.each
78
- begin
79
- loop do
80
- if sf.next == self
81
- loop do
82
- begin
83
- f = sf.next
84
- if f.respond_to? "dynamic?".to_sym and f.dynamic?
85
- return schema
86
- end
87
- rescue StopIteration
88
- raise ParseError.new "#{self.location}: error: invalid cycle detected"
89
- end
81
+ # @return [Group,nil]
82
+ def superGroup
83
+
84
+ result = nil
85
+
86
+ if @super
87
+
88
+ ptr = @super.resolve
89
+ stack = []
90
+ sequence = false
91
+ dynamic = false
92
+
93
+ while ptr and ptr.is_a? Definition and ptr.type.is_a? REF do
94
+
95
+ if stack.include? ptr
96
+ raise ParseError.new "#{@super.location}: supergoup circular reference"
97
+ else
98
+ if ptr.type.dynamic?
99
+ dynamic = true
100
+ end
101
+ if ptr.type.sequence?
102
+ if sequence
103
+ raise ParseError.new "#{@super.location}: sequence of sequence detected at '#{ptr.type.location}'"
90
104
  end
105
+ sequence = true
91
106
  end
107
+ stack << ptr
108
+ ptr = ptr.type.resolve
92
109
  end
93
- rescue StopIteration
94
110
  end
95
111
 
96
- error = false
97
- @fields = {}
98
- if !@superGroup or (@superGroup and @superGroup.link(schema, @ns, stack << self))
99
- if !@superGroup or @superGroup.ref.is_a?(Group)
100
- if @superGroup
101
- if @superGroup.dynamic_reference?
102
- Log.error "#{@superGroup.location}: error: reference to supergroup must not be dynamic"
103
- error = true
104
- else
105
- @superGroup.ref.fields.each do |f|
106
- @fields[f.nameWithID.name] = f
107
- end
108
- end
109
- end
110
- if !error
111
- @rawFields.each do |f|
112
- if @fields[f.nameWithID.name]
113
- Log.error "#{f.location}: error: field names must be unique within a group ('#{f.nameWithID.name}' first appears at #{@fields[f.nameWithID.name].location})"
114
- error = true
115
- else
116
- if f.link(schema, @ns, stack.dup << self)
117
- @fields[f.nameWithID.name] = f
118
- else
119
- error = true
120
- end
121
- end
122
- end
123
- end
124
- else
125
- Log.error "#{@superGroup.location}: error: reference to supergroup must resolve to group definition"
126
- error = true
112
+ if ptr.nil?
113
+ raise ParseError.new "#{@super.location}: supergroup reference '#{@super.ref}' does not resolve"
114
+ elsif ptr.is_a? Definition
115
+ if dynamic
116
+ raise ParseError.new "#{@super.location}: supergroup reference cannot resolve dynamic reference to a #{ptr.type.class} makes no sense"
127
117
  end
118
+ raise ParseError.new "#{@super.location}: supergroup reference must resolve to a group"
128
119
  else
129
- error = true
120
+ if dynamic
121
+ raise ParseError.new "#{@super.location}: supergroup reference cannot be dynamic"
122
+ end
123
+ if sequence
124
+ raise ParseError.new "#{@super.location}: supergroup reference cannot be a sequence"
125
+ end
126
+ if ptr == self
127
+ raise ParseError.new "#{@super.location}: supergroup cannot be own group"
128
+ end
129
+ result = ptr
130
+ end
131
+ end
132
+
133
+ result
134
+ end
135
+
136
+ # @private
137
+ def initialize(attr)
138
+
139
+ @ns = attr[:ns].freeze
140
+ @name = attr[:name][:name].dup
141
+ if @ns
142
+ @name.prepend "#{@ns}::"
143
+ end
144
+ @name.freeze
145
+ @id = attr[:name][:id]
146
+ @location = attr[:name][:loc].freeze
147
+ @fields = {}
148
+
149
+ if attr[:super]
150
+ @super = REF.new(attr[:super].merge(:table=>attr[:table], :ns=>attr[:ns]))
151
+ if @super.ref == @name or @super.ref.split("::").last == @name
152
+ raise ParseError.new "#{@location}: supergroup cannot be own group"
130
153
  end
154
+ else
155
+ @super = nil
156
+ end
131
157
 
132
- if !error
133
- @schema = schema
158
+ attr[:fields].each do |f|
159
+ if @fields[f[:name][:name]]
160
+ raise ParseError.new "#{f[:location]}: duplicate field name"
161
+ else
162
+ @fields[f[:name][:name]] = Field.new(f.merge({:table => attr[:table], :ns => attr[:ns]}))
134
163
  end
135
-
136
164
  end
137
-
138
- @schema
139
- end
140
165
 
141
- # @param name [String] name of field
142
- # @return [Field] field exists
143
- # @return [nil] field does not exist
144
- def field(name)
145
- @fields[name]
146
166
  end
147
167
 
148
- # @api private
149
- # @param superGroup [Group]
150
- # @return [true,false]
151
- def group_kind_of?(superGroup)
152
- (self == superGroup) or (@superGroup and @superGroup.ref.group_kind_of?(superGroup))
153
- end
168
+ protected
169
+
170
+ def rawFields
171
+ @fields.values
172
+ end
154
173
 
155
174
  end
156
175
  end
@@ -25,16 +25,15 @@ module SlowBlink::Message
25
25
  class BINARY
26
26
 
27
27
  # @private
28
- def self.from_compact!(input, stack)
29
- value = input.getBinary!
30
- if value
28
+ def self.from_compact(input, stack)
29
+ if value = input.getBinary
31
30
  if !@size or value.size <= @size
32
31
  self.new(value)
33
32
  else
34
33
  raise WeakError8.new "W8: Binary value exceeds maximum size"
35
34
  end
36
35
  else
37
- value
36
+ nil
38
37
  end
39
38
  end
40
39