slow_blink 0.0.2 → 0.0.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.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/ext/slow_blink/ext_compact_encoder/compact_encoder.c +258 -0
  3. data/ext/slow_blink/ext_compact_encoder/compact_encoder.h +92 -0
  4. data/ext/slow_blink/ext_compact_encoder/ext_compact_encoder.c +555 -0
  5. data/ext/slow_blink/ext_compact_encoder/extconf.rb +4 -0
  6. data/ext/slow_blink/ext_schema_parser/lexer.c +59 -59
  7. data/ext/slow_blink/ext_schema_parser/lexer.h +2 -2
  8. data/ext/slow_blink/ext_schema_parser/parser.c +380 -367
  9. data/ext/slow_blink/ext_schema_parser/parser.h +1 -1
  10. data/lib/slow_blink/annotatable.rb +1 -1
  11. data/lib/slow_blink/annotation.rb +5 -5
  12. data/lib/slow_blink/binary.rb +26 -0
  13. data/lib/slow_blink/boolean.rb +26 -0
  14. data/lib/slow_blink/compact_encoder.rb +45 -71
  15. data/lib/slow_blink/date.rb +25 -0
  16. data/lib/slow_blink/decimal.rb +26 -0
  17. data/lib/slow_blink/definition.rb +19 -10
  18. data/lib/slow_blink/enumeration.rb +14 -36
  19. data/lib/slow_blink/error.rb +19 -0
  20. data/lib/slow_blink/field.rb +3 -16
  21. data/lib/slow_blink/fixed.rb +26 -0
  22. data/lib/slow_blink/floating_point.rb +27 -0
  23. data/lib/slow_blink/group.rb +30 -43
  24. data/lib/slow_blink/incremental_annotation.rb +75 -21
  25. data/lib/slow_blink/integer.rb +65 -0
  26. data/lib/slow_blink/message/binary.rb +87 -0
  27. data/lib/slow_blink/message/boolean.rb +68 -0
  28. data/lib/slow_blink/message/date.rb +33 -0
  29. data/lib/slow_blink/message/decimal.rb +25 -0
  30. data/lib/slow_blink/message/enumeration.rb +69 -0
  31. data/lib/slow_blink/message/field.rb +73 -0
  32. data/lib/slow_blink/message/fixed.rb +84 -0
  33. data/lib/slow_blink/message/floating_point.rb +68 -0
  34. data/lib/slow_blink/message/group.rb +260 -0
  35. data/lib/slow_blink/message/integer.rb +217 -0
  36. data/lib/slow_blink/message/model.rb +202 -0
  37. data/lib/slow_blink/message/sequence.rb +85 -0
  38. data/lib/slow_blink/message/string.rb +95 -0
  39. data/lib/slow_blink/message/time.rb +78 -0
  40. data/lib/slow_blink/message/time_of_day.rb +132 -0
  41. data/lib/slow_blink/name_with_id.rb +2 -1
  42. data/lib/slow_blink/namespace.rb +140 -0
  43. data/lib/slow_blink/object.rb +29 -0
  44. data/lib/slow_blink/ref.rb +93 -0
  45. data/lib/slow_blink/schema.rb +94 -68
  46. data/lib/slow_blink/{component_reference.rb → schema_buffer.rb} +11 -22
  47. data/lib/slow_blink/sequence.rb +58 -0
  48. data/lib/slow_blink/string.rb +40 -0
  49. data/lib/slow_blink/sym.rb +4 -0
  50. data/lib/slow_blink/time.rb +30 -0
  51. data/lib/slow_blink/time_of_day.rb +30 -0
  52. data/lib/slow_blink/type.rb +7 -402
  53. data/lib/slow_blink/version.rb +1 -1
  54. data/lib/slow_blink.rb +1 -0
  55. data/rakefile +14 -3
  56. data/test/{integration/capture_stderr.rb → capture_stderr.rb} +0 -0
  57. data/test/tc_compact_encoder.rb +341 -0
  58. data/test/tc_field.rb +53 -0
  59. data/test/tc_group.rb +122 -0
  60. data/test/tc_incr_annote.rb +27 -0
  61. data/test/{integration/tc_inputs.rb → tc_inputs.rb} +7 -11
  62. data/test/tc_model.rb +65 -0
  63. data/test/tc_model_encode.rb +63 -0
  64. data/test/tc_namespace.rb +8 -0
  65. data/test/tc_types.rb +198 -0
  66. metadata +58 -11
  67. data/ext/slow_blink/ext_schema_parser/parser.l +0 -139
  68. data/ext/slow_blink/ext_schema_parser/parser.y +0 -932
  69. data/lib/slow_blink/message.rb +0 -43
@@ -0,0 +1,202 @@
1
+ # Copyright (c) 2016 Cameron Harper
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module SlowBlink
21
+
22
+ module Message
23
+
24
+ class Error < Exception
25
+ end
26
+
27
+ class Model
28
+
29
+ # @param nameOrID [String,Integer] name or id of top-level group
30
+ # @return [Class] anonymous class extending {DynamicGroup::CLASS} and including {DynamicGroup::INSTANCE}
31
+ def [](nameOrID)
32
+ if nameOrID.kind_of? Integer
33
+ @top.new(@top.groups.values.detect{|g|g.name == nameOrID})
34
+ else
35
+ @top.new(@top.groups[nameOrID])
36
+ end
37
+ end
38
+
39
+ attr_reader :top
40
+
41
+ # Initialise a message model from a schema
42
+ #
43
+ # @param schema [Schema]
44
+ # @param opts [Hash]
45
+ def initialize(schema, **opts)
46
+ @schema = schema
47
+ @groups = {}
48
+ schema.tagged.each do |id, g|
49
+ @groups[id] = _model_group(false, g)
50
+ end
51
+ groups = @groups
52
+ @top = Class.new do
53
+ @opt = false
54
+ @groups = groups
55
+ @permitted = groups.keys
56
+ extend DynamicGroup::CLASS
57
+ include DynamicGroup::INSTANCE
58
+ end
59
+ end
60
+
61
+ def decode_compact(input)
62
+ @top.from_compact!(input.dup)
63
+ end
64
+
65
+ def encode_compact(input)
66
+ @top.from_compact!(input)
67
+ end
68
+
69
+ def group(name, &block)
70
+ group = @top.groups.values.detect{|g|g.name == name}
71
+ if group
72
+ top = @top.new(group.new(nil))
73
+ top.instance_exec(top, &block)
74
+ top
75
+ else
76
+ raise
77
+ end
78
+ end
79
+
80
+ def new(&block)
81
+ if block.nil?
82
+ raise
83
+ end
84
+ result = self.instance_exec(&block)
85
+ end
86
+
87
+ # @private
88
+ #
89
+ # Create a model for a Group
90
+ #
91
+ # @param opt [true,false] this group is allowed to be optional
92
+ # @param group [SlowBlink::Group] group definition
93
+ # @return [Class] anonymous class extending {StaticGroup::CLASS} and including {StaticGroup::INSTANCE}
94
+ def _model_group(opt, group)
95
+ this = self
96
+ klass = Class.new do
97
+ @name = group.nameWithID.name
98
+ @id = group.nameWithID.id
99
+ @opt = opt
100
+ @fields = group.fields.inject([]) do |fields, f|
101
+ fields << this._model_field(f)
102
+ end
103
+ extend StaticGroup::CLASS
104
+ include StaticGroup::INSTANCE
105
+ end
106
+ end
107
+
108
+
109
+ # @private
110
+ #
111
+ # Create a model for a Field
112
+ #
113
+ # @param field [SlowBlink::Field] field definition
114
+ # @return [Class] anonymous class extending {Field::CLASS} and including {Field::INSTANCE}
115
+ def _model_field(field)
116
+ this = self
117
+ klass = Class.new do
118
+ @opt = field.opt?
119
+ @name = field.nameWithID.name
120
+ @id = field.nameWithID.id
121
+ @type = this._model_type(field)
122
+ include Field::INSTANCE
123
+ extend Field::CLASS
124
+ end
125
+ end
126
+
127
+ # @private
128
+ #
129
+ # Create a model for a type
130
+ #
131
+ # @param field [SlowBlink::Field] field definition (containing type)
132
+ # @return [Class] anonymous class extending {Field::CLASS} and including {Field::INSTANCE}
133
+ def _model_type(field)
134
+ type = field.type
135
+ name = field.nameWithID.name
136
+ case type.class
137
+ when SlowBlink::OBJECT
138
+ groups = @groups
139
+ permitted = @schema.tagged.keys
140
+ klass = Class.new do
141
+ @opt = field.opt?
142
+
143
+ @groups = groups
144
+ @permitted = permitted
145
+ extend DynamicGroup::CLASS
146
+ include DynamicGroup::INSTANCE
147
+ end
148
+ when SlowBlink::REF
149
+ if type.ref.kind_of? Group
150
+ if type.dynamic?
151
+ groups = @groups
152
+ permitted = @schema.tagged.keys
153
+ @schema.tagged.each do |id, g|
154
+ if g.group_kind_of?(type)
155
+ permitted << id
156
+ end
157
+ end
158
+ klass = Class.new do
159
+ @name = name
160
+ @opt = field.opt?
161
+ @groups = groups
162
+ @permitted = permitted
163
+ extend DynamicGroup::CLASS
164
+ include DynamicGroup::INSTANCE
165
+ end
166
+ else
167
+ _model_group(field.opt?, type.ref)
168
+ end
169
+ else
170
+ _model_type(opt, type.ref)
171
+ end
172
+ else
173
+ return Class.new do
174
+ @opt = field.opt?
175
+ @name = name
176
+ @type = type
177
+ extend SlowBlink::Message.const_get(type.class.name.split('::').last + "::CLASS")
178
+ include SlowBlink::Message.const_get(type.class.name.split('::').last + "::INSTANCE")
179
+ end
180
+ end
181
+ end
182
+
183
+ end
184
+
185
+ end
186
+
187
+ end
188
+
189
+ require "slow_blink/message/field"
190
+ require "slow_blink/message/integer"
191
+ require "slow_blink/message/string"
192
+ require "slow_blink/message/binary"
193
+ require "slow_blink/message/fixed"
194
+ require "slow_blink/message/boolean"
195
+ require "slow_blink/message/enumeration"
196
+ require "slow_blink/message/floating_point"
197
+ require "slow_blink/message/sequence"
198
+ require "slow_blink/message/group"
199
+ require "slow_blink/message/time"
200
+ require "slow_blink/message/time_of_day"
201
+ require "slow_blink/message/date"
202
+
@@ -0,0 +1,85 @@
1
+ # Copyright (c) 2016 Cameron Harper
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module SlowBlink::Message
21
+
22
+ module SEQUENCE
23
+
24
+ module CLASS
25
+
26
+ def from_compact!(input)
27
+ value = []
28
+ size = input.getU32!
29
+ if size
30
+ while out.size < size do
31
+ value << @type.from_compact!(input)
32
+ end
33
+ self.new(value)
34
+ else
35
+ self.new
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ module INSTANCE
42
+
43
+ # @param v [Array,nil]
44
+ def set(value)
45
+ if value
46
+ if value.kind_of? Array
47
+ @value = v
48
+ else
49
+ raise Error.new "bad type"
50
+ end
51
+ elsif self.class.opt?
52
+ @value = nil
53
+ else
54
+ raise Error.new "value unacceptable"
55
+ end
56
+ end
57
+
58
+ def get
59
+ @value
60
+ end
61
+
62
+ # @param value [Array]
63
+ def initialize(value)
64
+ if value
65
+ set(value)
66
+ else
67
+ @value = nil
68
+ end
69
+ end
70
+
71
+ def to_compact(out)
72
+ if @value
73
+ @value.inject(out.putU32(@value.size)) do |out, v|
74
+ out << v.to_compact
75
+ end
76
+ else
77
+ out.putU32(nil)
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ end
@@ -0,0 +1,95 @@
1
+ # Copyright (c) 2016 Cameron Harper
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module SlowBlink::Message
21
+
22
+ module STRING
23
+
24
+ module CLASS
25
+
26
+ def name
27
+ @name
28
+ end
29
+
30
+ def opt?
31
+ @opt
32
+ end
33
+
34
+ def from_compact!(input)
35
+ value = input.getString!
36
+ if value
37
+ if !@type.size or value.size <= @type.size
38
+ self.new(value)
39
+ else
40
+ raise Error.new "W7: String value exceeds maximum size"
41
+ end
42
+ elsif @opt
43
+ self.new(nil)
44
+ else
45
+ raise Error.new "W5: Value cannot be null"
46
+ end
47
+ end
48
+
49
+ def size
50
+ @type.size
51
+ end
52
+
53
+ end
54
+
55
+ module INSTANCE
56
+
57
+ def get
58
+ @value
59
+ end
60
+
61
+ def set(value)
62
+ if value
63
+ if value.kind_of? String
64
+ if !self.class.size or value.size <= self.class.size
65
+ @value = value
66
+ else
67
+ raise Error.new "string cannot be larger than #{self.class.size} bytes"
68
+ end
69
+ else
70
+ raise Error.new "expecting a string type"
71
+ end
72
+ elsif self.class.opt?
73
+ @value = nil
74
+ else
75
+ raise Error.new "string cannot be null"
76
+ end
77
+ end
78
+
79
+ def initialize(value)
80
+ if value
81
+ set(value)
82
+ else
83
+ @value = nil
84
+ end
85
+ end
86
+
87
+ def to_compact(out)
88
+ out.putString(@value)
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,78 @@
1
+ # Copyright (c) 2016 Cameron Harper
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module SlowBlink::Message
21
+
22
+ module MILLI_TIME
23
+
24
+ module CLASS
25
+
26
+ def from_compact!(input)
27
+ self.new(input.getI64!)
28
+ end
29
+
30
+ end
31
+
32
+ module INSTANCE
33
+
34
+ def set(value)
35
+ if value
36
+ raise
37
+ elsif self.class.opt?
38
+ @value = nil
39
+ else
40
+ raise
41
+ end
42
+ end
43
+
44
+ def get
45
+ @value
46
+ end
47
+
48
+ def initialize(value)
49
+ if value
50
+ set(value)
51
+ else
52
+ @value = nil
53
+ end
54
+ end
55
+
56
+ def to_compact(out)
57
+ out.putI64(@value)
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ module NANO_TIME
65
+
66
+ module CLASS
67
+
68
+ include SlowBlink::Message::MILLI_TIME::CLASS
69
+ end
70
+
71
+ module INSTANCE
72
+
73
+ include SlowBlink::Message::MILLI_TIME::INSTANCE
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,132 @@
1
+ # Copyright (c) 2016 Cameron Harper
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ # this software and associated documentation files (the "Software"), to deal in
5
+ # the Software without restriction, including without limitation the rights to
6
+ # use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ # the Software, and to permit persons to whom the Software is furnished to do so,
8
+ # subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ # FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ # COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
+
20
+ module SlowBlink::Message
21
+
22
+ module TIME_OF_DAY_MILLI
23
+
24
+ module CLASS
25
+
26
+ def from_compact!(input)
27
+ self.new(input.get32!)
28
+ end
29
+
30
+ end
31
+
32
+ module INSTANCE
33
+
34
+ def set(value)
35
+ if value
36
+ if value.kind_of? Integer
37
+ if value < 86400000
38
+ @value = value
39
+ else
40
+ raise Error.new "input out of range"
41
+ end
42
+ elsif value.kind_of? Time
43
+ @value = value.to_i
44
+ else
45
+ raise "what is this?"
46
+ end
47
+ elsif self.class.opt?
48
+ @value = nil
49
+ else
50
+ raise
51
+ end
52
+ end
53
+
54
+ def get
55
+ @value
56
+ end
57
+
58
+ def initialize(value)
59
+ if value
60
+ set(value)
61
+ else
62
+ @value = nil
63
+ end
64
+ end
65
+
66
+ # @private
67
+ def to_compact(out)
68
+ out.putU32(@value)
69
+
70
+
71
+
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ module TIME_OF_DAY_NANO
79
+
80
+ module CLASS
81
+
82
+ def from_compact!(input)
83
+ self.new(input.getU64!)
84
+ end
85
+
86
+ end
87
+
88
+ module INSTANCE
89
+
90
+
91
+ def set(value)
92
+ if value
93
+ if value.kind_of? Integer
94
+ if value < 86400000000000
95
+ @value = value
96
+ else
97
+ raise Error.new "input out of range"
98
+ end
99
+ elsif value.kind_of? Time
100
+ @value = value.to_i
101
+ else
102
+ raise "what is this?"
103
+ end
104
+ elsif self.class.opt?
105
+ @value = nil
106
+ else
107
+ raise
108
+ end
109
+ end
110
+
111
+ def get
112
+ @value
113
+ end
114
+
115
+ def initialize(value)
116
+ if value
117
+ set(value)
118
+ else
119
+ @value = nil
120
+ end
121
+ end
122
+
123
+ # @private
124
+ def to_compact(out)
125
+ out.putU64(@value)
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
132
+ end
@@ -34,8 +34,9 @@ module SlowBlink
34
34
  # @param name [String]
35
35
  # @param id [nil,Integer]
36
36
  def initialize(name, id)
37
+ @annotes = {}
37
38
  @name = name
38
- @id = id
39
+ @id = id
39
40
  end
40
41
 
41
42
  # @private