slow_blink 0.0.3 → 0.0.4

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/ext/slow_blink/ext_schema_parser/parser.c +245 -245
  3. data/lib/slow_blink/annotatable.rb +1 -2
  4. data/lib/slow_blink/annotation.rb +8 -1
  5. data/lib/slow_blink/compact_encoder.rb +1 -0
  6. data/lib/slow_blink/definition.rb +34 -10
  7. data/lib/slow_blink/enumeration.rb +15 -12
  8. data/lib/slow_blink/field.rb +9 -8
  9. data/lib/slow_blink/group.rb +61 -24
  10. data/lib/slow_blink/incremental_annotation.rb +7 -4
  11. data/lib/slow_blink/integer.rb +1 -1
  12. data/{test/tc_model.rb → lib/slow_blink/log.rb} +23 -40
  13. data/lib/slow_blink/message/binary.rb +39 -45
  14. data/lib/slow_blink/message/boolean.rb +25 -33
  15. data/lib/slow_blink/message/date.rb +2 -7
  16. data/lib/slow_blink/message/decimal.rb +1 -1
  17. data/lib/slow_blink/message/enumeration.rb +29 -33
  18. data/lib/slow_blink/message/field.rb +29 -37
  19. data/lib/slow_blink/message/fixed.rb +37 -45
  20. data/lib/slow_blink/message/floating_point.rb +24 -32
  21. data/lib/slow_blink/message/group.rb +172 -187
  22. data/lib/slow_blink/message/integer.rb +83 -132
  23. data/lib/slow_blink/message/model.rb +64 -63
  24. data/lib/slow_blink/message/sequence.rb +40 -48
  25. data/lib/slow_blink/message/string.rb +44 -51
  26. data/lib/slow_blink/message/time.rb +25 -40
  27. data/lib/slow_blink/message/time_of_day.rb +73 -86
  28. data/lib/slow_blink/name_with_id.rb +2 -6
  29. data/lib/slow_blink/namespace.rb +36 -36
  30. data/lib/slow_blink/ref.rb +29 -13
  31. data/lib/slow_blink/schema.rb +26 -10
  32. data/lib/slow_blink/schema_buffer.rb +14 -0
  33. data/lib/slow_blink/sequence.rb +16 -20
  34. data/lib/slow_blink/string.rb +0 -2
  35. data/lib/slow_blink/sym.rb +7 -5
  36. data/lib/slow_blink/type.rb +8 -5
  37. data/lib/slow_blink/version.rb +1 -1
  38. data/test/tc_field.rb +41 -0
  39. data/test/tc_group.rb +11 -0
  40. data/test/tc_model_static_group.rb +114 -0
  41. data/test/{tc_model_encode.rb → tc_model_think_blink.rb} +58 -13
  42. data/test/tc_types.rb +39 -0
  43. metadata +7 -6
@@ -18,13 +18,12 @@
18
18
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
19
 
20
20
  module SlowBlink
21
+
21
22
  module Annotatable
22
23
 
23
24
  # @return [Array<Annotation>]
24
25
  attr_reader :annotes
25
26
 
26
- # @private
27
- #
28
27
  # @param annotes [Array<Annotation,Integer>]
29
28
  def annote(annotes)
30
29
  annotes.each do |a|
@@ -1,3 +1,4 @@
1
+
1
2
  # Copyright (c) 2016 Cameron Harper
2
3
  #
3
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -18,12 +19,18 @@
18
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20
 
20
21
  module SlowBlink
22
+
21
23
  class Annotation
22
24
 
25
+ # @macro location
23
26
  attr_reader :location
27
+
28
+ # @return [String]
24
29
  attr_reader :id
30
+
31
+ # @return [Integer]
25
32
  attr_reader :value
26
-
33
+
27
34
  # @param id [String] any string
28
35
  # @param value [String] any string
29
36
  # @param location [String]
@@ -19,6 +19,7 @@
19
19
 
20
20
  module SlowBlink
21
21
 
22
+ # @api private
22
23
  module CompactEncoder
23
24
 
24
25
  # @!method getU8(input)
@@ -1,3 +1,4 @@
1
+
1
2
  # Copyright (c) 2016 Cameron Harper
2
3
  #
3
4
  # Permission is hereby granted, free of charge, to any person obtaining a copy of
@@ -18,6 +19,7 @@
18
19
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20
 
20
21
  module SlowBlink
22
+
21
23
  class Definition
22
24
 
23
25
  include Annotatable
@@ -26,14 +28,13 @@ module SlowBlink
26
28
  self == other
27
29
  end
28
30
 
29
- # @return [String]
31
+ # @macro location
30
32
  attr_reader :location
31
33
 
32
- # @return [String]
34
+ # @return [NameWithID]
33
35
  attr_reader :nameWithID
34
36
 
35
- # @return [ENUMERATION]
36
- # @return [Type]
37
+ # @return [Type,ENUMERATION]
37
38
  attr_reader :type
38
39
 
39
40
  # @param namespace [Namespace]
@@ -41,25 +42,48 @@ module SlowBlink
41
42
  @ns = namespace
42
43
  end
43
44
 
44
- # @private
45
- #
46
45
  # @param nameWithID [NameWithID]
47
46
  # @param type [ENUMERATION, Type]
48
47
  # @param location [String]
49
48
  def initialize(nameWithID, type, location)
50
49
  @annotes = {}
51
- @schema = nil
52
50
  @type = type
53
51
  @location = location
54
52
  @nameWithID = nameWithID
55
53
  @ns = nil
56
54
  end
57
55
 
56
+ # @api private
57
+ # Resolve references, enforce constraints, and detect cycles
58
+ #
59
+ # @param schema [Schema] schema this definition belongs to
60
+ # @param stack [nil, Array] objects that depend on this object
61
+ # @return [true,false] linked?
58
62
  def link(schema, stack=[])
59
- if @schema.nil?
60
- @schema = @type.link(schema, @ns, stack << self)
63
+
64
+ # a definition can resolve to a definition only if there is a dynamic
65
+ # link somewhere in the chain
66
+ sf = stack.each
67
+ begin
68
+ loop do
69
+ if sf.next == self
70
+ loop do
71
+ begin
72
+ f = sf.next
73
+ if f.respond_to? "dynamic?".to_sym and f.dynamic?
74
+ return schema
75
+ end
76
+ rescue StopIteration
77
+ raise Error.new "#{self.location}: error: invalid cycle detected"
78
+ end
79
+ end
80
+ end
81
+ end
82
+ rescue StopIteration
61
83
  end
62
- @schema
84
+
85
+ @type.link(schema, @ns, stack << self)
86
+
63
87
  end
64
88
 
65
89
  end
@@ -27,8 +27,6 @@ module SlowBlink
27
27
  self == other
28
28
  end
29
29
 
30
- # @private
31
- #
32
30
  # @param syms [Array<Sym>] symbol list
33
31
  def initialize(syms)
34
32
  @annotes = {}
@@ -37,20 +35,28 @@ module SlowBlink
37
35
  @schema = nil
38
36
  end
39
37
 
38
+ # @api private
39
+ #
40
+ # Resolve references, enforce constraints, and detect cycles
41
+ #
42
+ # @param schema [Schema] schema this definition belongs to
43
+ # @param ns [Namespace] namespace this definition belongs to
44
+ # @param stack [nil, Array] objects that depend on this object
45
+ # @return [true,false] linked?
40
46
  def link(schema, ns, stack=[])
41
47
  if @schema.nil?
42
48
  value = 0
43
- errors = 0
44
- @syms = {}
49
+ @syms = {}
50
+ @schema = schema
45
51
  @rawSyms.each do |s|
46
52
  if @syms[s.name]
47
- puts "#{s.location}: error: duplicate name '#{s.name}' (first defined at #{@syms[s.name].location})"
48
- errors += 1
53
+ Log.error "#{s.location}: error: symbols within an enumeration must have unique names ('#{s.name}' first appears at #{@syms[s.name].location})"
54
+ @schema = nil
49
55
  else
50
56
  if s.val
51
57
  if @syms.values.include? s.val
52
- puts "#{s.location}: error: duplicate value"
53
- errors += 1
58
+ Log.error "#{s.location}: error: values of symbols must be distinct ('#{s.val}' first appears at #{@syms[s.val].location})"
59
+ @schema = nil
54
60
  else
55
61
  value = s.val + 1
56
62
  end
@@ -60,10 +66,7 @@ module SlowBlink
60
66
  end
61
67
  @syms[s.name] = s
62
68
  end
63
- end
64
- if errors == 0
65
- @schema = schema
66
- end
69
+ end
67
70
  end
68
71
  @schema
69
72
  end
@@ -23,7 +23,7 @@ module SlowBlink
23
23
 
24
24
  include Annotatable
25
25
 
26
- # @return [String]
26
+ # @macro location
27
27
  attr_reader :location
28
28
 
29
29
  # @return [Type]
@@ -38,8 +38,6 @@ module SlowBlink
38
38
  @opt
39
39
  end
40
40
 
41
- # @private
42
- #
43
41
  # @param nameWithID [NameWithID]
44
42
  # @param type [Type]
45
43
  # @param opt [true,false] field is optional?
@@ -53,14 +51,17 @@ module SlowBlink
53
51
  @nameWithID = nameWithID
54
52
  end
55
53
 
56
- # @private
54
+ # @api private
55
+ #
56
+ # Resolve references, enforce constraints, and detect cycles
57
57
  #
58
- # @!macro common_link
58
+ # @param schema [Schema] schema this definition belongs to
59
+ # @param ns [Namespace] namespace this definition belongs to
60
+ # @param stack [nil, Array] objects that depend on this object
61
+ # @return [true,false] linked?
59
62
  def link(schema,ns, stack=[])
60
63
  if @schema.nil?
61
- if @type.link(schema, ns, stack << self)
62
- @schema = schema
63
- end
64
+ @schema = @type.link(schema, ns, stack << self)
64
65
  end
65
66
  @schema
66
67
  end
@@ -27,7 +27,7 @@ module SlowBlink
27
27
  self == other
28
28
  end
29
29
 
30
- # @return [String]
30
+ # @macro location
31
31
  attr_reader :location
32
32
 
33
33
  # @return [NameWithID]
@@ -43,8 +43,6 @@ module SlowBlink
43
43
  @ns = namespace
44
44
  end
45
45
 
46
- # @private
47
- #
48
46
  # @param nameWithID [NameWithID]
49
47
  # @param superGroup [REF, nil]
50
48
  # @param fields [Array<Field>]
@@ -59,42 +57,82 @@ module SlowBlink
59
57
  @nameWithID = nameWithID
60
58
  @ns = nil
61
59
  end
62
-
63
- # @private
60
+
61
+ # @api private
62
+ #
63
+ # Resolve references, enforce constraints, and detect cycles
64
64
  #
65
- # @macro common_link
65
+ # @param schema [Schema] schema this definition belongs to
66
+ # @param stack [nil, Array] objects that depend on this object
67
+ # @return [true,false] linked?
66
68
  def link(schema,stack=[])
69
+
67
70
  if @schema.nil?
68
- errors = 0
71
+
72
+ # a definition can resolve to a definition only if there is a dynamic
73
+ # link somewhere in the chain
74
+ sf = stack.each
75
+ begin
76
+ loop do
77
+ if sf.next == self
78
+ loop do
79
+ begin
80
+ f = sf.next
81
+ if f.respond_to? "dynamic?".to_sym and f.dynamic?
82
+ return schema
83
+ end
84
+ rescue StopIteration
85
+ raise Error.new "#{self.location}: error: invalid cycle detected"
86
+ end
87
+ end
88
+ end
89
+ end
90
+ rescue StopIteration
91
+ end
92
+
93
+ error = false
69
94
  @fields = {}
70
95
  if !@superGroup or (@superGroup and @superGroup.link(schema, @ns, stack << self))
71
96
  if !@superGroup or @superGroup.ref.is_a?(Group)
72
97
  if @superGroup
73
- @superGroup.ref.fields.each do |f|
74
- @fields[f.nameWithID.name] = f
75
- end
76
- end
77
- @rawFields.each do |f|
78
- if @fields[f.nameWithID.name]
79
- puts "#{f.location}: error: duplicate field name '#{f.nameWithID.name}' (first defined at #{@fields[f.nameWithID.name].location})"
80
- errors += 1
98
+ if @superGroup.dynamic_reference?
99
+ Log.error "#{@superGroup.location}: error: reference to supergroup must not be dynamic"
100
+ error = true
81
101
  else
82
- if f.link(schema, @ns, stack.dup << self)
102
+ @superGroup.ref.fields.each do |f|
83
103
  @fields[f.nameWithID.name] = f
84
- else
85
- errors += 1
86
104
  end
87
105
  end
88
106
  end
89
- if errors == 0
90
- @schema = schema
107
+ if !error
108
+ @rawFields.each do |f|
109
+ if @fields[f.nameWithID.name]
110
+ Log.error "#{f.location}: error: field names must be unique within a group ('#{f.nameWithID.name}' first appears at #{@fields[f.nameWithID.name].location})"
111
+ error = true
112
+ else
113
+ if f.link(schema, @ns, stack.dup << self)
114
+ @fields[f.nameWithID.name] = f
115
+ else
116
+ error = true
117
+ end
118
+ end
119
+ end
91
120
  end
92
121
  else
93
- puts "#{@superGroup.location}: error: superGroup '#{@superGroup.qname}' must resolve to a group definition"
122
+ Log.error "#{@superGroup.location}: error: reference to supergroup must resolve to group definition"
123
+ error = true
94
124
  end
125
+ else
126
+ error = true
127
+ end
128
+
129
+ if !error
130
+ @schema = schema
95
131
  end
132
+
96
133
  end
97
- @schema
134
+
135
+ @schema
98
136
  end
99
137
 
100
138
  # @param name [String] name of field
@@ -104,8 +142,7 @@ module SlowBlink
104
142
  @fields[name]
105
143
  end
106
144
 
107
- # Is this group a sub group of the super group?
108
- #
145
+ # @api private
109
146
  # @param superGroup [Group]
110
147
  # @return [true,false]
111
148
  def group_kind_of?(superGroup)
@@ -22,14 +22,17 @@ module SlowBlink
22
22
  # Blink Specification 7.3
23
23
  class IncrementalAnnotation
24
24
 
25
+ # @return [SchemaRef, DefinitionRef, DefinitionTypeRef, FieldRef, FieldTypeRef]
25
26
  attr_reader :componentReference
27
+
28
+ # @return [Array<Integer,Annotation>]
26
29
  attr_reader :annotes
30
+
31
+ # @macro location
27
32
  attr_reader :location
28
33
 
29
- # @private
30
- #
31
34
  # @param componentReference [SchemaRef, DefinitionRef, DefinitionTypeRef, FieldRef, FieldTypeRef] annotation target
32
- # @param annotations [Array<Integer,Annotation>]
35
+ # @param annotes [Array<Integer,Annotation>]
33
36
  # @param location [String]
34
37
  def initialize(componentReference, annotes, location)
35
38
  @componentReference = componentReference
@@ -38,7 +41,7 @@ module SlowBlink
38
41
  @schema = nil
39
42
  end
40
43
 
41
- # @private
44
+ # @api private
42
45
  #
43
46
  # Apply annotes to targets
44
47
  #
@@ -22,7 +22,7 @@ module SlowBlink
22
22
  class INTEGER < Type
23
23
  end
24
24
 
25
- # Blink Specification 3.1
25
+ # Blink Specification 3.1
26
26
  class I8 < INTEGER
27
27
  RANGE = Range.new(-128, 127)
28
28
  end
@@ -17,49 +17,32 @@
17
17
  # IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
18
  # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
19
 
20
- require "test/unit"
21
- require 'slow_blink'
20
+ module SlowBlink
22
21
 
23
- class TestModel < Test::Unit::TestCase
22
+ class Log
24
23
 
25
- include SlowBlink
26
-
27
- def test_think_blink
28
- rawSchema = <<-eos
29
- OrderExecuted/0x4c ->
30
- string Symbol,
31
- u64 OrderId,
32
- u32 Price,
33
- u32 Qty,
34
- u8 MatchId
35
- eos
36
- schema = Schema.new(SchemaBuffer.new(rawSchema))
37
- model = Message::Model.new(schema)
38
- end
39
-
40
- def test_from_compact
41
- rawSchema = <<-eos
42
- OrderExecuted/0x4c ->
43
- string Symbol,
44
- u64 OrderId,
45
- u32 Price,
46
- u32 Qty,
47
- u8 MatchId
48
- eos
49
- schema = Schema.new(SchemaBuffer.new(rawSchema))
24
+ @file = STDERR
25
+
26
+ def self.file=(file)
27
+ @file = file
28
+ end
29
+
30
+ def self.file
31
+ @file
32
+ end
33
+
34
+ def self.error(msg)
35
+ if @file
36
+ @file.puts(msg)
37
+ end
38
+ end
39
+
40
+ def self.info(msg)
41
+ if @file
42
+ @file.puts(msg)
43
+ end
44
+ end
50
45
 
51
- input = "\x0b\x4c\x05hello\x00\x01\x02\x03"
52
- model = Message::Model.new(schema)
53
-
54
- message = model.decode_compact(input)
55
-
56
- assert_equal("hello", message["Symbol"])
57
- assert_equal(0, message["OrderId"])
58
- assert_equal(1, message["Price"])
59
- assert_equal(2, message["Qty"])
60
- assert_equal(3, message["MatchId"])
61
46
  end
62
47
 
63
-
64
-
65
48
  end
@@ -19,68 +19,62 @@
19
19
 
20
20
  module SlowBlink::Message
21
21
 
22
- module BINARY
22
+ class BINARY
23
23
 
24
- module CLASS
25
-
26
- def opt?
27
- @opt
28
- end
24
+ def self.opt?
25
+ @opt
26
+ end
29
27
 
30
- def from_compact!(input)
31
- value = input.getBinary!
32
- if value
33
- if !@size or value.size <= @size
34
- self.new(value)
35
- else
36
- raise Error.new "W8: Binary value exceeds maximum size"
37
- end
38
- elsif @opt
39
- self.new(nil)
28
+ def self.from_compact!(input)
29
+ value = input.getBinary!
30
+ if value
31
+ if !@size or value.size <= @size
32
+ self.new(value)
40
33
  else
41
- raise Error.new "W5: Value cannot be null"
34
+ raise Error.new "W8: Binary value exceeds maximum size"
42
35
  end
36
+ elsif @opt
37
+ self.new(nil)
38
+ else
39
+ raise Error.new "W5: Value cannot be null"
43
40
  end
44
-
45
- def size
46
- @type.size
47
- end
48
-
49
41
  end
50
42
 
51
- module INSTANCE
43
+ def self.size
44
+ @type.size
45
+ end
52
46
 
53
- def set(value)
54
- if value
55
- if value.kind_of? String
56
- if !self.class.size or value.size <= self.class.size
57
- @value = value
58
- else
59
- raise Error.new "string cannot be larger than #{self.class.size} bytes"
60
- end
47
+ def set(value)
48
+ if value
49
+ if value.kind_of? String
50
+ if !self.class.size or value.size <= self.class.size
51
+ @value = value
61
52
  else
62
- raise Error.new "expecting a string type"
53
+ raise Error.new "string cannot be larger than #{self.class.size} bytes"
63
54
  end
64
- elsif self.class.opt?
65
- @value = nil
66
55
  else
67
- raise Error.new "string cannot be null"
56
+ raise Error.new "expecting a string type"
68
57
  end
58
+ elsif self.class.opt?
59
+ @value = nil
60
+ else
61
+ raise Error.new "string cannot be null"
69
62
  end
63
+ end
70
64
 
71
- def get
72
- @value
73
- end
74
-
75
- def initialize(value)
76
- set(value)
77
- end
65
+ def get
66
+ @value
67
+ end
78
68
 
79
- def to_compact(out)
80
- out.putBinary(@value)
81
- end
69
+ def initialize(value)
70
+ set(value)
71
+ end
82
72
 
73
+ def to_compact(out)
74
+ out.putBinary(@value)
83
75
  end
76
+
77
+
84
78
 
85
79
  end
86
80
 
@@ -19,50 +19,42 @@
19
19
 
20
20
  module SlowBlink::Message
21
21
 
22
- module BOOLEAN
23
-
24
- module CLASS
25
-
26
- def from_compact!(input)
27
- self.new(input.getBool!)
28
- end
22
+ class BOOLEAN
29
23
 
24
+ def self.from_compact!(input)
25
+ self.new(input.getBool!)
30
26
  end
31
27
 
32
- module INSTANCE
33
-
34
- def set(value)
35
- if value
36
- if value.kind_of? TrueClass or value.kind_of? FalseClass
37
- @value = value
38
- else
39
- raise "expecting true/false"
40
- end
41
- elsif self.class.opt?
42
- @value = nil
28
+ def set(value)
29
+ if value
30
+ if value.kind_of? TrueClass or value.kind_of? FalseClass
31
+ @value = value
43
32
  else
44
- raise Error.new "value unacceptable"
33
+ raise "expecting true/false"
45
34
  end
35
+ elsif self.class.opt?
36
+ @value = nil
37
+ else
38
+ raise Error.new "value unacceptable"
46
39
  end
40
+ end
47
41
 
48
- def get
49
- @value
50
- end
51
-
52
- def initialize(value)
53
- if value
54
- set(value)
55
- else
56
- @value = nil
57
- end
58
- end
42
+ def get
43
+ @value
44
+ end
59
45
 
60
- def to_compact(out)
61
- out.putBool(@value)
46
+ def initialize(value)
47
+ if value
48
+ set(value)
49
+ else
50
+ @value = nil
62
51
  end
63
-
64
52
  end
65
53
 
54
+ def to_compact(out)
55
+ out.putBool(@value)
56
+ end
57
+
66
58
  end
67
59
 
68
60
  end
@@ -19,14 +19,9 @@
19
19
 
20
20
  module SlowBlink::Message
21
21
 
22
- module DATE
22
+ class DATE
23
23
 
24
- module CLASS
25
- end
26
-
27
- module INSTANCE
28
- end
29
-
24
+
30
25
  end
31
26
 
32
27
  end