cddl 0.8.8 → 0.8.29
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 +4 -4
- data/bin/cddl +35 -15
- data/cddl.gemspec +3 -1
- data/data/cddl.abnf +1 -0
- data/lib/cbor-pp-play.rb +1 -0
- data/lib/cddl.rb +225 -31
- data/test/test-cddl.rb +51 -0
- data/test-data/7807.cddl +14 -0
- data/test-data/abignum.cddl +1 -0
- data/test-data/abnf1.cddl +3 -0
- data/test-data/abnf2.cddl +37 -0
- data/test-data/abnf3.cddl +32 -0
- data/test-data/bat.cddl +16 -0
- data/test-data/bpv7.cddl +136 -0
- data/test-data/bpv7a.cddl +181 -0
- data/test-data/bpv7b.cddl +167 -0
- data/test-data/cat-re.cddl +2 -0
- data/test-data/complex-occ.cddl +11 -0
- data/test-data/coral.cddl +10 -0
- data/test-data/coral1.cddl +5 -0
- data/test-data/coral2.cddl +7 -0
- data/test-data/coral3.cddl +7 -0
- data/test-data/det1.cddl +12 -0
- data/test-data/feat1.cddl +4 -0
- data/test-data/feature-controller.cddl +6 -0
- data/test-data/feature-detail.cddl +5 -0
- data/test-data/foo.cddl +1 -0
- data/test-data/homenet-de.cddl +12 -0
- data/test-data/homenet-fe.cddl +12 -0
- data/test-data/jim-cut-2.cddl +11 -0
- data/test-data/jim-cut.cddl +12 -0
- data/test-data/jsoniodef.cddl +719 -0
- data/test-data/lint1.cddl +9 -0
- data/test-data/mdl-ble.cddl +9 -0
- data/test-data/mdl-deve.cddl +54 -0
- data/test-data/mdl-dp.cddl +11 -0
- data/test-data/mdl-mso.cddl +20 -0
- data/test-data/mdl-request.cddl +26 -0
- data/test-data/mdl-response.cddl +66 -0
- data/test-data/mdl.cddl +11 -0
- data/test-data/mon-val.cddl +1 -0
- data/test-data/multipart-ct.cddl +2 -0
- data/test-data/named-group.cddl +7 -0
- data/test-data/non-empty.cddl +5 -0
- data/test-data/oid.cddl +8 -0
- data/test-data/oidbat.cddl +8 -0
- data/test-data/plus.cddl +3 -0
- data/test-data/sasl.cddl +24 -0
- data/test-data/sequence.cddl +1 -0
- data/test-data/sipos.cddl +8 -0
- data/test-data/star-edited.cddl +98 -0
- data/test-data/star.cddl +95 -0
- data/test-data/test-gen.cddl +3 -0
- data/test-data/time.cddl +11 -0
- data/test-data/yangid.cddl +1 -0
- data/test-data/yaron1.cddl +95 -0
- metadata +69 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d71bf9745f9a7e1c96d6ae4007cf598a36617347c1ed772950ace7dedef3c121
|
|
4
|
+
data.tar.gz: ca84d02afd7243260046c0e75ae0b14eb5442238b97ef56f050ff0d9cbecd6c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0595a939e1677462971fba537b6cab3268b84662e4764e2ab69658009928687ca85da7ceb721ee23c6b803c1bf70cebcb90471703cd6fb17325f37838bc45fc7'
|
|
7
|
+
data.tar.gz: a69d45135335bfcdacc58c03339ec5a7316cb4d99596e65b67b7ca947e65a47adc3fcbd7469b442d9c6bd5fec2d1ee9da8a7a07204f26a489c3c3505205abd6c
|
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
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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.
|
|
3
|
+
s.version = '0.8.29'
|
|
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
8
|
s.add_dependency('json')
|
|
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) {
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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
|
-
|
|
552
|
-
if
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
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 :
|
|
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
|
|
751
|
-
if
|
|
752
|
-
|
|
753
|
-
|
|
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[
|
|
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
|
-
|
|
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]
|
data/test-data/7807.cddl
ADDED
|
@@ -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
|