cddl 0.8.8 → 0.9.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/bin/cddl +35 -15
  3. data/cddl.gemspec +4 -2
  4. data/data/cddl.abnf +1 -0
  5. data/lib/cbor-pp-play.rb +1 -0
  6. data/lib/cddl.rb +225 -31
  7. data/test/test-cddl.rb +51 -0
  8. data/test-data/7807.cddl +14 -0
  9. data/test-data/abignum.cddl +1 -0
  10. data/test-data/abnf1.cddl +3 -0
  11. data/test-data/abnf2.cddl +37 -0
  12. data/test-data/abnf3.cddl +32 -0
  13. data/test-data/bat.cddl +16 -0
  14. data/test-data/bpv7.cddl +136 -0
  15. data/test-data/bpv7a.cddl +181 -0
  16. data/test-data/bpv7b.cddl +167 -0
  17. data/test-data/cat-re.cddl +2 -0
  18. data/test-data/complex-occ.cddl +11 -0
  19. data/test-data/coral.cddl +10 -0
  20. data/test-data/coral1.cddl +5 -0
  21. data/test-data/coral2.cddl +7 -0
  22. data/test-data/coral3.cddl +7 -0
  23. data/test-data/det1.cddl +12 -0
  24. data/test-data/feat1.cddl +4 -0
  25. data/test-data/feature-controller.cddl +6 -0
  26. data/test-data/feature-detail.cddl +5 -0
  27. data/test-data/foo.cddl +1 -0
  28. data/test-data/homenet-de.cddl +12 -0
  29. data/test-data/homenet-fe.cddl +12 -0
  30. data/test-data/jim-cut-2.cddl +11 -0
  31. data/test-data/jim-cut.cddl +12 -0
  32. data/test-data/jsoniodef.cddl +719 -0
  33. data/test-data/lint1.cddl +9 -0
  34. data/test-data/mdl-ble.cddl +9 -0
  35. data/test-data/mdl-deve.cddl +54 -0
  36. data/test-data/mdl-dp.cddl +11 -0
  37. data/test-data/mdl-mso.cddl +20 -0
  38. data/test-data/mdl-request.cddl +26 -0
  39. data/test-data/mdl-response.cddl +66 -0
  40. data/test-data/mdl.cddl +11 -0
  41. data/test-data/mon-val.cddl +1 -0
  42. data/test-data/multipart-ct.cddl +2 -0
  43. data/test-data/named-group.cddl +7 -0
  44. data/test-data/non-empty.cddl +5 -0
  45. data/test-data/oid.cddl +8 -0
  46. data/test-data/oidbat.cddl +8 -0
  47. data/test-data/plus.cddl +3 -0
  48. data/test-data/sasl.cddl +24 -0
  49. data/test-data/sequence.cddl +1 -0
  50. data/test-data/sipos.cddl +8 -0
  51. data/test-data/star-edited.cddl +98 -0
  52. data/test-data/star.cddl +95 -0
  53. data/test-data/test-gen.cddl +3 -0
  54. data/test-data/time.cddl +11 -0
  55. data/test-data/yangid.cddl +1 -0
  56. data/test-data/yaron1.cddl +95 -0
  57. metadata +70 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c877883cb125426e061f527ba4375c0f021d70dfef060336fe0bb0f5e2ca3d4
4
- data.tar.gz: 7a3dc4065f3616bf57c229b410782b35140018ecada4418c0ef45056c62aef0b
3
+ metadata.gz: 1c5fe473658f795abcc5e1599dd18ea3e62525c2f595a8e6c36d4fc9fa7654e8
4
+ data.tar.gz: 1d3789efc876946703170afb3aca08e458ad19c18ef8c8a5477852ab02fcc78d
5
5
  SHA512:
6
- metadata.gz: b3987fbe82e80dddba2f650b1a12941ed6092708297302cf1a78dfe45b20b79d08e85901cb8739b5fc79eab8cde70ca8efb88698f4340da72c722a7a461565c6
7
- data.tar.gz: 68c35688bac9b30411ee419e171860c463df28c3452bce1741399274e51295b609e0acc8df54e9876037f9d96ba02e369fd9465c2fe7c38bb9682d5ec19018cd
6
+ metadata.gz: f108776ab78dd95aa075e3450bcf121c8374508cbe9df27a539090af5faa4f9e70d378b39318bdd0b47ef97b29228ec4796e32b0229084942ee7106cdcb567c4
7
+ data.tar.gz: b642fe30b4c4aef6ee12fc42a7f1caab6b94ef3797789c5d7b8f190b447fdc4133669ddfa9ba923b91ce31760cfb41da6859b1e1c2d0d5b976f8133c2e742dc9
data/bin/cddl CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env RUBY_THREAD_VM_STACK_SIZE=5000000 ruby
2
2
  # -*- coding: utf-8 -*-
3
3
  # require_relative '../lib/cddl'
4
4
  require 'cddl'
@@ -14,22 +14,24 @@ def usage
14
14
  warn "Usage:"
15
15
  warn "#$0 spec.cddl generate [n]"
16
16
  warn "#$0 spec.cddl json-generate [n]"
17
- warn "#$0 spec.cddl validate instance.cbor"
18
- warn "#$0 spec.cddl validate instance.json"
17
+ warn "#$0 spec.cddl validate instance.cbor..."
18
+ warn "#$0 spec.cddl validate instance.json..."
19
19
  exit EX_USAGE
20
20
  end
21
21
 
22
- def read_arg(arg)
22
+ def read_arg(arg, remember_fn = true)
23
23
  if arg == "-"
24
+ $fn = "(stdin)" if remember_fn
24
25
  STDIN.read
25
26
  else
26
27
  usage unless arg
28
+ $fn = arg if remember_fn
27
29
  File.read(arg, mode: "rb")
28
30
  end
29
31
  end
30
32
 
31
33
  def parser
32
- @parser ||= CDDL::Parser.new(read_arg(ARGV[0]))
34
+ @parser ||= CDDL::Parser.new(read_arg(ARGV[0], false))
33
35
  end
34
36
 
35
37
  def my_pp(v)
@@ -48,13 +50,19 @@ def my_diag(v)
48
50
  end
49
51
  end
50
52
 
53
+ retcode = 0
54
+
51
55
  begin
52
56
  case ARGV[1]
53
- when /\A.p/
57
+ when /\A..*p/
54
58
  $annotate = true
55
59
  require_relative '../lib/cbor-pp'
56
60
  end
57
61
  case ARGV[1]
62
+ when /\A..*s/
63
+ $sequence = true
64
+ end
65
+ case ARGV[1]
58
66
  when /\Ar/ # secret
59
67
  $advanced = true
60
68
  my_pp parser.rules
@@ -81,15 +89,25 @@ begin
81
89
  g = parser.generate
82
90
  puts JSON.pretty_generate(g)
83
91
  end
84
- when /\Av/
85
- instance = read_arg(ARGV[2])
86
- instance = CBOR.decode(instance.b) rescue JSON.load(instance)
87
- instance = instance.cbor_clone if $annotate && ENV["EXPERIMENTAL_ANNOTATE"]
88
- ann = parser.validate(instance)
89
- # my_pp ann
90
- instance.cbor_add_annotations_from(ann) rescue nil
91
- my_diag(instance) if $annotate
92
- exit 1 unless ann
92
+ when /\Av(v)?/
93
+ verbose = $1
94
+ ARGV[2..-1].each do |fn|
95
+ instance = read_arg(fn)
96
+ instance = if $sequence
97
+ CBOR.decode("\x9f".b << instance.b << "\xff".b)
98
+ else
99
+ CBOR.decode(instance.b) rescue JSON.load(instance)
100
+ end
101
+ instance = instance.cbor_clone if $annotate && ENV["EXPERIMENTAL_ANNOTATE"]
102
+ warn "#{fn}:" if verbose
103
+ ann = parser.validate(instance)
104
+ # my_pp ann
105
+ instance.cbor_add_annotations_from(ann) rescue nil
106
+ my_diag(instance) if $annotate
107
+ unless ann
108
+ retcode = 1
109
+ end
110
+ end
93
111
  else
94
112
  usage
95
113
  end
@@ -97,3 +115,5 @@ rescue CDDL::ParseError => e
97
115
  warn e.message
98
116
  exit EX_DATAERR
99
117
  end
118
+
119
+ exit retcode
data/cddl.gemspec CHANGED
@@ -1,11 +1,12 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.8.8'
3
+ s.version = '0.9.1'
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')
7
7
  s.add_dependency('abnc')
8
- s.add_dependency('json')
8
+ s.add_dependency('json_pure')
9
+ s.add_dependency('abnftt')
9
10
  s.add_dependency('regexp-examples') # , '1.1.0')
10
11
  s.add_dependency('colorize')
11
12
  s.files = `git ls-files`.split("\n").grep(/^[a-z]/)
@@ -19,3 +20,4 @@ spec = Gem::Specification.new do |s|
19
20
  s.homepage = "http://github.com/cabo/cddl"
20
21
  s.license = 'MIT'
21
22
  end
23
+
data/data/cddl.abnf CHANGED
@@ -16,6 +16,7 @@ type1 = type2 [S (rangeop / annotator) S type2]
16
16
  / "#" "6" ["." uint] "(" S type S ")" ; note no space!
17
17
  / "#" DIGIT ["." uint] ; major/ai
18
18
  / "#" ; any
19
+ / "~" S typename [genericarg]
19
20
  / "{" S group S "}"
20
21
  / "[" S group S "]"
21
22
  / "&" S "(" S group S ")"
data/lib/cbor-pp-play.rb CHANGED
@@ -2,6 +2,7 @@ require_relative "cbor-pp"
2
2
 
3
3
  a = [1, {foo: "bar", busel: "basel", baz: "bass", ant: "cat", bat: "dog", eel: "fox"},
4
4
  2, 3, 4, [3]*55, "foo".b, 0.00006103515625, 0.0000099, 1e-7, nil]
5
+ a[0].cbor_annotation_add "flurp"
5
6
  a[1].cbor_annotation_add "fasel"
6
7
  CBOR::PP.pp a
7
8
 
data/lib/cddl.rb CHANGED
@@ -3,6 +3,7 @@ require 'pp'
3
3
  require 'pathname'
4
4
  require 'cbor-pure' unless defined?(CBOR::Tagged)
5
5
  require 'regexp-examples'
6
+ require 'abnftt'
6
7
  require 'colorize'
7
8
  require 'base64'
8
9
 
@@ -55,6 +56,8 @@ module CDDL
55
56
  @ast = @abnf.ast?
56
57
  # our little argument stack for rule processing
57
58
  @insides = []
59
+ # collect error information
60
+ @last_message = ""
58
61
  end
59
62
 
60
63
  def apr # for debugging
@@ -243,12 +246,28 @@ module CDDL
243
246
  [rule[0], *rule[1]]
244
247
  end
245
248
 
249
+ def remove_indentation(s)
250
+ l = s.lines
251
+ indent = l.grep(/\S/).map {|l| l[/^\s*/].size}.min
252
+ l.map {|l| l.sub(/^ {0,#{indent}}/, "")}.join
253
+ end
254
+
246
255
  # Memoize a bit here
247
256
 
248
257
  REGEXP_FOR_STRING = Hash.new {|h, k|
249
258
  h[k] = Regexp.new("\\A#{k}\\z")
250
259
  }
251
260
 
261
+ ABNF_PARSER_FOR_STRING = Hash.new {|h, k|
262
+ grammar = "cddl-t0p--1eve1-f0r--abnf = " << k # XXX
263
+ h[k] = ABNF.from_abnf(grammar)
264
+ }
265
+
266
+ ABNF_ENCODING_FOR_CONOP = {
267
+ abnf: Encoding::UTF_8,
268
+ abnfb: Encoding::BINARY
269
+ }
270
+
252
271
  def generate
253
272
  @recursion = 0
254
273
  generate1(rules)
@@ -329,8 +348,12 @@ module CDDL
329
348
  unless kr
330
349
  case vr[0]
331
350
  when :grpent
332
- fail "grpent in map #{vr.inspect}" unless vr.size == 2
333
- g = Array.new(st) { generate1(vr[1], true) }.flatten(1)
351
+ # fail "grpent in map #{vr.inspect}" unless vr.size == 2
352
+ g = Array.new(st) {
353
+ vr[1..-1].map{ |vrx|
354
+ generate1(vrx, true)
355
+ }.flatten(1)
356
+ }.flatten(1)
334
357
  # warn "GGG #{g.inspect}"
335
358
  return g
336
359
  when :grpchoice
@@ -389,7 +412,7 @@ module CDDL
389
412
  when :anno
390
413
  target = where[2]
391
414
  control = where[3]
392
- case where[1]
415
+ case conop = where[1]
393
416
  when :size
394
417
  should_be_int = generate1(control)
395
418
  unless (Array === target && target[0] == :prim && [0, 2, 3].include?(target[1])) && Integer === should_be_int && should_be_int >= 0
@@ -435,6 +458,35 @@ module CDDL
435
458
  $default_warned = true
436
459
  end
437
460
  generate1(target, inmap)
461
+ when :feature
462
+ generate1(target, inmap)
463
+ when :cat, :det
464
+ lhs = generate1(target, inmap)
465
+ rhs = generate1(control)
466
+ if conop == :det
467
+ lhs = remove_indentation(lhs)
468
+ rhs = remove_indentation(rhs)
469
+ end
470
+ begin
471
+ lhs + rhs
472
+ rescue Exception => e
473
+ fail "Can't #{lhs.inspect} .cat #{rhs.inspect}: #{e.message}"
474
+ end
475
+ when :plus
476
+ lhs = generate1(target, inmap)
477
+ rhs = generate1(control)
478
+ begin
479
+ case lhs
480
+ when Integer
481
+ lhs + Integer(rhs)
482
+ when Numeric
483
+ lhs + rhs
484
+ else
485
+ fail "#{lhs.inspect}: Not a number"
486
+ end
487
+ rescue Exception => e
488
+ fail "Can't #{lhs.inspect} .plus #{rhs.inspect}: #{e.message}"
489
+ end
438
490
  when :eq
439
491
  content = generate1(control)
440
492
  if validate1(content, where)
@@ -448,7 +500,7 @@ module CDDL
448
500
  content = Integer(content)
449
501
  case target[1]
450
502
  when 0
451
- case where[1]
503
+ case conop
452
504
  when :lt
453
505
  rand(0...content)
454
506
  when :le
@@ -475,12 +527,26 @@ module CDDL
475
527
  fail "Don't know yet how to generate #{where}"
476
528
  end
477
529
  REGEXP_FOR_STRING[regexp].random_example(max_repeater_variance: 5)
530
+ when :abnf, :abnfb
531
+ grammar = generate1(control)
532
+ bytes = true if target == [:prim, 2]
533
+ bytes = false if target == [:prim, 3]
534
+ unless !bytes.nil? && String === grammar
535
+ fail "Don't know yet how to generate #{where}"
536
+ end
537
+ grammar << "\n" unless grammar =~ /\n\z/
538
+ out = ABNF_PARSER_FOR_STRING[grammar].generate
539
+ if conop == :abnfb
540
+ out = out.codepoints.pack("C*")
541
+ end
542
+ enc = bytes ? Encoding::BINARY : Encoding::UTF_8
543
+ out.force_encoding(enc)
478
544
  when :cbor, :cborseq
479
545
  unless target == [:prim, 2]
480
546
  fail "Don't know yet how to generate #{where}"
481
547
  end
482
548
  content = CBOR::encode(generate1(control))
483
- if where[1] == :cborseq
549
+ if conop == :cborseq
484
550
  # remove the first head
485
551
  n = case content.getbyte(0) - (4 << 5)
486
552
  when 0..23; 1
@@ -498,7 +564,7 @@ module CDDL
498
564
  content = generate1(target)
499
565
  if validate1(content, control)
500
566
  return content
501
- elsif where[1] == :within
567
+ elsif conop == :within
502
568
  warn "*** #{content.inspect} meets #{target.inspect} but not #{control.inspect}"
503
569
  end
504
570
  end
@@ -523,7 +589,7 @@ module CDDL
523
589
  end
524
590
  end
525
591
 
526
- VALUE_TYPE = {text: String, int: Integer, float: Float}
592
+ VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
527
593
  SIMPLE_VALUE = {
528
594
  [:prim, 7, 20] => [true, false, :bool],
529
595
  [:prim, 7, 21] => [true, true, :bool],
@@ -536,9 +602,38 @@ module CDDL
536
602
  [true, t[1], vt]
537
603
  elsif v = SIMPLE_VALUE[t]
538
604
  v
539
- else
540
- [false]
541
- end
605
+ elsif t[0] == :anno
606
+ _, conop, target, control = t
607
+ # warn ["EXV0", conop, target, control].inspect
608
+ if conop == :cat || conop == :plus || conop == :det
609
+ ok1, v1, vt1 = extract_value(target)
610
+ ok2, v2, vt2 = extract_value(control)
611
+ # warn ["EXV", ok1, v1, vt1, ok2, v2, vt2].inspect
612
+ if ok1 && ok2
613
+ if vt1 == Integer
614
+ [true, v1 + Integer(v2), Integer] if vt2 == Integer || vt2 == Float
615
+ elsif vt1 == Float
616
+ [true, v1 + v2, vt1] if vt2 == Integer || vt2 == Float
617
+ else
618
+ if conop == :det
619
+ v1 = remove_indentation(v1)
620
+ v2 = remove_indentation(v2)
621
+ end
622
+ [true, v1 + v2, vt1] if vt1 == vt2
623
+ end
624
+ end rescue nil
625
+ end
626
+ end || [false]
627
+ end
628
+
629
+ def extract_array(t)
630
+ return [false] unless t[0] == :array
631
+ [true, *t[1..-1].map { |el|
632
+ return [false] unless el[0..3] == [:member, 1, 1, nil]
633
+ ok, v, vt = extract_value(el[4])
634
+ return [false] unless ok
635
+ [v, vt]
636
+ }]
542
637
  end
543
638
 
544
639
  def validate_diag
@@ -547,11 +642,20 @@ module CDDL
547
642
 
548
643
  def validate(d, warn=true)
549
644
  @recursion = 0
645
+ $features = Hash.new {|h, k| h[k] = {}}
550
646
  result = validate1a(d, rules)
551
- unless result
552
- if warn
647
+ if warn
648
+ if result
649
+ if $features != {}
650
+ ok = ENV["CDDL_FEATURE_OK"] and ok = ok.split(/,\s*/) or ok = []
651
+ # warn([:OK, ok, $features].inspect)
652
+ features = $features.reject {|k, v| ok.include? k.to_s }
653
+ warn "** Features potentially used (#$fn): #{features.map {|k, v| "#{k}: #{v.keys}"}.join(", ")}" if features != {}
654
+ end
655
+ else
553
656
  warn "CDDL validation failure (#{result.inspect} for #{d.inspect}):"
554
657
  PP::pp(validate_diag, STDERR)
658
+ puts(validate_diag.cbor_diagnostic)
555
659
  end
556
660
  end
557
661
  result
@@ -559,7 +663,7 @@ module CDDL
559
663
 
560
664
  def validate_result(check)
561
665
  check || (
562
- @last_message = yield
666
+ @last_message << yield
563
667
  false
564
668
  )
565
669
  end
@@ -592,7 +696,9 @@ module CDDL
592
696
  ann.concat(ann2)
593
697
  end
594
698
  if occ < s
595
- @last_message = "occur not reached in array #{d} for #{where}"
699
+ # warn "*** lme #{@last_message.encoding} #{@last_message}"
700
+ # warn "*** #{"\noccur #{occ} < #{s}, not reached at #{i} in array #{d} for #{where}".encoding}"
701
+ @last_message << "\noccur #{occ} < #{s}, not reached at #{i} in array #{d} for #{where}"
596
702
  return [false, ann]
597
703
  end
598
704
  end
@@ -681,13 +787,17 @@ module CDDL
681
787
  puts "COMPLEX: #{k.inspect} #{simple.inspect} #{simpleval.inspect}" if ENV["CDDL_TRACE"]
682
788
  keys = d_check.keys
683
789
  ta, keys = keys.partition{ |key| validate1(key, k)}
684
- # XXX check ta.size against s/e
685
- ta.all? { |val|
686
- if (ann2 = validate1a(d[val], v)) &&
687
- d_check.delete(val) {:not_found} != :not_found
688
- anno.concat(ann2)
689
- end
690
- }
790
+ count = 0
791
+ catch :enough do
792
+ ta.all? { |val|
793
+ if (ann2 = validate1a(d[val], v)) && # XXX check cut or not!
794
+ d_check.delete(val) {:not_found} != :not_found
795
+ anno.concat(ann2)
796
+ throw :enough, true if (count += 1) == e
797
+ true
798
+ end
799
+ }
800
+ end and validate_result(count >= s) { "not enough #{ta.inspect} for #{r.inspect}" }
691
801
  end
692
802
  end
693
803
  else
@@ -741,16 +851,31 @@ module CDDL
741
851
  idx, ann = validate_forward(d, 0, where)
742
852
  ann if validate_result(idx == d.size) { "#{validate_diag.inspect} -- cannot complete (#{idx}, #{d.size}) array #{d} for #{where}" }
743
853
  end
744
- when :text, :int, :float, :bytes
854
+ when :int, :float
745
855
  _, v = extract_value(where)
746
856
  [] if d == v
857
+ when :text, :bytes
858
+ _, v = extract_value(where)
859
+ [] if d == v && ((d.encoding == Encoding::BINARY) == (v.encoding == Encoding::BINARY))
747
860
  when :range
748
861
  [] if where[2] === d && where[1].include?(d)
749
862
  when :anno
750
- target = where[2]
751
- if ann = validate1a(d, target)
752
- control = where[3]
753
- case where[1]
863
+ _, conop, target, control = where
864
+ if conop == :cat || conop == :plus || conop == :det
865
+ ok1, v1, vt1 = extract_value(target)
866
+ ok2, v2, vt2 = extract_value(control)
867
+ # warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect
868
+ if ok1 && ok2
869
+ v2 = Integer(v2) if vt1 == Integer
870
+ if conop == :det
871
+ v1 = remove_indentation(v1)
872
+ v2 = remove_indentation(v2)
873
+ end
874
+ # warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
875
+ [] if d == v1 + v2 # XXX Focus ArgumentError
876
+ end
877
+ elsif ann = validate1a(d, target)
878
+ case conop
754
879
  when :size
755
880
  case d
756
881
  when Integer
@@ -789,8 +914,26 @@ module CDDL
789
914
  $default_warned = true
790
915
  end
791
916
  ann
917
+ when :feature
918
+ ok, v, vt = extract_value(control)
919
+ if ok
920
+ nm = v
921
+ det = d
922
+ warn "*** feature controller should be a string: #{control.inspect}" unless String == vt
923
+ else
924
+ ok, *v = extract_array(control)
925
+ if ok && v.size == 2
926
+ nm = v[0][0]
927
+ det = v[1][0]
928
+ warn "*** first element of feature controller should be a string: #{control.inspect}" unless String === nm
929
+ else
930
+ warn "*** feature controller not implemented: #{control.inspect}"
931
+ end
932
+ end
933
+ $features[nm][det] = true
934
+ ann
792
935
  when :lt, :le, :gt, :ge, :eq, :ne
793
- op = OPERATORS[where[1]]
936
+ op = OPERATORS[conop]
794
937
  ok, v, _vt = extract_value(control)
795
938
  if ok
796
939
  ann if d.send(op, v) rescue nil # XXX Focus ArgumentError
@@ -806,6 +949,24 @@ module CDDL
806
949
  end
807
950
  end
808
951
  )
952
+ when :abnf, :abnfb
953
+ ann if (
954
+ if String === d
955
+ ok, v, vt = extract_value(control)
956
+ if ok && vt == String
957
+ begin
958
+ ABNF_PARSER_FOR_STRING[v].validate(
959
+ d.dup.force_encoding(ABNF_ENCODING_FOR_CONOP[conop]).codepoints.pack("U*")
960
+ )
961
+ true
962
+ rescue => e
963
+ # warn "*** #{e}" # XXX
964
+ @last_message = e.to_s.force_encoding(Encoding::UTF_8)
965
+ nil
966
+ end
967
+ end
968
+ end
969
+ )
809
970
  when :cbor
810
971
  ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
811
972
  when :cborseq
@@ -837,6 +998,14 @@ module CDDL
837
998
  when 3
838
999
  String === d && d.encoding != Encoding::BINARY # cheat
839
1000
  when 6
1001
+ if Integer === d
1002
+ t = 2 # assuming only 2/3 match an Integer
1003
+ if d < 0
1004
+ d = ~d
1005
+ t = 3
1006
+ end
1007
+ d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
1008
+ end
840
1009
  CBOR::Tagged === d && d.tag == where[2] && validate1a(d.data, where[3])
841
1010
  when 7
842
1011
  t, v = extract_value(where)
@@ -959,7 +1128,7 @@ module CDDL
959
1128
  when ""
960
1129
  parts[1].b
961
1130
  when "h"
962
- parts[1].gsub(/\s/, "").chars.each_slice(2).map{ |x| Integer(x.join, 16).chr("BINARY") }.join
1131
+ parts[1].gsub(/\s/, "").chars.each_slice(2).map{ |x| Integer(x.join, 16).chr("BINARY") }.join.b
963
1132
  when "b64"
964
1133
  Base64.urlsafe_decode64(parts[1])
965
1134
  else
@@ -1073,9 +1242,13 @@ module CDDL
1073
1242
  def g_process(name, g, genericargs)
1074
1243
  r, ids = g
1075
1244
  args = genericargs.children(:type1).map {|x| type1(x, true)}
1245
+ # warn "** args #{args.inspect}"
1076
1246
  fail "number of args #{name} #{ids.size} #{args.size}" if ids.size != args.size
1077
1247
  bindings = Hash[ids.zip(args)]
1078
- r_process("#{name}<#{genericargs._strip}>", r, bindings)
1248
+ # warn "** bindings: #{bindings.inspect}"
1249
+ genname = "#{name}<#{args.inspect}>" # XXX this works up to a RECURSE...
1250
+ # warn "** genname #{genname}"
1251
+ r_process(genname, r, bindings)
1079
1252
  end
1080
1253
 
1081
1254
  def type_recall(name, canbegroup, genericargs)
@@ -1142,7 +1315,7 @@ module CDDL
1142
1315
  end
1143
1316
  when :recurse_grpent # XXX we don't have the entry yet
1144
1317
  when :member
1145
- fail "map entry without member key given: #{member}" unless member[3] || member[4][0] == :grpent || member[4][0] == :grpchoice
1318
+ fail "map entry #{member.inspect} without member key given: #{member}" unless member[3] || member[4][0] == :grpent || member[4][0] == :grpchoice
1146
1319
  else
1147
1320
  fail ["type1 member", member].inspect unless member[0] == :member
1148
1321
  end
@@ -1152,7 +1325,8 @@ module CDDL
1152
1325
  BRACE = {"{" => :map, "[" => :array}
1153
1326
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
1154
1327
  SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
1155
- :default, :lt, :le, :gt, :ge, :eq, :ne]
1328
+ :default, :lt, :le, :gt, :ge, :eq, :ne,
1329
+ :feature, :abnf, :abnfb, :det, :cat, :plus]
1156
1330
 
1157
1331
  def type1(n, canbegroup = false)
1158
1332
  # puts "NVALUE #{n.value.inspect}"
@@ -1214,6 +1388,26 @@ module CDDL
1214
1388
  v
1215
1389
  }
1216
1390
  ]
1391
+ when /\A~/
1392
+ if tn = n.typename
1393
+ s = type_recall(tn.to_s, false, n.genericarg).flatten(1)
1394
+ else
1395
+ fail "No typename in unwrap #{n}"
1396
+ end
1397
+ if s[0] != :type1
1398
+ fail [:UNWRAPs0, s].inspect
1399
+ end
1400
+ case s[1]
1401
+ when :map, :array
1402
+ [:grpent, s[2..-1]]
1403
+ when :prim
1404
+ if s[2] != 6
1405
+ fail [:UNWRAPs2, s].inspect
1406
+ end
1407
+ s[4] # check :type1?
1408
+ else
1409
+ fail [:UNWRAPs1, s].inspect
1410
+ end
1217
1411
  else
1218
1412
  "unimplemented #{n}"
1219
1413
  end
data/test/test-cddl.rb CHANGED
@@ -171,6 +171,57 @@ HERE
171
171
  assert parser.validate_for_test(true)
172
172
  end
173
173
 
174
+ def test_validate_bignum
175
+ parser = CDDL::Parser.new <<HERE
176
+ test = bigint
177
+ HERE
178
+ assert parser.validate_for_test(2**4711)
179
+ assert parser.validate_for_test(-2**815)
180
+ assert parser.validate_for_test(1)
181
+ assert parser.validate_for_test(0)
182
+ assert parser.validate_for_test(-11)
183
+ end
184
+
185
+ def test_aaaaaaaa_invalidate_bignum
186
+ parser = CDDL::Parser.new <<HERE
187
+ test = bignint
188
+ HERE
189
+ refute parser.validate_for_test(2**4711, false)
190
+ assert parser.validate_for_test(-2**815)
191
+ refute parser.validate_for_test(1, false)
192
+ refute parser.validate_for_test(0, false)
193
+ assert parser.validate_for_test(-11)
194
+ end
195
+
196
+
197
+ def test_aaaaaaaa_validate_bignum0b
198
+ parser = CDDL::Parser.new <<HERE
199
+ test = #6.2("")
200
+ HERE
201
+ refute parser.validate_for_test(1, false)
202
+ refute parser.validate_for_test(0, false)
203
+ end
204
+
205
+
206
+ def test_aaaaaaaa_validate_bignum0
207
+ parser = CDDL::Parser.new <<HERE
208
+ test = #6.2(h'')
209
+ HERE
210
+ assert parser.validate_for_test(0)
211
+ refute parser.validate_for_test(1, false)
212
+ end
213
+
214
+
215
+ def test_aaaaaaaa_validate_bignum1
216
+ parser = CDDL::Parser.new <<HERE
217
+ test = #6.2(h'01')
218
+ HERE
219
+ assert parser.validate_for_test(1)
220
+ refute parser.validate_for_test(0, false)
221
+ refute parser.validate_for_test(2, false)
222
+ end
223
+
224
+
174
225
  def test_validate_a
175
226
  parser = CDDL::Parser.new <<HERE
176
227
  test = [* one: 1]
@@ -0,0 +1,14 @@
1
+ coap-problem-details = {
2
+ type => uint,
3
+ ? title => text,
4
+ ? response-code => bstr .size 1,
5
+ ? detail => text,
6
+ ? instance => uri,
7
+ * $$coap-problem-details-extension,
8
+ }
9
+
10
+ type = 0
11
+ title = 1
12
+ response-code = 2
13
+ detail = 3
14
+ instance = 4
@@ -0,0 +1 @@
1
+ abignum = unsigned
@@ -0,0 +1,3 @@
1
+ foo = text .abnf '4DIGIT
2
+ DIGIT = %x30-39 ; 0-9
3
+ '