cddl 0.8.16 → 0.8.21
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 +24 -14
- data/cddl.gemspec +2 -1
- data/lib/cddl.rb +63 -9
- 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/cat-re.cddl +2 -0
- data/test-data/oid.cddl +8 -0
- data/test-data/oidbat.cddl +8 -0
- data/test-data/sasl.cddl +24 -0
- metadata +24 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 207ea6c166a60cfc705009af0a15b9633e301429cd8958d279f9d710800765bb
|
4
|
+
data.tar.gz: 6b0e05ce4c0059d2a40a39892784da5e838451772bbad0d301c056a2c83418cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fd0733ddb7c869b89578d92aee41d818ae3a4c85fbb9db0d4377136498195c054c17670c00ae89322578d5f6dfa64e1f10c5ed6c9c1cfcee27e9d135d9ac843
|
7
|
+
data.tar.gz: 7a64af74fe96ae30fe834c36ca7c59326257f27e2d9a16ac3edb97bd1772c46e6f77c4a8dd715c27996a1b59369b8efe7be8332f82215afd7a0014cb72097f59
|
data/bin/cddl
CHANGED
@@ -14,8 +14,8 @@ 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
|
|
@@ -48,6 +48,8 @@ def my_diag(v)
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
retcode = 0
|
52
|
+
|
51
53
|
begin
|
52
54
|
case ARGV[1]
|
53
55
|
when /\A..*p/
|
@@ -85,19 +87,25 @@ begin
|
|
85
87
|
g = parser.generate
|
86
88
|
puts JSON.pretty_generate(g)
|
87
89
|
end
|
88
|
-
when /\Av
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
90
|
+
when /\Av(v)?/
|
91
|
+
verbose = $1
|
92
|
+
ARGV[2..-1].each do |fn|
|
93
|
+
instance = read_arg(fn)
|
94
|
+
instance = if $sequence
|
95
|
+
CBOR.decode("\x9f".b << instance.b << "\xff".b)
|
96
|
+
else
|
97
|
+
CBOR.decode(instance.b) rescue JSON.load(instance)
|
98
|
+
end
|
99
|
+
instance = instance.cbor_clone if $annotate && ENV["EXPERIMENTAL_ANNOTATE"]
|
100
|
+
warn "#{fn}:" if verbose
|
101
|
+
ann = parser.validate(instance)
|
102
|
+
# my_pp ann
|
103
|
+
instance.cbor_add_annotations_from(ann) rescue nil
|
104
|
+
my_diag(instance) if $annotate
|
105
|
+
unless ann
|
106
|
+
retcode = 1
|
107
|
+
end
|
94
108
|
end
|
95
|
-
instance = instance.cbor_clone if $annotate && ENV["EXPERIMENTAL_ANNOTATE"]
|
96
|
-
ann = parser.validate(instance)
|
97
|
-
# my_pp ann
|
98
|
-
instance.cbor_add_annotations_from(ann) rescue nil
|
99
|
-
my_diag(instance) if $annotate
|
100
|
-
exit 1 unless ann
|
101
109
|
else
|
102
110
|
usage
|
103
111
|
end
|
@@ -105,3 +113,5 @@ rescue CDDL::ParseError => e
|
|
105
113
|
warn e.message
|
106
114
|
exit EX_DATAERR
|
107
115
|
end
|
116
|
+
|
117
|
+
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.21'
|
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]/)
|
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
|
|
@@ -243,12 +244,28 @@ module CDDL
|
|
243
244
|
[rule[0], *rule[1]]
|
244
245
|
end
|
245
246
|
|
247
|
+
def remove_indentation(s)
|
248
|
+
l = s.lines
|
249
|
+
indent = l.grep(/\S/).map {|l| l[/^\s*/].size}.min
|
250
|
+
l.map {|l| l.sub(/^ {0,#{indent}}/, "")}.join
|
251
|
+
end
|
252
|
+
|
246
253
|
# Memoize a bit here
|
247
254
|
|
248
255
|
REGEXP_FOR_STRING = Hash.new {|h, k|
|
249
256
|
h[k] = Regexp.new("\\A#{k}\\z")
|
250
257
|
}
|
251
258
|
|
259
|
+
ABNF_PARSER_FOR_STRING = Hash.new {|h, k|
|
260
|
+
grammar = "cddl-t0p--1eve1-f0r--abnf = " << k # XXX
|
261
|
+
h[k] = ABNF.from_abnf(grammar)
|
262
|
+
}
|
263
|
+
|
264
|
+
ABNF_ENCODING_FOR_CONOP = {
|
265
|
+
abnf: Encoding::UTF_8,
|
266
|
+
abnfb: Encoding::BINARY
|
267
|
+
}
|
268
|
+
|
252
269
|
def generate
|
253
270
|
@recursion = 0
|
254
271
|
generate1(rules)
|
@@ -393,7 +410,7 @@ module CDDL
|
|
393
410
|
when :anno
|
394
411
|
target = where[2]
|
395
412
|
control = where[3]
|
396
|
-
case where[1]
|
413
|
+
case conop = where[1]
|
397
414
|
when :size
|
398
415
|
should_be_int = generate1(control)
|
399
416
|
unless (Array === target && target[0] == :prim && [0, 2, 3].include?(target[1])) && Integer === should_be_int && should_be_int >= 0
|
@@ -441,9 +458,10 @@ module CDDL
|
|
441
458
|
generate1(target, inmap)
|
442
459
|
when :feature
|
443
460
|
generate1(target, inmap)
|
444
|
-
when :cat
|
461
|
+
when :cat, :det
|
445
462
|
lhs = generate1(target, inmap)
|
446
463
|
rhs = generate1(control)
|
464
|
+
rhs = remove_indentation(rhs) if conop == :det
|
447
465
|
begin
|
448
466
|
lhs + rhs
|
449
467
|
rescue Exception => e
|
@@ -477,7 +495,7 @@ module CDDL
|
|
477
495
|
content = Integer(content)
|
478
496
|
case target[1]
|
479
497
|
when 0
|
480
|
-
case
|
498
|
+
case conop
|
481
499
|
when :lt
|
482
500
|
rand(0...content)
|
483
501
|
when :le
|
@@ -504,12 +522,25 @@ module CDDL
|
|
504
522
|
fail "Don't know yet how to generate #{where}"
|
505
523
|
end
|
506
524
|
REGEXP_FOR_STRING[regexp].random_example(max_repeater_variance: 5)
|
525
|
+
when :abnf, :abnfb
|
526
|
+
grammar = generate1(control)
|
527
|
+
bytes = true if target == [:prim, 2]
|
528
|
+
bytes = false if target == [:prim, 3]
|
529
|
+
unless !bytes.nil? && String === grammar
|
530
|
+
fail "Don't know yet how to generate #{where}"
|
531
|
+
end
|
532
|
+
out = ABNF_PARSER_FOR_STRING[grammar].generate
|
533
|
+
if conop == :abnfb
|
534
|
+
out = out.codepoints.pack("C*")
|
535
|
+
end
|
536
|
+
enc = bytes ? Encoding::BINARY : Encoding::UTF_8
|
537
|
+
out.force_encoding(enc)
|
507
538
|
when :cbor, :cborseq
|
508
539
|
unless target == [:prim, 2]
|
509
540
|
fail "Don't know yet how to generate #{where}"
|
510
541
|
end
|
511
542
|
content = CBOR::encode(generate1(control))
|
512
|
-
if
|
543
|
+
if conop == :cborseq
|
513
544
|
# remove the first head
|
514
545
|
n = case content.getbyte(0) - (4 << 5)
|
515
546
|
when 0..23; 1
|
@@ -527,7 +558,7 @@ module CDDL
|
|
527
558
|
content = generate1(target)
|
528
559
|
if validate1(content, control)
|
529
560
|
return content
|
530
|
-
elsif
|
561
|
+
elsif conop == :within
|
531
562
|
warn "*** #{content.inspect} meets #{target.inspect} but not #{control.inspect}"
|
532
563
|
end
|
533
564
|
end
|
@@ -568,7 +599,7 @@ module CDDL
|
|
568
599
|
elsif t[0] == :anno
|
569
600
|
_, conop, target, control = t
|
570
601
|
# warn ["EXV0", conop, target, control].inspect
|
571
|
-
if conop == :cat || conop == :plus
|
602
|
+
if conop == :cat || conop == :plus || conop == :det
|
572
603
|
ok1, v1, vt1 = extract_value(target)
|
573
604
|
ok2, v2, vt2 = extract_value(control)
|
574
605
|
# warn ["EXV", ok1, v1, vt1, ok2, v2, vt2].inspect
|
@@ -578,6 +609,7 @@ module CDDL
|
|
578
609
|
elsif vt1 == Float
|
579
610
|
[true, v1 + v2, vt1] if vt2 == Integer || vt2 == Float
|
580
611
|
else
|
612
|
+
v2 = remove_indentation(v2) if conop == :det
|
581
613
|
[true, v1 + v2, vt1] if vt1 == vt2
|
582
614
|
end
|
583
615
|
end rescue nil
|
@@ -622,7 +654,7 @@ module CDDL
|
|
622
654
|
|
623
655
|
def validate_result(check)
|
624
656
|
check || (
|
625
|
-
@last_message
|
657
|
+
@last_message << yield
|
626
658
|
false
|
627
659
|
)
|
628
660
|
end
|
@@ -655,7 +687,9 @@ module CDDL
|
|
655
687
|
ann.concat(ann2)
|
656
688
|
end
|
657
689
|
if occ < s
|
658
|
-
|
690
|
+
# warn "*** lme #{@last_message.encoding} #{@last_message}"
|
691
|
+
# warn "*** #{"\noccur #{occ} < #{s}, not reached at #{i} in array #{d} for #{where}".encoding}"
|
692
|
+
@last_message << "\noccur #{occ} < #{s}, not reached at #{i} in array #{d} for #{where}"
|
659
693
|
return [false, ann]
|
660
694
|
end
|
661
695
|
end
|
@@ -820,6 +854,7 @@ module CDDL
|
|
820
854
|
# warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect
|
821
855
|
if ok1 && ok2
|
822
856
|
v2 = Integer(v2) if vt1 == Integer
|
857
|
+
v2 = remove_indentation(v2) if conop == :det
|
823
858
|
# warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
|
824
859
|
[] if d == v1 + v2 # XXX Focus ArgumentError
|
825
860
|
end
|
@@ -896,6 +931,24 @@ module CDDL
|
|
896
931
|
end
|
897
932
|
end
|
898
933
|
)
|
934
|
+
when :abnf, :abnfb
|
935
|
+
ann if (
|
936
|
+
if String === d
|
937
|
+
ok, v, vt = extract_value(control)
|
938
|
+
if ok && vt == String
|
939
|
+
begin
|
940
|
+
ABNF_PARSER_FOR_STRING[v].validate(
|
941
|
+
d.dup.force_encoding(ABNF_ENCODING_FOR_CONOP[conop]).codepoints.pack("U*")
|
942
|
+
)
|
943
|
+
true
|
944
|
+
rescue => e
|
945
|
+
# warn "*** #{e}" # XXX
|
946
|
+
@last_message = e.to_s.force_encoding(Encoding::UTF_8)
|
947
|
+
nil
|
948
|
+
end
|
949
|
+
end
|
950
|
+
end
|
951
|
+
)
|
899
952
|
when :cbor
|
900
953
|
ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
|
901
954
|
when :cborseq
|
@@ -1250,7 +1303,8 @@ module CDDL
|
|
1250
1303
|
BRACE = {"{" => :map, "[" => :array}
|
1251
1304
|
RANGE_EXCLUDE_END = {".." => false, "..." => true}
|
1252
1305
|
SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
|
1253
|
-
:default, :lt, :le, :gt, :ge, :eq, :ne,
|
1306
|
+
:default, :lt, :le, :gt, :ge, :eq, :ne,
|
1307
|
+
:feature, :abnf, :abnfb, :det, :cat, :plus]
|
1254
1308
|
|
1255
1309
|
def type1(n, canbegroup = false)
|
1256
1310
|
# puts "NVALUE #{n.value.inspect}"
|
@@ -0,0 +1,37 @@
|
|
1
|
+
start = [Tag0, Tag1004]
|
2
|
+
|
3
|
+
; for draft-ietf-cbor-date-tag
|
4
|
+
Tag1004 = #6.1004(text .abnf full-date)
|
5
|
+
; for RFC 7049
|
6
|
+
Tag0 = #6.0(text .abnf date-time)
|
7
|
+
|
8
|
+
full-date = "full-date" .cat rfc3339
|
9
|
+
date-time = "date-time" .cat rfc3339
|
10
|
+
|
11
|
+
; Note the trick of idiomatically starting with a newline, separating
|
12
|
+
; off the element in the .cat from the rule-list
|
13
|
+
rfc3339 = '
|
14
|
+
date-fullyear = 4DIGIT
|
15
|
+
date-month = 2DIGIT ; 01-12
|
16
|
+
date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on
|
17
|
+
; month/year
|
18
|
+
time-hour = 2DIGIT ; 00-23
|
19
|
+
time-minute = 2DIGIT ; 00-59
|
20
|
+
time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap sec
|
21
|
+
; rules
|
22
|
+
time-secfrac = "." 1*DIGIT
|
23
|
+
time-numoffset = ("+" / "-") time-hour ":" time-minute
|
24
|
+
time-offset = "Z" / time-numoffset
|
25
|
+
|
26
|
+
partial-time = time-hour ":" time-minute ":" time-second
|
27
|
+
[time-secfrac]
|
28
|
+
full-date = date-fullyear "-" date-month "-" date-mday
|
29
|
+
full-time = partial-time time-offset
|
30
|
+
|
31
|
+
date-time = full-date "T" full-time
|
32
|
+
' .cat rfc5234-core
|
33
|
+
|
34
|
+
rfc5234-core = '
|
35
|
+
DIGIT = %x30-39 ; 0-9
|
36
|
+
; abbreviated here
|
37
|
+
'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
start = [tt, tb, bt, bb]
|
2
|
+
|
3
|
+
|
4
|
+
tt = text .abnf '4DIGIT 1FOO
|
5
|
+
DIGIT = %x30-39 ; 0-9
|
6
|
+
FOO = %xc0-cf
|
7
|
+
'
|
8
|
+
tb = text .abnfb '4DIGIT 1FOO
|
9
|
+
DIGIT = %x30-39 ; 0-9
|
10
|
+
FOO = %xc0-cf
|
11
|
+
'
|
12
|
+
bt = bytes .abnf '4DIGIT 1FOO
|
13
|
+
DIGIT = %x30-39 ; 0-9
|
14
|
+
FOO = %xc0-cf
|
15
|
+
'
|
16
|
+
bb = bytes .abnfb '4DIGIT 1FOO
|
17
|
+
DIGIT = %x30-39 ; 0-9
|
18
|
+
FOO = %xc0-cf
|
19
|
+
'
|
20
|
+
|
21
|
+
; ["7408\xC6", "7073\xC3", h'30383131CD', h'32363738CD']
|
22
|
+
; ["5892\u00ca", "2145\u00c6", h'33333338C38B', h'31343033C388']
|
23
|
+
|
24
|
+
|
25
|
+
; ** ENCOED UTF-8
|
26
|
+
; ** ENCOED UTF-8
|
27
|
+
; ** ENCOED UTF-8
|
28
|
+
; ** ENCOED UTF-8
|
29
|
+
; ["5845\u00c6", "9329\u00cb", h'38393538C389', h'33343230C386']
|
30
|
+
|
31
|
+
|
32
|
+
; ["1066\u00cc", "9253\xC9", h'38333533C38A', h'32373337C4']
|
data/test-data/bat.cddl
ADDED
data/test-data/oid.cddl
ADDED
data/test-data/sasl.cddl
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
message = text .abnfb ("message" .cat rfc4505)
|
2
|
+
|
3
|
+
rfc4505 = '
|
4
|
+
message = [ email / token ]
|
5
|
+
;; to be prepared in accordance with Section 3
|
6
|
+
|
7
|
+
UTF1 = %x00-3F / %x41-7F ;; less "@" (U+0040)
|
8
|
+
UTF2 = %xC2-DF UTF0
|
9
|
+
UTF3 = %xE0 %xA0-BF UTF0 / %xE1-EC 2(UTF0) /
|
10
|
+
%xED %x80-9F UTF0 / %xEE-EF 2(UTF0)
|
11
|
+
UTF4 = %xF0 %x90-BF 2(UTF0) / %xF1-F3 3(UTF0) /
|
12
|
+
%xF4 %x80-8F 2(UTF0)
|
13
|
+
UTF0 = %x80-BF
|
14
|
+
|
15
|
+
TCHAR = UTF1 / UTF2 / UTF3 / UTF4
|
16
|
+
;; any UTF-8 encoded Unicode character
|
17
|
+
;; except "@" (U+0040)
|
18
|
+
|
19
|
+
email = "too@much.work"; for this example
|
20
|
+
;email = addr-spec
|
21
|
+
;; as defined in [IMAIL]
|
22
|
+
|
23
|
+
token = 1*255TCHAR
|
24
|
+
'
|
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.8.
|
4
|
+
version: 0.8.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carsten Bormann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cbor-diag
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: abnftt
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: regexp-examples
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,13 +114,18 @@ files:
|
|
100
114
|
- test-data/7807.cddl
|
101
115
|
- test-data/a.cddl
|
102
116
|
- test-data/abignum.cddl
|
117
|
+
- test-data/abnf1.cddl
|
118
|
+
- test-data/abnf2.cddl
|
119
|
+
- test-data/abnf3.cddl
|
103
120
|
- test-data/ambig.cddl
|
104
121
|
- test-data/b.cddl
|
105
122
|
- test-data/badaddr.cddl
|
106
123
|
- test-data/basic_syntax_example.cddl
|
124
|
+
- test-data/bat.cddl
|
107
125
|
- test-data/bpv7.cddl
|
108
126
|
- test-data/bpv7a.cddl
|
109
127
|
- test-data/bpv7b.cddl
|
128
|
+
- test-data/cat-re.cddl
|
110
129
|
- test-data/cdni-ct.cddl
|
111
130
|
- test-data/coral.cddl
|
112
131
|
- test-data/coral1.cddl
|
@@ -148,8 +167,11 @@ files:
|
|
148
167
|
- test-data/mon-val.cddl
|
149
168
|
- test-data/multipart-ct.cddl
|
150
169
|
- test-data/named-group.cddl
|
170
|
+
- test-data/oid.cddl
|
171
|
+
- test-data/oidbat.cddl
|
151
172
|
- test-data/patch1.cddl
|
152
173
|
- test-data/reused_named_group.cddl
|
174
|
+
- test-data/sasl.cddl
|
153
175
|
- test-data/sequence.cddl
|
154
176
|
- test-data/structure.cddl
|
155
177
|
- test-data/test-gen.cddl
|