slow_blink 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
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
+ module Annotatable
22
+
23
+ # @return [Array<Annotation>]
24
+ attr_reader :annotes
25
+
26
+ # @private
27
+ #
28
+ # @param annotes [Array<Annotation,Integer>]
29
+ def annote(annotes)
30
+ annotes.each do |a|
31
+ if a.is_a? Annotation
32
+ if @annotes[a.id]
33
+ puts "#{a.location}: warning: overriding previous annotation for id '#{a.id}'"
34
+ end
35
+ @annotes[a.id] = a
36
+ else
37
+ if @nameWithID.id
38
+ puts "#{a.location}: warning: overriding previous id"
39
+ end
40
+ @nameWithID.id = a
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,38 @@
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
+ class Annotation
22
+
23
+ attr_reader :location
24
+ attr_reader :id
25
+ attr_reader :literal
26
+
27
+ # @param id [String] any string
28
+ # @param literal [String] any string
29
+ # @param location [String]
30
+ def initialize(id,literal,location)
31
+ @id = id
32
+ @literal = literal
33
+ @location = location
34
+ end
35
+
36
+ end
37
+ end
38
+
@@ -0,0 +1,97 @@
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
+ # SlowBlink
21
+ module SlowBlink
22
+
23
+ module CompactEncoder
24
+
25
+ # @return [String]
26
+ def self.putNull
27
+ "\x40"
28
+ end
29
+
30
+ # @return [String]
31
+ def self.putPresent
32
+ "\x01"
33
+ end
34
+
35
+ def self.putBool(value)
36
+ (value) ? "\x01" : "\x00"
37
+ end
38
+
39
+ # @param value [Float]
40
+ # @return [String]
41
+ def self.putF64(value)
42
+ putVLC([value].pack("G").unpack("Q<").first)
43
+ end
44
+
45
+ def self.putString(value)
46
+ putVLC(value.size) + value
47
+ end
48
+
49
+ def self.putBinary(value)
50
+ putVLC(value.size) + value.to_s
51
+ end
52
+
53
+ def self.putFixed(value)
54
+ value.to_s
55
+ end
56
+
57
+
58
+
59
+
60
+
61
+ # @private
62
+ #
63
+ # @param value [Integer] unsigned integer
64
+ # @return [Integer] bytes to encode as VLC
65
+ def self.getSizeUnsigned(value)
66
+ end
67
+
68
+ # @private
69
+ #
70
+ # @param value [Integer] signed integer
71
+ # @return [Integer] bytes to encode as VLC
72
+ def self.getSizeSigned(value)
73
+ end
74
+
75
+ # @private
76
+ #
77
+ # @param value [Integer] signed or unsigned integer
78
+ # @param opts [Hash] option
79
+ # @option opts [Symbol] :signed value is a signed integer
80
+ def self.putVLC(value, **opts)
81
+ bytes = opts[:signed] ? getSizeSigned(value) : getSizeUnsigned(value)
82
+ case bytes
83
+ when 1
84
+ [value].pack("C")
85
+ when 2
86
+ [0x80 | value].pack("S<")
87
+ else
88
+ out = [0xc0 | bytes]
89
+ while out.size < (bytes - 1) do
90
+ out << (value >> 8)
91
+ end
92
+ out.pack("S<C#{bytes-2}")
93
+ end
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,50 @@
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
+ # SCHEMA
23
+ class SchemaRef
24
+ end
25
+
26
+ # qName
27
+ class DefinitionRef < SchemaRef
28
+ # @param qName [String] name of the definition to annotate
29
+ def initialize(qName)
30
+ @qName = qName
31
+ end
32
+ end
33
+
34
+ # qName.TYPE
35
+ class DefinitionTypeRef < DefinitionRef
36
+ end
37
+
38
+ # qName.name
39
+ class FieldRef < SchemaRef
40
+ def initialize(qName, name)
41
+ @qName = qName
42
+ @name = name
43
+ end
44
+ end
45
+
46
+ # qName.name.TYPE
47
+ class FieldTypeRef < FieldRef
48
+ end
49
+
50
+ end
@@ -0,0 +1,57 @@
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
+ class Definition
22
+
23
+ include Annotatable
24
+ extend CompactEncoder
25
+
26
+ # @return [String]
27
+ attr_reader :location
28
+
29
+ # @return [String]
30
+ attr_reader :nameWithID
31
+
32
+ # @return [Enumeration]
33
+ # @return [Type]
34
+ attr_reader :enumOrType
35
+
36
+ # @private
37
+ #
38
+ # @param nameWithID [NameWithID]
39
+ # @param enumOrType [Enumeration, Type]
40
+ # @param location [String]
41
+ def initialize(nameWithID, enumOrType, location)
42
+ @annotes = {}
43
+ @schema = nil
44
+ @enumOrType = enumOrType
45
+ @location = location
46
+ @nameWithID = nameWithID
47
+ end
48
+
49
+ # @private
50
+ #
51
+ # @!macro common_link
52
+ def link(schema, stack=[])
53
+ @schema = @enumOrType.link(schema, stack << self)
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,105 @@
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
+ class Enumeration
23
+
24
+ include Annotatable
25
+ extend CompactEncoder
26
+
27
+ # @private
28
+ #
29
+ # @param syms [Array<Sym>] symbol list
30
+ def initialize(syms)
31
+ @annotes = {}
32
+ @rawSyms = syms
33
+ @syms = {}
34
+ @schema = nil
35
+ end
36
+
37
+ def ===(other)
38
+ self.class == other.class
39
+ end
40
+
41
+ # @private
42
+ #
43
+ # @macro common_link
44
+ def link(schema, stack=[])
45
+ if @schema != schema
46
+ @schema = nil
47
+ value = 0
48
+ errors = 0
49
+ @syms = {}
50
+ @rawSyms.each do |s|
51
+ if @syms[s.name]
52
+ puts "#{s.location}: error: duplicate name"
53
+ errors += 1
54
+ else
55
+ if s.val
56
+ if @syms.values.include? s.val
57
+ puts "#{s.location}: error: duplicate value"
58
+ errors += 1
59
+ else
60
+ value = s.val + 1
61
+ end
62
+ else
63
+ @syms[s.name] = value
64
+ value += 1
65
+ end
66
+ end
67
+ end
68
+ if errors == 0
69
+ @schema = schema
70
+ end
71
+ end
72
+ @schema
73
+ end
74
+
75
+ # @param nameOrVal [String,Integer]
76
+ # @return [Sym]
77
+ # @return [nil]
78
+ def sym(nameOrVal)
79
+ if key.kind_of? String
80
+ @syms[key.to_s]
81
+ else
82
+ @syms.detect{|s|s.val == s.to_i}
83
+ end
84
+ end
85
+
86
+ # @private
87
+ def validate(input)
88
+ if sym(input)
89
+ true
90
+ else
91
+ raise
92
+ end
93
+ end
94
+
95
+ # @private
96
+ def encode_compact(value, **opts)
97
+ if opts[:opt]
98
+ putPresent + putVLC(value)
99
+ else
100
+ putVLC(value)
101
+ end
102
+ end
103
+
104
+ end
105
+ end
@@ -0,0 +1,4 @@
1
+ module SlowBlink
2
+ class Error < Exception
3
+ end
4
+ end
@@ -0,0 +1,82 @@
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
+ class Field
23
+
24
+ include Annotatable
25
+ extend CompactEncoder
26
+
27
+ # @return [String]
28
+ attr_reader :location
29
+
30
+ # @return [Type]
31
+ attr_reader :type
32
+
33
+ # @return [NameWithID]
34
+ attr_reader :nameWithID
35
+
36
+ # @return [true] field is optional
37
+ # @return [false] field is mandatory
38
+ def opt?
39
+ @opt
40
+ end
41
+
42
+ # @private
43
+ #
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
55
+ end
56
+
57
+ # @private
58
+ #
59
+ # @!macro common_link
60
+ def link(schema,stack=[])
61
+ if @schema != schema
62
+ @schema = nil
63
+ if @type.link(schema, stack << self)
64
+ @schema = schema
65
+ end
66
+ end
67
+ @schema
68
+ end
69
+
70
+ # @private
71
+ def encode_compact(value, **opts)
72
+ if value[name]
73
+ @type.encode_compact(value[:name], opt: @opt)
74
+ elsif @opt
75
+ putNull
76
+ else
77
+ raise
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,129 @@
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
+ class Group
23
+
24
+ include Annotatable
25
+ extend CompactEncoder
26
+
27
+ # @return [String]
28
+ attr_reader :location
29
+
30
+ # @return [NameWithID]
31
+ attr_reader :nameWithID
32
+
33
+ # @private
34
+ #
35
+ # @param nameWithID [NameWithID]
36
+ # @param superGroup [REF, nil]
37
+ # @param fields [Array<Field>]
38
+ # @param location [String]
39
+ def initialize(nameWithID, superGroup, fields, location)
40
+ @annotes = {}
41
+ @schema = nil
42
+ @superGroup = superGroup
43
+ @rawFields = fields
44
+ @location = location
45
+ @fields = []
46
+ @nameWithID = nameWithID
47
+ end
48
+
49
+ # @private
50
+ #
51
+ # @macro common_link
52
+ def link(schema,stack=[])
53
+ if @schema != schema
54
+ errors = 0
55
+ @schema = nil
56
+ @fields = {}
57
+ if !@superGroup or (@superGroup and @superGroup.link(schema, stack << self))
58
+ if !@superGroup or @superGroup.value.is_a?(Group)
59
+ if @superGroup
60
+ @fields.merge(@superGroup.value.fields)
61
+ end
62
+ @rawFields.each do |f|
63
+ if @fields[f.nameWithID.name]
64
+ puts "#{f.location}: error: field with duplicate name '#{f.nameWithID.name}'"
65
+ errors += 1
66
+ else
67
+ if f.link(schema, stack.dup << self)
68
+ @fields[f.nameWithID.name] = f
69
+ else
70
+ errors += 1
71
+ end
72
+ end
73
+ end
74
+ if errors == 0
75
+ @schema = schema
76
+ end
77
+ else
78
+ puts "#{@superGroup.location}: error: superGroup must be a group"
79
+ end
80
+ end
81
+ end
82
+ @schema
83
+ end
84
+
85
+ # @param name [String] name of field
86
+ # @return [Field] field exists
87
+ # @return [nil] field does not exist
88
+ def field(name)
89
+ @fields[name]
90
+ end
91
+
92
+ def fields
93
+ @fields
94
+ end
95
+
96
+ # @private
97
+ def validate(value)
98
+ if value.kind_of? Hash
99
+ if value["$type"] == @nameWithID.name
100
+ @fields.each do |name,f|
101
+ f.validate(value[name])
102
+ end
103
+ true
104
+ else
105
+ raise
106
+ end
107
+ end
108
+ end
109
+
110
+ # @private
111
+ #
112
+ # @param value [Hash] Blink JSON format
113
+ # @param opts [Hash] options
114
+ # @option opts [Symbol] :dynamic encode as dynamic group
115
+ # @return [String] compact format
116
+ def encode_compact(value, **opts)
117
+ out = ""
118
+ @fields.each do |name, f|
119
+ out << f.encode_compact(value)
120
+ end
121
+ if opts[:dynamic]
122
+ putVLC(@nameWithID.id) + putVLC(out.size) + out
123
+ else
124
+ out
125
+ end
126
+ end
127
+
128
+ end
129
+ end