cddl 0.4.1 → 0.4.2

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
  SHA1:
3
- metadata.gz: d81421c45b8589d98a0bee597ebf58684b6dc47d
4
- data.tar.gz: 2c43ce26e9ec1061a91ffc078eb797293e6e861c
3
+ metadata.gz: 0f6311c506c4a4e5cbf7e7ae7311301a9d4b6c8d
4
+ data.tar.gz: e6fdfe83c6aec225ce434ae492a709fd06d0c890
5
5
  SHA512:
6
- metadata.gz: a59f236c132f7d3c4c20b20275270a304873abe3a0a527cd923a84d683ab953d59a65fa006f7de0c81de45c0d175bb86dcbb7abc680aa5f83e7753464d0dc8d6
7
- data.tar.gz: 2724e39b65ff8d6b2de65845ae67a713276fd99743625f2745bc4d6a6c0433ae43f736d47e1741f5e4df936c5102f112e675e541cffa3991a98abb54e93c9b67
6
+ metadata.gz: c2926569f00e5e7e509b3e6d05271da2c0d79a79eb46e38e97701218fe339113d08a8057369ff3c4b5f02bdd3f5fbb80ebc34875c6767b619ea327f722bf7ce3
7
+ data.tar.gz: 3df458899c4ed7890ef68a40b3c64484599b2805084eb9c8eee15789c94c269452c6352ce34d77dd078e612957c29ded13b650520c179dc6fe886f853e2a60e6
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.4.1'
3
+ s.version = '0.4.2'
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')
@@ -30,7 +30,7 @@ annotator = "." id
30
30
  group = "(" S *grpent S ")"
31
31
  / *grpent
32
32
 
33
- grpent = [occur S] [memberkey S] type1 optcom
33
+ grpent = [occur S] [memberkey S] type optcom
34
34
  / [occur S] groupname [genericarg] optcom ; always preempted by previous...
35
35
 
36
36
  memberkey = type1 S "=>"
@@ -115,6 +115,14 @@ module CDDL
115
115
  result
116
116
  end
117
117
 
118
+ def lookup_recurse_grpent(name)
119
+ rule = @stage1[name]
120
+ [rule[0], *rule[1..-1].map {|x|
121
+ fail rule.inspect if x.size != 1
122
+ x[0]
123
+ }]
124
+ end
125
+
118
126
  # Memoize a bit here
119
127
 
120
128
  REGEXP_FOR_STRING = Hash.new {|h, k|
@@ -132,6 +140,18 @@ module CDDL
132
140
  generate1(where[rand(where.size-1)+1])
133
141
  when :map
134
142
  Hash[where[1..-1].flat_map {|m| generate1(m, true)}]
143
+ when :recurse_grpent
144
+ rule = lookup_recurse_grpent(where[1])
145
+ if @recursion < MAX_RECURSE
146
+ @recursion += 1
147
+ #p ["recurse_grpent", *rule]
148
+ #r = generate1(rule)
149
+ r = rule[1..-1].flat_map {|m| generate1(m, inmap)}
150
+ @recursion -= 1
151
+ r
152
+ else
153
+ fail "Deep recursion into #{name}: #{@stage1[name]}, not yet implemented"
154
+ end
135
155
  when :array, :grpent
136
156
  r = where[1..-1].flat_map {|m| generate1(m).map{|e| e[1]}}
137
157
  .flat_map {|e| Array === e && e[0] == :grpent ? e[1..-1] : [e]}
@@ -233,6 +253,7 @@ module CDDL
233
253
  rule = @stage1[name]
234
254
  if @recursion < MAX_RECURSE
235
255
  @recursion += 1
256
+ #p ["recurse", *rule]
236
257
  r = generate1(rule)
237
258
  @recursion -= 1
238
259
  r
@@ -240,7 +261,7 @@ module CDDL
240
261
  fail "Deep recursion into #{name}: #{@stage1[name]}, not yet implemented"
241
262
  end
242
263
  else
243
- fail "Don't know how to generate from #{where[0]}"
264
+ fail "Don't know how to generate from #{where[0]} in #{where.inspect}"
244
265
  end
245
266
  end
246
267
 
@@ -289,15 +310,22 @@ module CDDL
289
310
  i = 0
290
311
  where[1..-1].each { |r|
291
312
  t, s, e, _k, v = r # XXX
292
- fail unless t == :member
293
- occ = 0
294
- while ((occ < e) && i != d.size && (n = validate_linear(d, start+i, v)))
313
+ if t == :recurse_grpent
314
+ rule = lookup_recurse_grpent(s)
315
+ n = validate_linear(d, start+i, rule)
316
+ return false unless n
295
317
  i += n
296
- occ += 1
297
- end
298
- if occ < s
299
- @last_message = "occur not reached in array #{d} for #{where}"
300
- return false
318
+ else
319
+ fail r.inspect unless t == :member
320
+ occ = 0
321
+ while ((occ < e) && i != d.size && (n = validate_linear(d, start+i, v)))
322
+ i += n
323
+ occ += 1
324
+ end
325
+ if occ < s
326
+ @last_message = "occur not reached in array #{d} for #{where}"
327
+ return false
328
+ end
301
329
  end
302
330
  }
303
331
  i
@@ -483,13 +511,26 @@ module CDDL
483
511
  end
484
512
  end
485
513
 
514
+ RECURSE_TYPE = {grpent: :recurse_grpent, type1: :recurse}
515
+ RECURSE_TYPE.default_proc = proc do |a|
516
+ fail a.inspect
517
+ end
518
+
486
519
  def r_process(n, r, bindings = {})
487
520
  t = r[0]
488
521
  # puts "Processing rule #{n} = #{t}"
489
522
  @stage1[n] ||= begin
490
- @stage1[n] = [:type1, [:recurse, n]]
523
+ @stage1[n] = [t, [RECURSE_TYPE[t], n]]
491
524
  @bindings.push(bindings)
492
- r = [t, *r[1..-1].map {|e| send(t, e)}]
525
+ r = [t, *r[1..-1].map {|e|
526
+ case t
527
+ when :grpent
528
+ grpent(e)
529
+ when :type1
530
+ type1(e, r.size == 2) # a single type1 could be a group
531
+ else
532
+ fail t
533
+ end}]
493
534
  @bindings.pop
494
535
  r
495
536
  end
@@ -509,11 +550,16 @@ module CDDL
509
550
  end
510
551
 
511
552
  def grpent(n) # returns array of entries
553
+ nt = n.type || n.bareword.s.type # check for grpchoice later
554
+ unless nt
555
+ warn @abnf.ast?
556
+ fail ["ntype", n, n.children].inspect
557
+ end
512
558
  occ = occur(n.occur)
513
559
  if mk = n.memberkey # work around unclear bug in ast generation below
514
- fail n.inspect unless n.type1
515
- if (t1 = mk.type1) || ((t1 = mk.s) && (t1 = t1.type) && (t1 = t1.type1)) # workaround
516
- [[:member, *occ, type1(t1), type1(n.type1)]]
560
+ if (t1 = mk.type1 || t1 = mk.value ||
561
+ ((t1 = mk.s) && (t1 = t1.type) && (t1 = t1.type1))) # workaround
562
+ [[:member, *occ, type1(t1), type(nt)]]
517
563
  else
518
564
  bw = mk.bareword
519
565
  unless bw
@@ -521,31 +567,36 @@ module CDDL
521
567
  fail [n, n.children, mk, mk.children].inspect
522
568
  end
523
569
  name = bw.to_s
524
- [[:member, *occ, [:string, name], type1(n.type1)]]
570
+ [[:member, *occ, [:string, name], type(nt)]]
525
571
  end
526
572
  else
527
- t = if n.bareword # work around unclear bug, part 2
528
- t1 = n.bareword.type1 || n.bareword.s.type.type1 # workaround
573
+ t = if nbw = nt.bareword
574
+ t1 = nbw.type1 # || n.bareword.s.type.type1 # workaround
529
575
  type1(t1, true)
530
576
  else
531
- type1(n.type1, true) # type1 can be a group here!
577
+ type(nt, true) # type can actually be a group here!
532
578
  end
579
+ # pp ["t is", t]
533
580
  if t[0] == :grpent && (@insides.last != :array || occ == [1, 1])
534
581
  # go through the members here and multiply the occs
535
582
  t1 = t[1..-1].flatten(1)
536
- t1.flat_map {|t2|
537
- if t2[0] == :member
538
- [t2]
539
- else
540
- fail unless t2[0] == :grpent # XXX Where is the nested multiplication here?
541
- t2[1..-1]
542
- end
543
- }.map {|mem|
544
- mem[1] *= occ[0]
545
- mem[2] *= occ[1] # Does all the infinity magic
546
- # p mem
547
- mem
548
- }
583
+ if t1[0] == :recurse_grpent
584
+ [t1]
585
+ else
586
+ t1.flat_map {|t2|
587
+ if t2[0] == :member
588
+ [t2]
589
+ else
590
+ fail t1.inspect unless t2[0] == :grpent # XXX Where is the nested multiplication here?
591
+ t2[1..-1]
592
+ end
593
+ }.map {|mem|
594
+ mem[1] *= occ[0]
595
+ mem[2] *= occ[1] # Does all the infinity magic
596
+ # p mem
597
+ mem
598
+ }
599
+ end
549
600
  else
550
601
  if t[0] == :grpent
551
602
  t = [t[0], *t[1..-1].flatten(1)]
@@ -688,8 +739,9 @@ module CDDL
688
739
  end
689
740
  end
690
741
 
691
- def type(n)
692
- s = n.children(:type1).map {|ch| type1(ch)}
742
+ def type(n, canbegroup = false)
743
+ # pp ["nch", n.children]
744
+ s = n.children(:type1).map {|ch| type1(ch, canbegroup)}
693
745
  if s.size == 1
694
746
  s.first
695
747
  else
@@ -0,0 +1,72 @@
1
+ ; draft-ietf-cdni-control-triggers-06.txt
2
+
3
+ CIT-object = CIT-command / Trigger-Status-Resource / Trigger-Collection
4
+
5
+ CIT-command ; use media type application/cdni.ci.TriggerCommand+json
6
+ = {
7
+ ? trigger: Triggerspec
8
+ ? cancel: [* URI]
9
+ cdn-path: [* Cdn-PID]
10
+ }
11
+
12
+ Trigger-Status-Resource ; application/cdni.ci.TriggerStatus+json.
13
+ = {
14
+ trigger: Triggerspec
15
+ ctime: Absolute-Time
16
+ mtime: Absolute-Time
17
+ ? etime: Absolute-Time
18
+ status: Trigger-Status
19
+ ? errors: [* Error-Description]
20
+ }
21
+
22
+ Trigger-Collection ; application/cdni.ci.TriggerCollection+json
23
+ = {
24
+ triggers: [* URI]
25
+ ? staleresourcetime: int ; time in seconds
26
+ ? coll-all: URI
27
+ ? coll-pending: URI
28
+ ? coll-active: URI
29
+ ? coll-complete: URI
30
+ ? coll-failed: URI
31
+ ? cdn-id: Cdn-PID
32
+ }
33
+
34
+ Triggerspec = { ; 5.2.1
35
+ type: Trigger-Type
36
+ ? metadata.urls: [* URI]
37
+ ? content.urls: [* URI]
38
+ ? content.ccid: [* Ccid]
39
+ ? metadata.patterns: [* Pattern-Match]
40
+ ? content.patterns: [* Pattern-Match]
41
+ }
42
+
43
+ Trigger-Type = "preposition" / "invalidate" / "purge" ; 5.2.2
44
+
45
+ Trigger-Status = "pending" / "active" / "complete" / "processed"
46
+ / "failed" / "cancelling" / "cancelled" ; 5.2.3
47
+
48
+ Pattern-Match = { ; 5.2.4
49
+ pattern: tstr
50
+ ? case-sensitive: bool
51
+ ? match-query-string: bool
52
+ }
53
+
54
+ Absolute-Time = number ; seconds since UNIX epoch, 5.2.5
55
+
56
+ Error-Description = { ; 5.2.6
57
+ error: Error-Code
58
+ ? metadata.urls: [* URI]
59
+ ? content.urls: [* URI]
60
+ ? metadata.patterns: [* Pattern-Match]
61
+ ? content.patterns: [* Pattern-Match]
62
+ ? description: tstr
63
+ }
64
+
65
+ Error-Code = "emeta" / "econtent" / "eperm" / "ereject"
66
+ / "ecdn" / "ecancelled" ; 5.2.7
67
+
68
+ Ccid = tstr ; see I-D.ietf-cdni-metadata
69
+
70
+ Cdn-PID = tstr .regexp "AS[0-9]+:[0-9]+"
71
+
72
+ URI = tstr
@@ -374,6 +374,82 @@ HERE
374
374
  end
375
375
 
376
376
 
377
+ def test_simple_alternative
378
+ parser = CDDL::Parser.new <<HERE
379
+ test = {
380
+ foo: 1
381
+ bar: 1 / 2
382
+ baz: 3
383
+ bee: 4
384
+ }
385
+ HERE
386
+ # pp parser.rules
387
+ expected1 = {'foo' => 1, 'bar' => 1, 'baz' => 3, 'bee' => 4}
388
+ expected2 = {'foo' => 1, 'bar' => 2, 'baz' => 3, 'bee' => 4}
389
+ 10.times {
390
+ g = parser.generate
391
+ # pp g
392
+ assert expected1 == g || expected2 == g
393
+ assert parser.validate(g)
394
+ }
395
+ end
396
+
397
+ def test_another_simple_alternative
398
+ parser = CDDL::Parser.new <<HERE
399
+ test = {
400
+ bar: int / true
401
+ }
402
+ HERE
403
+ # pp parser.rules
404
+ 10.times {
405
+ g = parser.generate
406
+ # pp ["tasa", g]
407
+ bar = g['bar']
408
+ assert bar == true || Integer(bar)
409
+ assert parser.validate(g)
410
+ }
411
+ end
412
+
413
+ def test_simple_alternative_in_array
414
+ parser = CDDL::Parser.new <<HERE
415
+ test = [
416
+ 1 / 2
417
+ 3 / 4
418
+ ]
419
+ HERE
420
+ # pp parser.rules
421
+ 10.times {
422
+ g = parser.generate
423
+ #pp ["saia", g]
424
+ assert_equal g.size, 2
425
+ assert [1, 2].include? g[0]
426
+ assert [3, 4].include? g[1]
427
+ assert parser.validate(g)
428
+ }
429
+ end
430
+
431
+ def test_simple_alternative_in_array2
432
+ parser = CDDL::Parser.new <<HERE
433
+ test = [
434
+ 1 / 2
435
+ bar
436
+ foob: 3 / 4
437
+ ]
438
+ bar = 5 / 6
439
+ HERE
440
+ # pp parser.rules
441
+ 10.times {
442
+ g = parser.generate
443
+ # pp ["saia", g]
444
+ assert_equal g.size, 3
445
+ assert [1, 2].include? g[0]
446
+ assert [5, 6].include? g[1]
447
+ assert [3, 4].include? g[2]
448
+ assert parser.validate(g)
449
+ }
450
+ end
451
+
452
+
377
453
  def test_validate_number_key
378
454
  parser = CDDL::Parser.new <<HERE
379
455
  test = [test1, test2, test3]
@@ -825,9 +901,83 @@ a = [a] / 1
825
901
  HERE
826
902
  10.times {
827
903
  g = parser.generate
828
- pp ["recurse-test", g]
904
+ pp ["recurse-test1", g]
905
+ assert parser.validate(g)
906
+ }
907
+ end
908
+
909
+ def test_endless_group_recursion
910
+ parser = CDDL::Parser.new <<HERE
911
+ b = {a}
912
+ a = (
913
+ foo: int
914
+ a
915
+ )
916
+ HERE
917
+ assert_raise { parser.validate(1) }
918
+ assert_raise { parser.generate }
919
+ end
920
+
921
+ def test_non_group_recursion
922
+ parser = CDDL::Parser.new <<HERE
923
+ a = {
924
+ foo: int
925
+ bar: ([a] / 1)
926
+ }
927
+ HERE
928
+ 10.times {
929
+ g = parser.generate
930
+ # pp ["non-recurse-test", g]
931
+ assert parser.validate(g)
932
+ }
933
+ end
934
+
935
+ def test_group_recursion
936
+ parser = CDDL::Parser.new <<HERE
937
+ b = {a}
938
+ a = (
939
+ foo: int
940
+ bar: ([a] / 1)
941
+ )
942
+ HERE
943
+ p parser.rules
944
+ 10.times {
945
+ g = parser.generate
946
+ # pp ["recurse-group-test", g]
829
947
  assert parser.validate(g)
830
948
  }
831
949
  end
832
950
 
951
+ def test_group_recursion_fail1
952
+ parser = CDDL::Parser.new <<HERE
953
+ b = {a}
954
+ a = (
955
+ foo: int
956
+ bar: ([a: a] / 1)
957
+ )
958
+ HERE
959
+ assert_raise { p parser.rules }
960
+ end
961
+
962
+ def test_empty_group
963
+ parser = CDDL::Parser.new <<HERE
964
+ a = {b}
965
+ b = ()
966
+ HERE
967
+ assert_equal({}, parser.generate)
968
+ assert parser.validate({})
969
+ end
970
+
971
+
972
+ def test_empty_group_indirect
973
+ parser = CDDL::Parser.new <<HERE
974
+ a = {b}
975
+ b = (c)
976
+ c = ()
977
+ HERE
978
+ # XXX
979
+ # assert_equal({}, parser.generate)
980
+ # assert parser.validate({})
981
+ end
982
+
833
983
  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.4.1
4
+ version: 0.4.2
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-24 00:00:00.000000000 Z
11
+ date: 2015-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -101,6 +101,7 @@ files:
101
101
  - test-data/7071-concise.cddl
102
102
  - test-data/7071-verbose.cddl
103
103
  - test-data/basic_syntax_example.cddl
104
+ - test-data/cdni-ct.cddl
104
105
  - test-data/dcaf1.cddl
105
106
  - test-data/jcr-ex.cddl
106
107
  - test-data/minimal.cddl