slow_blink 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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