bare-rb 0.1.3 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b1147744e8da154541d6591f1e78929ad90a57ba806541a03cc5e770b43af6b
4
- data.tar.gz: 121a6ba57b86dc43f9e1b65145cc35e5c2174934e97bfdc142ddcd848f74deae
3
+ metadata.gz: 0206b2d45e4ea60de2e60934cda498eac9fd03c627f01455e6eb0a2e59163af9
4
+ data.tar.gz: 2477608d876cae8e775575dbd8f1f39db985414249c55c2d94c1251a569bdab5
5
5
  SHA512:
6
- metadata.gz: 8490934a87328cf339307924d7268e71e0c4c58336021294c2e957d618ab871ecc1a7d05f07ae72025e214f0fab7b64df7d31d37c3b6cbea8687315a523cb7f0
7
- data.tar.gz: d2930be08e535b50638eeda6814cd7d2e1544eead403a4f4efd81817cc54eb352a0e52575460f612ba9a5127949d61c6724c7a724e0feac3f7a2c9d54906da36
6
+ metadata.gz: 9d7430875487bff66b60e21b1893ada24df12bad88661b3dc06b3f71ab0f88877e6a24a08381f8180398ada99a31b2fc319f8880f676758db9bd767ad3d7321e
7
+ data.tar.gz: d2765a0a51f394ee02070b4ab3ceb56ac6c38793d3ee8ce020256df69302af016fcb4c435436ef93b25057d842d281a0cb5d20c8cea14c0621963da661fccc47
data/lib/bare-rb.rb CHANGED
@@ -2,64 +2,65 @@ require 'set'
2
2
  require_relative "types"
3
3
  require_relative "lexer"
4
4
  require_relative "parser"
5
+ require_relative 'dfs'
6
+ require_relative 'generative_testing/gen'
7
+ require_relative 'generative_testing/monkey_patch'
5
8
 
6
9
  class Bare
7
- def self.encode(msg, schema, type=nil)
8
- if schema.is_a?(Bare::Schema)
9
- raise NoTypeProvided("To encode with a schema as opposed to a raw type you must specify which type in the same you want to encode as a symbol.\nBare.encode(msg, schema, :Type)") if type.nil?
10
- return schema[type].encode(msg)
10
+ def self.encode(msg, schema, type = nil)
11
+ buffer = "".b
12
+ if schema.is_a?(BareTypes::Schema)
13
+ raise NoTypeProvided.new("To encode with a schema as opposed to a raw type you must specify which type in the schema you want to encode as a symbol.\nBare.encode(msg, schema, :Type)") if type.nil?
14
+ unless schema.types.include?(type)
15
+ raise("#{type} is not a type found in this schema. Choose from #{schema.types.keys}")
16
+ end
17
+ schema[type].encode(msg, buffer)
11
18
  else
12
- schema.encode(msg)
19
+ schema.encode(msg, buffer)
13
20
  end
21
+ buffer
14
22
  end
15
23
 
16
- def self.decode(msg, schema, type=nil)
17
- if schema.is_a?(Bare::Schema)
18
- raise NoTypeProvided("To decode with a schema as opposed to a raw type you must specify which type in the same you want to encode as a symbol.\nBare.encode(msg, schema, :Type)") if type.nil?
19
- return schema[type].decode(msg)[:value]
24
+ def self.decode(msg, schema, type = nil)
25
+ if schema.is_a?(BareTypes::Schema)
26
+ raise NoTypeProvided.new("To decode with a schema as opposed to a raw type you must specify which type in the same you want to encode as a symbol.\nBare.encode(msg, schema, :Type)") if type.nil?
27
+ value, _ = schema[type].decode(msg)
28
+ value
20
29
  else
21
- schema.decode(msg)[:value]
30
+ value, _ = schema.decode(msg)
31
+ value
32
+ end
33
+ end
34
+
35
+ # Returns a schema and a binary input
36
+ # optionally write these to files
37
+ def self.generative_test(schema_path=nil, binary_path=nil)
38
+ schema = BareTypes::Schema.make
39
+ input = schema.create_input
40
+ key = schema.types.keys[0]
41
+ binary = Bare.encode(input[key], schema, key)
42
+ unless binary_path.nil?
43
+ file = File.open(binary_path, 'wb+')
44
+ file.write(binary)
45
+ file.close
46
+ end
47
+ unless schema_path.nil?
48
+ file = File.open(schema_path, 'w+')
49
+ file.write(schema.to_s)
50
+ file.close
22
51
  end
52
+ return schema, binary, key
23
53
  end
24
54
 
25
55
  def self.parse_schema(path)
26
- # Hash of class names to BARE ASTs
56
+ # Hash of class names to BARE types
27
57
  # Eg. types['Customer'] == Bare.i32
28
- types = parser(lexer(path))
29
- Bare.Schema(types)
58
+ parsed = parser(lexer(path))
59
+ Bare.Schema(parsed)
30
60
  end
31
61
 
32
62
  def self.Schema(hash)
33
- Bare::Schema.new(hash)
34
- end
35
-
36
- class Schema
37
-
38
- def ==(otherSchema)
39
- return false unless otherSchema.is_a?(Bare::Schema)
40
- return @types == otherSchema.types
41
- end
42
-
43
- def types
44
- @types
45
- end
46
-
47
- def [](key)
48
- return @types[key]
49
- end
50
-
51
- def initialize(types)
52
- @types = types
53
- @types.keys.each do |key|
54
- if @types[key].is_a?(Symbol)
55
- @types[key] = @types[@types[key]]
56
- else
57
- # Users may user symbols to reference not yet defined types
58
- # here we recursively call our bare classes to finalize their types
59
- @types[key].finalize_references(@types)
60
- end
61
- end
62
- end
63
+ BareTypes::Schema.new(hash)
63
64
  end
64
65
 
65
66
  # These classes are wrapped in methods for ergonomics.
@@ -160,7 +161,4 @@ class Bare
160
161
  def self.Enum(*opts)
161
162
  return BareTypes::Enum.new(*opts)
162
163
  end
163
-
164
-
165
164
  end
166
-
data/lib/exceptions.rb CHANGED
@@ -5,6 +5,30 @@ class BareException < StandardError
5
5
  end
6
6
  end
7
7
 
8
+ class InvalidBool < BareException
9
+ def initialize(msg = nil)
10
+ super
11
+ end
12
+ end
13
+
14
+ class CircularSchema < BareException
15
+ def initialize(msg = nil)
16
+ super
17
+ end
18
+ end
19
+
20
+ class ReferenceException < BareException
21
+ def initialize(msg=nil)
22
+ super
23
+ end
24
+ end
25
+
26
+ class FixedDataSizeWrong < BareException
27
+ def initialize(msg=nil)
28
+ super
29
+ end
30
+ end
31
+
8
32
  class NoTypeProvided < BareException
9
33
  def initialize(msg = nil)
10
34
  super
@@ -0,0 +1,26 @@
1
+ require_relative '../bare-rb'
2
+ require_relative './monkey_patch'
3
+ require_relative './grammar_util'
4
+
5
+ def get_type(depth, names = [], can_be_symbol = true)
6
+ if names.size == 0
7
+ can_be_symbol = false
8
+ end
9
+ terminators = [BareTypes::Data, BareTypes::DataFixedLen,
10
+ BareTypes::U8, BareTypes::U16, BareTypes::U32, BareTypes::U64,
11
+ BareTypes::I8, BareTypes::I16, BareTypes::I32, BareTypes::I64,
12
+ BareTypes::F32, BareTypes::F64]
13
+ aggregates = [BareTypes::Array, BareTypes::ArrayFixedLen,
14
+ BareTypes::Struct]
15
+
16
+ all = terminators + aggregates
17
+
18
+ # 1/5 changes of a reference
19
+ if rand(5) == 0 && names.size != 1 && can_be_symbol
20
+ names[rand(names.size)]
21
+ elsif depth >= 10 # if depth >= 10 only use terminating types
22
+ all[rand(terminators.size)].make(depth + 1, names)
23
+ else
24
+ all[rand(all.size)].make(depth + 1, names)
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ def create_user_type_name
2
+ upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
3
+ lower = upper.downcase
4
+ digit = "0123456789"
5
+
6
+ name = upper[rand(upper.size)]
7
+ loop do
8
+ if rand(50) < 5
9
+ break
10
+ end
11
+ num = rand(3)
12
+ if num == 0
13
+ name << upper[rand(upper.size)]
14
+ elsif num == 1
15
+ name << lower[rand(lower.size)]
16
+ else
17
+ name << digit[rand(digit.size)]
18
+ end
19
+ end
20
+ name.to_sym
21
+ end
22
+
@@ -0,0 +1,262 @@
1
+ require_relative '../bare-rb'
2
+ require_relative './grammar_util'
3
+
4
+ # 10MB max data size
5
+ DATA_MAX_SIZE = 30000
6
+ ARRAY_MAX_SIZE = 40
7
+ STRUCT_FIELDS_MAX = 5
8
+
9
+ # Monkey patch every bare class to include make and create_input
10
+ # make - a factory to create a random variant of the bare class
11
+ # create_input - creates an input that could be used with Bare.Encode for this type
12
+
13
+ class BareTypes::Reference
14
+ def create_input
15
+ self.ref.create_input
16
+ end
17
+
18
+ def self.make(depth, names)
19
+ self.ref.make(depth, names)
20
+ end
21
+ end
22
+
23
+ # region Integers
24
+ class BareTypes::U8
25
+ def self.make(depth, names)
26
+ BareTypes::U8.new
27
+ end
28
+
29
+ def create_input
30
+ rand(256)
31
+ end
32
+ end
33
+
34
+ class BareTypes::U16
35
+ def self.make(depth, names)
36
+ BareTypes::U16.new
37
+ end
38
+
39
+ def create_input
40
+ rand(2 ** 16)
41
+ end
42
+ end
43
+
44
+ class BareTypes::U32
45
+ def self.make(depth, names)
46
+ BareTypes::U32.new
47
+ end
48
+
49
+ def create_input
50
+ rand(2 ** 32)
51
+ end
52
+ end
53
+
54
+ class BareTypes::U64
55
+ def self.make(depth, names)
56
+ BareTypes::U64.new
57
+ end
58
+
59
+ def create_input
60
+ rand(2 ** 64)
61
+ end
62
+ end
63
+
64
+ class BareTypes::I8
65
+ def self.make(depth, names)
66
+ BareTypes::I8.new
67
+ end
68
+
69
+ def create_input
70
+ rand(2 ** 8) - (2 ** 7)
71
+ end
72
+ end
73
+
74
+ class BareTypes::I16
75
+ def self.make(depth, names)
76
+ BareTypes::I16.new
77
+ end
78
+
79
+ def create_input
80
+ rand(2 ** 16) - (2 ** 15)
81
+ end
82
+ end
83
+
84
+ class BareTypes::I32
85
+ def self.make(depth, names)
86
+ BareTypes::I32.new
87
+ end
88
+
89
+ def create_input
90
+ rand(2 ** 32) - (2 ** 31)
91
+ end
92
+ end
93
+
94
+ class BareTypes::I64
95
+ def self.make(depth, names)
96
+ BareTypes::I64.new
97
+ end
98
+
99
+ def create_input
100
+ rand(2 ** 64) - (2 ** 63)
101
+ end
102
+ end
103
+
104
+ # endregion
105
+
106
+ #region Floats
107
+ class BareTypes::F32
108
+ def self.make(depth, names)
109
+ self.new
110
+ end
111
+
112
+ def create_input
113
+ float = nil
114
+ loop do
115
+ input = [rand(266), rand(266), rand(266), rand(266)]
116
+ float = input.pack("cccc").unpack('e')
117
+ if float[0] == float[0] && !float[0].nan?
118
+ break
119
+ end
120
+ end
121
+ float[0]
122
+ end
123
+ end
124
+
125
+ class BareTypes::F64
126
+ def self.make(depth, names)
127
+ self.new
128
+ end
129
+
130
+ def create_input
131
+ float = nil
132
+ loop do
133
+ input = [rand(266), rand(266), rand(266), rand(266), rand(266), rand(266), rand(266), rand(266)]
134
+ float = input.pack("cccccccc").unpack('E')
135
+ if float[0] == float[0] && !float[0].nan?
136
+ break
137
+ end
138
+ end
139
+ float[0]
140
+ end
141
+ end
142
+
143
+ #endregion
144
+
145
+ #region Data
146
+ class BareTypes::DataFixedLen
147
+ def self.make(depth, names)
148
+ length = rand(max = DATA_MAX_SIZE) + 1
149
+ self.new(length)
150
+ end
151
+
152
+ def create_input
153
+ # 100 random bytes
154
+ arr = []
155
+ 0.upto(length - 1).each do |i|
156
+ arr << i % 256
157
+ end
158
+ arr.pack('c*')
159
+ end
160
+ end
161
+
162
+ class BareTypes::Data
163
+ def self.make(depth, names)
164
+ self.new
165
+ end
166
+
167
+ def create_input
168
+ arr = []
169
+ 0.upto(rand(DATA_MAX_SIZE)).each do |i|
170
+ arr << i % 256
171
+ end
172
+ arr.pack('c*')
173
+ end
174
+ end
175
+
176
+ #endregion
177
+
178
+ #region Array
179
+ class BareTypes::Array
180
+ def self.make(depth, names)
181
+ BareTypes::Array.new(get_type(depth + 1, names))
182
+ end
183
+
184
+ def create_input
185
+ count = rand(ARRAY_MAX_SIZE) + 1
186
+ arr = []
187
+ 0.upto(count) do
188
+ arr << @type.create_input
189
+ end
190
+ arr
191
+ end
192
+ end
193
+
194
+ class BareTypes::ArrayFixedLen
195
+ def self.make(depth, names)
196
+ self.new(get_type(depth + 1, names,), rand(ARRAY_MAX_SIZE) + 1)
197
+ end
198
+
199
+ def create_input
200
+ arr = []
201
+ 0.upto(@size - 1) do
202
+ arr << @type.create_input
203
+ end
204
+ arr
205
+ end
206
+ end
207
+
208
+ #endregion
209
+
210
+ #region Agg Types
211
+
212
+ class BareTypes::Struct
213
+ def self.make(depth, names)
214
+ hash = {}
215
+ 0.upto(rand(STRUCT_FIELDS_MAX) + 1) do
216
+ hash[create_user_type_name.to_sym] = get_type(depth + 1, names)
217
+ end
218
+ self.new(hash)
219
+ end
220
+
221
+ def create_input
222
+ input = {}
223
+ @mapping.keys.each do |name|
224
+ input[name] = @mapping[name].create_input
225
+ end
226
+ input
227
+ end
228
+ end
229
+
230
+ # endregion
231
+
232
+ class BareTypes::Schema
233
+ def create_input
234
+ input = {}
235
+ @types.each do |key, type|
236
+ input[key] = type.create_input
237
+ end
238
+ input
239
+ end
240
+
241
+ def self.make
242
+ schema = nil
243
+ loop do
244
+ names = []
245
+ schema = {}
246
+ 0.upto(rand(10)+1) do
247
+ names << create_user_type_name.to_sym
248
+ end
249
+ names.each do |name|
250
+ without_this_name = names.select { |n| n != name }
251
+ schema[name] = get_type(0, without_this_name, false)
252
+ end
253
+ begin
254
+ schema = Bare.Schema(schema)
255
+ rescue CircularSchema
256
+ next
257
+ end
258
+ break
259
+ end
260
+ schema
261
+ end
262
+ end
data/lib/lexer.rb CHANGED
@@ -3,55 +3,56 @@ require_relative './exceptions'
3
3
  def lexer(path)
4
4
  tokens = []
5
5
  line_num = 0
6
- File.open(path).each do |line|
6
+ file = File.open(path)
7
+ file.each do |line|
7
8
  while line.size > 0
8
9
  if /^#/.match(line)
9
10
  break
10
11
  elsif /^\n/.match(line)
11
12
  break
12
13
  elsif /^ /.match(line)
13
- line = line[1..]
14
+ line = line[1..line.size]
14
15
  elsif /^</.match(line)
15
- line = line[1..]
16
+ line = line[1..line.size]
16
17
  tokens << :less_than
17
18
  elsif /^>/.match(line)
18
- line = line[1..]
19
+ line = line[1..line.size]
19
20
  tokens << :greater_than
20
21
  next
21
22
  elsif /^{/.match(line)
22
- line = line[1..]
23
+ line = line[1..line.size]
23
24
  tokens << :open_block
24
25
  elsif /^=/.match(line)
25
- line = line[1..]
26
+ line = line[1..line.size]
26
27
  tokens << :equal
27
28
  elsif /^}/.match(line)
28
- line = line[1..]
29
+ line = line[1..line.size]
29
30
  tokens << :close_block
30
31
  elsif /^\[/.match(line)
31
- line = line[1..]
32
+ line = line[1..line.size]
32
33
  tokens << :open_brace
33
34
  elsif /^\]/.match(line)
34
- line = line[1..]
35
+ line = line[1..line.size]
35
36
  tokens << :close_brace
36
37
  elsif /^\(/.match(line)
37
- line = line[1..]
38
+ line = line[1..line.size]
38
39
  tokens << :open_paren
39
40
  elsif /^\)/.match(line)
40
- line = line[1..]
41
+ line = line[1..line.size]
41
42
  tokens << :close_paren
42
43
  elsif /^\|/.match(line)
43
- line = line[1..]
44
+ line = line[1..line.size]
44
45
  tokens << :bar
45
46
  elsif match = /^([0-9]+)/.match(line)
46
47
  tokens << match[0].to_i
47
- line = line[(match[0].size)..]
48
+ line = line[(match[0].size)..line.size]
48
49
  next
49
- elsif match = /^[a-z,A-Z,_][_,a-z,A-Z,0-9]+/.match(line)
50
+ elsif match = /^[a-z,A-Z,_][_,a-z,A-Z,0-9]*/.match(line)
50
51
  tokens << match[0]
51
- line = line[(match[0].size)..]
52
+ line = line[(match[0].size)..line.size]
52
53
  elsif /:/.match(line)
53
54
  tokens << :colon
54
- line = line[1..]
55
+ line = line[1..line.size]
55
56
  else
56
57
  raise SchemaParsingException.new("Unable to lex line #{line_num} near #{line.inspect}")
57
58
  end
data/lib/parser.rb CHANGED
@@ -38,15 +38,15 @@ class Parser
38
38
  name = tokens[0]
39
39
  int_repr = tokens[2]
40
40
  enum_hash[int_repr] = name
41
- tokens = tokens[3..]
41
+ tokens = tokens[3..tokens.size]
42
42
  else
43
43
  enum_hash[count] = tokens[0]
44
44
  count += 1
45
- tokens = tokens[1..]
45
+ tokens = tokens[1..tokens.size]
46
46
  end
47
47
  end
48
48
  enum = Bare.Enum(enum_hash)
49
- return tokens[1..], enum
49
+ return tokens[1..tokens.size], enum
50
50
  end
51
51
 
52
52
  def parse_union(tokens)
@@ -55,13 +55,13 @@ class Parser
55
55
  # type A_UNION ( int | uint | data = 7 | f32 )
56
56
  while tokens[0] != :close_paren
57
57
  if tokens[0] == :bar
58
- tokens = tokens[1..]
58
+ tokens = tokens[1..tokens.size]
59
59
  else
60
60
  if tokens[1] == :equal
61
61
  raise SchemaParsingException.new("Equals sign in union must be followed by a number") unless tokens[2].is_a?(Numeric)
62
62
  count = tokens[2]
63
63
  tokens, type = self.parse(tokens)
64
- tokens = tokens[2..]
64
+ tokens = tokens[2..tokens.size]
65
65
  union_hash[count] = type
66
66
  count += 1
67
67
  else
@@ -78,63 +78,63 @@ class Parser
78
78
  struct_fields = {}
79
79
  while tokens.size >= 2 and tokens[1] == :colon
80
80
  name = tokens[0]
81
- tokens, type = self.parse(tokens[2..])
81
+ tokens, type = self.parse(tokens[2..tokens.size])
82
82
  struct_fields[name.to_sym] = type
83
83
  end
84
- return tokens[1..], struct_fields
84
+ return tokens[1..tokens.size], struct_fields
85
85
  end
86
86
 
87
87
  def parse(tokens)
88
88
  while tokens.size > 0
89
89
  if tokens[0] == "type"
90
90
  name = tokens[1]
91
- tokens, type = self.parse(tokens[2..])
91
+ tokens, type = self.parse(tokens[2..tokens.size])
92
92
  @definitions[name.to_sym] = type
93
93
  elsif tokens[0] == "map"
94
94
  raise SchemaParsingException.new("Map must be followed by a '[' eg. map[string]data") if tokens[1] != :open_brace
95
- tokens, map_from_type = parse(tokens[2..])
95
+ tokens, map_from_type = parse(tokens[2..tokens.size])
96
96
  raise SchemaParsingException.new("Map to type must be followed by a ']' eg. map[string]data") if tokens[0] != :close_brace
97
- tokens, map_to_type = parse(tokens[1..])
97
+ tokens, map_to_type = parse(tokens[1..tokens.size])
98
98
  return tokens, Bare.Map(map_from_type, map_to_type)
99
99
  elsif tokens[0] == "data" && tokens.size > 3 && tokens[1] == :less_than
100
100
  raise SchemaParsingException.new("data< must be followed by a number for a fixed sized bare data") unless tokens[2].is_a?(Numeric)
101
101
  raise SchemaParsingException.new("data<# must be followed by a >") unless tokens[3] == :greater_than
102
- return tokens[4..], Bare.DataFixedLen(tokens[2])
102
+ return tokens[4..tokens.size], Bare.DataFixedLen(tokens[2])
103
103
  elsif tokens[0] == "enum"
104
104
  name = tokens[1]
105
105
  raise SchemaParsingException.new("Enum must be followed by a '{'") if tokens[2] != :open_block
106
- tokens, enum = parse_enum(tokens[3..])
106
+ tokens, enum = parse_enum(tokens[3..tokens.size])
107
107
  @definitions[name.to_sym] = enum
108
108
  elsif tokens[0] == "optional"
109
109
  raise SchemaParsingException.new("Optional must be followed by a '< TYPE > you are missing the first <'") if tokens[1] != :less_than
110
- tokens, optional_type = self.parse(tokens[2..])
110
+ tokens, optional_type = self.parse(tokens[2..tokens.size])
111
111
  raise SchemaParsingException.new("Optional must be followed by a '< TYPE >' you are missing the last >") if tokens[0] != :greater_than
112
- return tokens[1..], Bare.Optional(optional_type)
112
+ return tokens[1..tokens.size], Bare.Optional(optional_type)
113
113
  elsif tokens[0] == :open_brace
114
114
  if tokens[1].is_a?(Numeric)
115
115
  size = tokens[1]
116
116
  raise SchemaParsingException.new("Fixed Length Array size must be followed by a ']'") if tokens[2] != :close_brace
117
- tokens, arr_type = parse(tokens[3..])
117
+ tokens, arr_type = parse(tokens[3..tokens.size])
118
118
  return tokens, Bare.ArrayFixedLen(arr_type, size)
119
119
  else
120
- tokens, arr_type = parse(tokens[2..])
120
+ tokens, arr_type = parse(tokens[2..tokens.size])
121
121
  return tokens, Bare.Array(arr_type)
122
122
  end
123
123
  elsif tokens[0] == :open_paren
124
- tokens, union_hash = parse_union(tokens[1..])
124
+ tokens, union_hash = parse_union(tokens[1..tokens.size])
125
125
  raise SchemaParsingException.new("Union must be followed by a ')'") if tokens[0] != :close_paren
126
- return tokens[1..], Bare.Union(union_hash)
126
+ return tokens[1..tokens.size], Bare.Union(union_hash)
127
127
  elsif tokens[0] == :open_block
128
- tokens, struct_fields = parse_struct(tokens[1..])
128
+ tokens, struct_fields = parse_struct(tokens[1..tokens.size])
129
129
  strct = Bare.Struct(struct_fields)
130
130
  return tokens, strct
131
131
  elsif @primitives.include?(tokens[0])
132
132
  type = @primitives[tokens[0]]
133
- return tokens[1..], type
133
+ return tokens[1..tokens.size], type
134
134
  elsif @definitions.keys.include?(tokens[0].to_sym) # User defined type
135
- return tokens[1..], @definitions[tokens[0].to_sym]
135
+ return tokens[1..tokens.size], tokens[0].to_sym
136
136
  elsif tokens[0].is_a?(String) && tokens[0][0].upcase == tokens[0][0] # Not yet defined user type
137
- return tokens[1..], tokens[0].to_sym
137
+ return tokens[1..tokens.size], tokens[0].to_sym
138
138
  else
139
139
  raise SchemaParsingException.new("Unable to parse token: #{tokens[0]}")
140
140
  end