cddl 0.1.4 → 0.1.5

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 (6) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cddl +9 -1
  3. data/cddl.gemspec +1 -1
  4. data/lib/cddl.rb +50 -26
  5. data/test/test-cddl.rb +76 -24
  6. metadata +3 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 14938c337d552f720d587e2b46be2c4738e48f8b
4
- data.tar.gz: 9a2b6a95471d6d29b6acd051d3c838d30f1724c0
3
+ metadata.gz: ae990c0c1e630a5f206d115bc5ae8cbc2e5612cd
4
+ data.tar.gz: 7ff78e8928e1cd3e7f60fa1086e6b055b23e39d7
5
5
  SHA512:
6
- metadata.gz: 557ce79dad209f8577c361effcb3aea96ee43be2b4dba7914fa34fdb9f7bca9d5e5adfe079dcdadce42062f07f1eb55c2e825ec1c30833f9d23d5ffb118ecaf1
7
- data.tar.gz: a1d8f53c4baf9d5c50c65a7daf3a91d40a1c5c43616978f3fedcb0c84493012906335712003c90b73d04b0f2800d9e89d081200036e5506f99b20db8a95b23d6
6
+ metadata.gz: 25cb1b61914141616819edfbcfa2a7de955295a1c1863f22ed6af85700f5cc1fa9897c6cbf51a9bcd65814f927f026e389fd80c916713e07a195a2b42dbb5136
7
+ data.tar.gz: 042f0f7497d609872bfce8b95da45d98a273a06092c67d2816704618497067910add06f4bf88abfa7d066cc90dff30f19ead71f43dc2ddcceb10e61b57866a23
data/bin/cddl CHANGED
@@ -15,8 +15,16 @@ def usage
15
15
  exit 1
16
16
  end
17
17
 
18
+ def read_arg(arg)
19
+ if arg == "-"
20
+ STDIN.read
21
+ else
22
+ File.read(arg)
23
+ end
24
+ end
25
+
18
26
  def parser
19
- @parser ||= CDDL::Parser.new(File.read(ARGV[0]))
27
+ @parser ||= CDDL::Parser.new(read_arg(ARGV[0]))
20
28
  end
21
29
 
22
30
  case ARGV[1]
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.1.4'
3
+ s.version = '0.1.5'
4
4
  s.summary = "CDDL generator and validator."
5
5
  s.description = %{A parser, generator, and validator for CDDL}
6
6
  s.add_dependency('cbor-diag')
@@ -10,6 +10,8 @@ module CDDL
10
10
  PRELUDE = File.read("#{DATA_DIR}/prelude.cddl")
11
11
  ABNF_SPEC = File.read("#{DATA_DIR}/cddl.abnf")
12
12
 
13
+ MANY = Float::INFINITY
14
+
13
15
  class Parser
14
16
  def initialize(source_text)
15
17
  @abnf = Peggy::ABNF.new
@@ -27,6 +29,8 @@ module CDDL
27
29
  end
28
30
  puts @abnf.ast? if $debug_ast
29
31
  @ast = @abnf.ast?
32
+ # our little argument stack for rule processing
33
+ @insides = []
30
34
  end
31
35
 
32
36
  def apr # for debugging
@@ -72,12 +76,11 @@ module CDDL
72
76
  generate(where[rand(where.size-1)+1])
73
77
  when :map
74
78
  Hash[where[1..-1].flat_map {|m| generate(m, true)}]
75
- when :array
79
+ when :array, :grpent
76
80
  where[1..-1].flat_map {|m| generate(m).map{|e| e[1]}}
77
81
  when :member
78
82
  s = where[1]
79
- e = where[2]
80
- e = 4 if e == -1
83
+ e = [where[2], [s, 4].max].min # truncate to 4 unless must be more
81
84
  s += rand(e + 1 - s) if e != s
82
85
  kr = where[3]
83
86
  vr = where[4]
@@ -164,6 +167,36 @@ module CDDL
164
167
  )
165
168
  end
166
169
 
170
+ def validate_forward(d, start, where)
171
+ i = 0
172
+ where[1..-1].each { |r|
173
+ t, s, e, _k, v = r # XXX
174
+ fail unless t == :member
175
+ occ = 0
176
+ while ((occ < e) && i != d.size && (n = validate_linear(d, start+i, v)))
177
+ i += n
178
+ occ += 1
179
+ end
180
+ if occ < s
181
+ @last_message = "occur not reached in array #{d} for #{where}"
182
+ return false
183
+ end
184
+ }
185
+ i
186
+ end
187
+
188
+ # returns number of matches or false for breakage
189
+ def validate_linear(d, start, where)
190
+ fail unless Array === d
191
+ case where[0]
192
+ when :grpent
193
+ # must be inside an array with nested occurrences
194
+ validate_forward(d, start, where)
195
+ else
196
+ validate1(d[start], where) ? 1 : false
197
+ end
198
+ end
199
+
167
200
  def validate1(d, where=rules)
168
201
  # puts "DATA: #{d.inspect}"
169
202
  # puts "RULE: #{where.inspect}"
@@ -205,21 +238,7 @@ module CDDL
205
238
  when :array
206
239
  if Array === d
207
240
  # validate1 against the record
208
- # XXX do that in some recursive descent fashion
209
- i = 0
210
- where[1..-1].each { |r|
211
- t, s, e, _k, v = r # XXX
212
- fail unless t == :member
213
- occ = 0
214
- while ((e == -1 || occ < e) && i != d.size && validate1(d[i], v))
215
- i += 1
216
- occ += 1
217
- end
218
- if occ < s
219
- @last_message = "occur not reached in array #{d} for #{where}"
220
- return false
221
- end
222
- }
241
+ i = validate_forward(d, 0, where)
223
242
  validate_result(i == d.size) { "cannot complete array #{d} for #{where}" }
224
243
  end
225
244
  when :string, :int, :float
@@ -310,25 +329,27 @@ module CDDL
310
329
  else
311
330
  type1(n.type1, true) # type1 can be a group here!
312
331
  end
313
- if t[0] == :grpent
332
+ if t[0] == :grpent && (@insides.last == :map || occ == [1, 1])
314
333
  # go through the members here and multiply the occs
315
- # XXX only do this for maps. Keep the structure up for the arrays!
316
334
  t1 = t[1..-1].flatten(1)
317
335
  t1.flat_map {|t2|
318
336
  if t2[0] == :member
319
337
  [t2]
320
338
  else
321
- fail unless t2[0] == :grpent
339
+ fail unless t2[0] == :grpent # XXX Where is the nested multiplication here?
322
340
  t2[1..-1]
323
341
  end
324
342
  }.map {|mem|
325
343
  # p mem
326
344
  mem[1] *= occ[0]
327
- mem[2] *= [occ[1], -1].max
345
+ mem[2] *= occ[1] # Does all the infinity magic
328
346
  # p mem
329
347
  mem
330
348
  }
331
349
  else
350
+ if t[0] == :grpent
351
+ t = [t[0], *t[1..-1].flatten(1)]
352
+ end
332
353
  [[:member, *occ, nil, t]]
333
354
  end
334
355
  end
@@ -407,15 +428,18 @@ module CDDL
407
428
  when /\A\(/
408
429
  type(n.type)
409
430
  when /\A[\[{]/
410
- s = n.children(:group).flat_map {|ch| group(ch)}
411
431
  type = BRACE[str[0]]
432
+ @insides << type
433
+ s = n.children(:group).flat_map {|ch| group(ch)}
434
+ @insides.pop
412
435
  if type == :map
413
436
  s.each do |member|
414
437
  fail unless member[0] == :member
415
438
  fail "map entry without member key given: #{member}" unless member[3]
416
439
  end
417
- # XXX do the occurrence multiplier here
440
+ # XXX could do the occurrence multiplier here
418
441
  end
442
+ # warn s.inspect
419
443
  [type, *s]
420
444
  else
421
445
  "unimplemented #{n}"
@@ -441,7 +465,7 @@ module CDDL
441
465
  when ""
442
466
  [1, 1]
443
467
  when "+"
444
- [1, -1]
468
+ [1, MANY]
445
469
  when "?"
446
470
  [0, 1]
447
471
  when /\A(\d*)\*(\d*)\z/
@@ -451,7 +475,7 @@ module CDDL
451
475
  s = s.to_i
452
476
  end
453
477
  if (e = $2) == ""
454
- e = -1
478
+ e = MANY
455
479
  else
456
480
  e = e.to_i
457
481
  end
@@ -21,7 +21,7 @@ class TestABNF < Test::Unit::TestCase
21
21
  [:array,
22
22
  [:member,
23
23
  0,
24
- -1,
24
+ CDDL::MANY,
25
25
  nil,
26
26
  [:map,
27
27
  [:member, 1, 1, [:string, "rater"], [:prim, 3]],
@@ -33,7 +33,7 @@ class TestABNF < Test::Unit::TestCase
33
33
  [:member, 0, 1, [:string, "sample-size"], [:prim, 0]],
34
34
  [:member, 0, 1, [:string, "generated"], [:prim, 0]],
35
35
  [:member, 0, 1, [:string, "expires"], [:prim, 0]],
36
- [:member, 0, -1, [:type1, [:prim]], [:prim]]]]]]]]
36
+ [:member, 0, CDDL::MANY, [:type1, [:prim]], [:prim]]]]]]]]
37
37
 
38
38
  def test_aa_rfc7071_concise
39
39
  parser1 = CDDL::Parser.new(File.read("#{TEST_DATA_DIR}/7071-concise.cddl"))
@@ -56,7 +56,6 @@ HERE
56
56
  assert_equal [0x4711, 0b1011001110001111000], parser.generate
57
57
  end
58
58
 
59
-
60
59
  def test_validate_person_occurs
61
60
  person = <<HERE
62
61
  person = (
@@ -67,19 +66,25 @@ HERE
67
66
  parser1 = CDDL::Parser.new "unlimitedpersons = [* person ]" + person
68
67
  parser2 = CDDL::Parser.new "oneortwoPerson = [1*2 person ]" + person
69
68
  parser3 = CDDL::Parser.new "min2Person = [2* person ]" + person
70
-
69
+
71
70
  assert parser1.validate([])
72
71
  refute parser2.validate([], false)
73
72
  refute parser3.validate([], false)
74
73
  assert parser1.validate(["Methuselah", 969])
75
74
  assert parser2.validate(["Methuselah", 969])
76
75
  refute parser3.validate(["Methuselah", 969], false)
77
- assert parser1.validate(["Methuselah", "Methuselah", 969, 969]) # XXX Sequence
78
- assert parser2.validate(["Methuselah", "Methuselah", 969, 969])
79
- assert parser3.validate(["Methuselah", "Methuselah", 969, 969])
80
- assert parser1.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969]) # XXX Sequence
76
+ assert parser1.validate(["Methuselah", 969, "Methuselah", 969])
77
+ assert parser2.validate(["Methuselah", 969, "Methuselah", 969])
78
+ assert parser3.validate(["Methuselah", 969, "Methuselah", 969])
79
+ assert parser1.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969])
80
+ refute parser2.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969], false)
81
+ assert parser3.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969])
82
+ refute parser1.validate(["Methuselah", "Methuselah", 969, 969], false)
83
+ refute parser2.validate(["Methuselah", "Methuselah", 969, 969], false)
84
+ refute parser3.validate(["Methuselah", "Methuselah", 969, 969], false)
85
+ refute parser1.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
81
86
  refute parser2.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
82
- assert parser3.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969])
87
+ refute parser3.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
83
88
  end
84
89
 
85
90
  def test_validate
@@ -215,9 +220,9 @@ HERE
215
220
  # pp parser.apr
216
221
  assert parser.validate([])
217
222
  assert parser.validate([1, 2])
218
- assert parser.validate([1, 1, 2, 2]) # XXX: This is probably a BUG
219
- refute parser.validate([1, 2, 1, 2], false) # XXX->assert: major surgery required
220
- assert parser.validate([1]) # XXX -> refute (rules left)
223
+ assert parser.validate([1, 2, 1, 2])
224
+ refute parser.validate([1, 1, 2, 2], false)
225
+ refute parser.validate([1], false)
221
226
  refute parser.validate([1, 2, 1], false)
222
227
  end
223
228
 
@@ -251,7 +256,7 @@ HERE
251
256
  # puts "APR:"
252
257
  # pp parser.apr
253
258
  assert parser.validate([])
254
- assert parser.validate([1])
259
+ refute parser.validate([1], false)
255
260
  assert parser.validate([1, 2])
256
261
  refute parser.validate([2, 1], false)
257
262
  refute parser.validate([1, 1, 2, 2], false)
@@ -273,8 +278,8 @@ HERE
273
278
  refute parser.validate([1], false)
274
279
  assert parser.validate([1, 2])
275
280
  refute parser.validate([2, 1], false)
276
- assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
277
- refute parser.validate([1, 2, 1, 2], false)
281
+ refute parser.validate([1, 1, 2, 2], false)
282
+ assert parser.validate([1, 2, 1, 2])
278
283
  refute parser.validate([1, 2, 1], false)
279
284
  end
280
285
 
@@ -289,15 +294,15 @@ HERE
289
294
  # puts "APR:"
290
295
  # pp parser.apr
291
296
  assert parser.validate([])
292
- assert parser.validate([1])
297
+ refute parser.validate([1], false)
293
298
  assert parser.validate([1, 2])
294
299
  refute parser.validate([2, 1], false)
295
- assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
296
- refute parser.validate([1, 2, 1, 2], false)
300
+ refute parser.validate([1, 1, 2, 2], false)
301
+ assert parser.validate([1, 2, 1, 2])
297
302
  refute parser.validate([1, 2, 1], false)
298
303
  end
299
304
 
300
-
305
+
301
306
  def test_validate_occur23 # XXX need indirection for now
302
307
  # $debug_ast = true
303
308
  parser = CDDL::Parser.new <<HERE
@@ -313,11 +318,35 @@ HERE
313
318
  refute parser.validate([1], false)
314
319
  refute parser.validate([1, 2], false)
315
320
  refute parser.validate([2, 1], false)
316
- assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
317
- assert parser.validate([1, 1, 1, 2, 2]) # XXX not sequence preserving
318
- assert parser.validate([1, 1, 2, 2, 2]) # XXX not sequence preserving
319
- assert parser.validate([1, 1, 1, 2, 2, 2]) # XXX not sequence preserving
320
- refute parser.validate([1, 2, 1, 2], false)
321
+ assert parser.validate([1, 2, 1, 2])
322
+ assert parser.validate([1, 2, 1, 2, 1, 2])
323
+ refute parser.validate([1, 2, 1, 2, 1, 2, 1, 2], false)
324
+ refute parser.validate([1, 1, 2, 2, 2], false)
325
+ refute parser.validate([1, 1, 1, 2, 2, 2], false)
326
+ refute parser.validate([1, 2, 1], false)
327
+ end
328
+
329
+
330
+ def test_validate_occur12plus1 # XXX need indirection for now
331
+ # $debug_ast = true
332
+ parser = CDDL::Parser.new <<HERE
333
+ test = [1*2 test1 1*1 test1]
334
+ test1 = (one: 1, two: 2)
335
+ HERE
336
+ # puts "RULES:"
337
+ # pp parser.rules
338
+ # puts "APR:"
339
+ # pp parser.apr
340
+ pp parser.generate
341
+ refute parser.validate([], false)
342
+ refute parser.validate([1], false)
343
+ refute parser.validate([1, 2], false)
344
+ refute parser.validate([2, 1], false)
345
+ refute parser.validate([1, 2, 1, 2], false) # !!! PEG semantics gets us here
346
+ assert parser.validate([1, 2, 1, 2, 1, 2])
347
+ refute parser.validate([1, 2, 1, 2, 1, 2, 1, 2], false)
348
+ refute parser.validate([1, 1, 2, 2, 2], false)
349
+ refute parser.validate([1, 1, 1, 2, 2, 2], false)
321
350
  refute parser.validate([1, 2, 1], false)
322
351
  end
323
352
 
@@ -363,5 +392,28 @@ HERE
363
392
  refute parser.validate(CBOR::Tagged.new(55799, CBOR::Tagged.new(999, [0, "barley", 1])), false)
364
393
  end
365
394
 
395
+ def test_nested_group_many1
396
+ parser = CDDL::Parser.new <<HERE
397
+ foo = {* bar}
398
+ bar = (* b: 1)
399
+ HERE
400
+ assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
401
+ end
402
+
403
+ def test_nested_group_many2
404
+ parser = CDDL::Parser.new <<HERE
405
+ foo = {* bar}
406
+ bar = (b: 1)
407
+ HERE
408
+ assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
409
+ end
410
+
411
+ def test_nested_group_many3
412
+ parser = CDDL::Parser.new <<HERE
413
+ foo = {* bar}
414
+ bar = (4*6 b: 1)
415
+ HERE
416
+ assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
417
+ end
366
418
 
367
419
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cddl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-02 00:00:00.000000000 Z
11
+ date: 2015-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -92,9 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  version: '0'
93
93
  requirements: []
94
94
  rubyforge_project:
95
- rubygems_version: 2.4.5
95
+ rubygems_version: 2.4.6
96
96
  signing_key:
97
97
  specification_version: 4
98
98
  summary: CDDL generator and validator.
99
99
  test_files: []
100
- has_rdoc: