cddl 0.10.3 → 0.12.14
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 +18 -2
- data/cddl.gemspec +7 -6
- data/data/cddl.abnf +29 -13
- data/lib/cddl.rb +349 -53
- data/test-data/b64u-strict.cddl +12 -0
- data/test-data/cat-re.cddl +2 -0
- data/test-data/catb64.cddl +8 -0
- data/test-data/decimal-warn.cddl +1 -0
- data/test-data/dotplus1.cddl +3 -0
- data/test-data/dotplus2.cddl +3 -0
- data/test-data/dotplus3.cddl +3 -0
- data/test-data/dotplus4.cddl +3 -0
- data/test-data/enum.cddl +14 -0
- data/test-data/enum1.cddl +12 -0
- data/test-data/json1.cddl +15 -0
- data/test-data/jwt.cddl +15 -0
- data/test-data/prim.cddl +7 -0
- data/test-data/printf.cddl +2 -0
- data/test-data/printf0.cddl +1 -0
- data/test-data/printf1.cddl +2 -0
- data/test-data/printf2.cddl +2 -0
- data/test-data/printf3.cddl +2 -0
- data/test-data/valemb.cddl +16 -0
- metadata +59 -17
- data/lib/base45_lite.rb +0 -71
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a4b5bfb31fd9b7fcf4cf66a1d0f2a76550c9682215c486d99a03997bab1ae30b
|
|
4
|
+
data.tar.gz: 97f11378fb18576f115ffb8cbd668fe9e14e33e91e4aac01d874c69e206f2fbd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 623f3945c3fff7c04dd2a4e1c77879d585d347092c87b54d5ead6b8fb3ed3c5ab68a58ae67b7f3f936437c8bc9f92dea6f8597509ba8913fbc5e2e47f43d398a
|
|
7
|
+
data.tar.gz: a04d3f282b0d42182f63dd66988fece8fb0ab7ddb4e159b2f8213705503cff0a97b622a172096b881dc4fe70f16bdcc48a51fa035413bc55421bb5e15d1bcda3
|
data/bin/cddl
CHANGED
|
@@ -7,10 +7,13 @@ require 'json'
|
|
|
7
7
|
|
|
8
8
|
Encoding.default_external = "UTF-8" # wake up, smell the coffee
|
|
9
9
|
|
|
10
|
+
CDDL_VERSION = Gem.loaded_specs["cddl"].version rescue "unknown-version"
|
|
11
|
+
|
|
10
12
|
EX_USAGE = 64
|
|
11
13
|
EX_DATAERR = 65
|
|
12
14
|
|
|
13
15
|
def usage
|
|
16
|
+
warn "cddl tool version #{CDDL_VERSION}"
|
|
14
17
|
warn "Usage:"
|
|
15
18
|
warn "#$0 spec.cddl generate [n]"
|
|
16
19
|
warn "#$0 spec.cddl json-generate [n]"
|
|
@@ -19,6 +22,13 @@ def usage
|
|
|
19
22
|
exit EX_USAGE
|
|
20
23
|
end
|
|
21
24
|
|
|
25
|
+
def utfify(s)
|
|
26
|
+
s.force_encoding(Encoding::UTF_8).scrub { |c|
|
|
27
|
+
warn "*** replaced invalid UTF-8 byte sequence #{c.inspect} by U+FFFD REPLACEMENT CHARACTER"
|
|
28
|
+
0xFFFD.chr(Encoding::UTF_8)
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
22
32
|
def read_arg(arg, remember_fn = true)
|
|
23
33
|
if arg == "-"
|
|
24
34
|
$fn = "(stdin)" if remember_fn
|
|
@@ -31,7 +41,7 @@ def read_arg(arg, remember_fn = true)
|
|
|
31
41
|
end
|
|
32
42
|
|
|
33
43
|
def parser
|
|
34
|
-
@parser ||= CDDL::Parser.new(read_arg(ARGV[0], false))
|
|
44
|
+
@parser ||= CDDL::Parser.new(utfify(read_arg(ARGV[0], false)))
|
|
35
45
|
end
|
|
36
46
|
|
|
37
47
|
def my_pp(v)
|
|
@@ -96,7 +106,12 @@ begin
|
|
|
96
106
|
instance = if $sequence
|
|
97
107
|
CBOR.decode("\x9f".b << instance.b << "\xff".b)
|
|
98
108
|
else
|
|
99
|
-
|
|
109
|
+
begin
|
|
110
|
+
CBOR.decode(instance.b)
|
|
111
|
+
rescue => e
|
|
112
|
+
warn e.inspect if verbose
|
|
113
|
+
JSON.load(utfify(instance))
|
|
114
|
+
end
|
|
100
115
|
end
|
|
101
116
|
instance = instance.cbor_clone if $annotate && ENV["EXPERIMENTAL_ANNOTATE"]
|
|
102
117
|
warn "#{fn}:" if verbose
|
|
@@ -104,6 +119,7 @@ begin
|
|
|
104
119
|
# my_pp ann
|
|
105
120
|
instance.cbor_add_annotations_from(ann) rescue nil
|
|
106
121
|
my_diag(instance) if $annotate
|
|
122
|
+
warn "ann: #{!!ann}" if verbose
|
|
107
123
|
unless ann
|
|
108
124
|
retcode = 1
|
|
109
125
|
end
|
data/cddl.gemspec
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
|
2
2
|
s.name = 'cddl'
|
|
3
|
-
s.version = '0.
|
|
3
|
+
s.version = '0.12.14'
|
|
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
|
-
s.add_dependency('abnc')
|
|
7
|
+
s.add_dependency('abnc', '~> 0.1.1')
|
|
8
8
|
s.add_dependency('json_pure')
|
|
9
9
|
s.add_dependency('abnftt')
|
|
10
|
-
s.add_dependency('regexp-examples') # , '1.1.0')
|
|
10
|
+
s.add_dependency('regexp-examples', '~> 1.5.1') # , '1.1.0')
|
|
11
11
|
s.add_dependency('colorize')
|
|
12
12
|
s.add_dependency('base32', '~> 0.3')
|
|
13
|
+
s.add_dependency('base45_lite', '~> 1.0')
|
|
14
|
+
s.add_dependency('scanf', '~> 1.0')
|
|
13
15
|
s.files = `git ls-files`.split("\n").grep(/^[a-z]/)
|
|
14
16
|
s.files = Dir['lib/**/*.rb'] + %w(cddl.gemspec) + Dir['data/**/*.abnf'] + Dir['data/**/*.cddl'] + Dir['test-data/**/*.cddl'] + Dir['test/**/*.rb']
|
|
15
17
|
s.require_path = 'lib'
|
|
16
18
|
s.executables = ['cddl']
|
|
17
|
-
s.
|
|
18
|
-
s.required_ruby_version = '>= 2.0'
|
|
19
|
+
s.required_ruby_version = '>= 2.3'
|
|
19
20
|
s.author = "Carsten Bormann"
|
|
20
21
|
s.email = "cabo@tzi.org"
|
|
21
|
-
s.homepage = "
|
|
22
|
+
s.homepage = "https://www.rfc-editor.org/rfc/rfc8610#appendix-F"
|
|
22
23
|
s.license = 'MIT'
|
|
23
24
|
end
|
|
24
25
|
|
data/data/cddl.abnf
CHANGED
|
@@ -13,7 +13,8 @@ genericarg = "<" S type1 S *("," S type1 S ) ">"
|
|
|
13
13
|
type = type1 S *("/" S type1 S)
|
|
14
14
|
|
|
15
15
|
type1 = type2 [S (rangeop / annotator) S type2]
|
|
16
|
-
/ "#" "6" ["."
|
|
16
|
+
/ "#" "6" ["." headnumber] "(" S type S ")" ; note no space!
|
|
17
|
+
/ "#" "7" ["." headnumber] ; note no space!
|
|
17
18
|
/ "#" DIGIT ["." uint] ; major/ai
|
|
18
19
|
/ "#" ; any
|
|
19
20
|
/ "~" S typename [genericarg]
|
|
@@ -22,6 +23,8 @@ type1 = type2 [S (rangeop / annotator) S type2]
|
|
|
22
23
|
/ "&" S "(" S group S ")"
|
|
23
24
|
/ "&" S groupname [genericarg]
|
|
24
25
|
|
|
26
|
+
headnumber = uint / ("<" type ">")
|
|
27
|
+
|
|
25
28
|
type2 = value
|
|
26
29
|
/ typename [genericarg]
|
|
27
30
|
/ "(" type ")"
|
|
@@ -38,7 +41,7 @@ grpent = [occur S] [memberkey S] type optcom
|
|
|
38
41
|
/ [occur S] groupname [genericarg] optcom ; preempted by above
|
|
39
42
|
/ [occur S] "(" S group S ")" optcom
|
|
40
43
|
|
|
41
|
-
memberkey = type1 S "=>"
|
|
44
|
+
memberkey = type1 S ["^" S] "=>"
|
|
42
45
|
/ bareword S ":"
|
|
43
46
|
/ value S ":"
|
|
44
47
|
|
|
@@ -62,32 +65,45 @@ value = number
|
|
|
62
65
|
int = ["-"] uint
|
|
63
66
|
|
|
64
67
|
; This is a float if it has fraction or exponent; int otherwise
|
|
65
|
-
number = int ["." fraction] ["e" exponent ]
|
|
68
|
+
number = hexfloat / (int ["." fraction] ["e" exponent ])
|
|
69
|
+
hexfloat = ["-"] "0x" 1*HEXDIG ["." 1*HEXDIG] "p" exponent
|
|
66
70
|
fraction = 1*DIGIT
|
|
67
|
-
exponent =
|
|
71
|
+
exponent = ["+"/"-"] 1*DIGIT
|
|
68
72
|
|
|
69
73
|
text = %x22 *SCHAR %x22
|
|
70
|
-
SCHAR = %x20-21 / %x23-7E / SESC
|
|
71
|
-
|
|
74
|
+
SCHAR = %x20-21 / %x23-5B / %x5D-7E / NONASCII / SESC
|
|
75
|
+
|
|
76
|
+
SESC = "\" ( %x22 / "/" / "\" / ; \" \/ \\
|
|
77
|
+
%x62 / %x66 / %x6E / %x72 / %x74 / ; \b \f \n \r \t
|
|
78
|
+
(%x75 hexchar) ) ; \uXXXX
|
|
79
|
+
|
|
80
|
+
hexchar = "{" (1*"0" [ hexscalar ] / hexscalar) "}" /
|
|
81
|
+
non-surrogate / (high-surrogate "\" %x75 low-surrogate)
|
|
82
|
+
non-surrogate = ((DIGIT / "A"/"B"/"C" / "E"/"F") HEXDIG HEXDIG HEXDIG) /
|
|
83
|
+
("D" %x30-37 HEXDIG HEXDIG)
|
|
84
|
+
high-surrogate = "D" ("8"/"9"/"A"/"B") HEXDIG HEXDIG
|
|
85
|
+
low-surrogate = "D" ("C"/"D"/"E"/"F") HEXDIG HEXDIG
|
|
86
|
+
hexscalar = "10" HEXDIG HEXDIG HEXDIG HEXDIG / HEXDIG1 HEXDIG HEXDIG HEXDIG HEXDIG
|
|
87
|
+
/ non-surrogate / HEXDIG [HEXDIG [HEXDIG]]
|
|
72
88
|
|
|
73
89
|
bytes = [bsqual] %x27 *BCHAR %x27
|
|
74
|
-
BCHAR = %x20-26 / %x28-5B / %x5D-7E / SESC / CRLF
|
|
75
|
-
bsqual =
|
|
76
|
-
/ %x62.36.34 ; "b64"
|
|
90
|
+
BCHAR = %x20-26 / %x28-5B / %x5D-7E / NONASCII / SESC / "\'" / CRLF
|
|
91
|
+
bsqual = "h" / "b64"
|
|
77
92
|
|
|
78
93
|
id = EALPHA *(*("-" / ".") (EALPHA / DIGIT))
|
|
79
94
|
ALPHA = %x41-5A / %x61-7A
|
|
80
|
-
EALPHA =
|
|
95
|
+
EALPHA = ALPHA / "@" / "_" / "$"
|
|
81
96
|
DIGIT = %x30-39
|
|
82
97
|
DIGIT1 = %x31-39
|
|
83
98
|
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
|
|
99
|
+
HEXDIG1 = DIGIT1 / "A" / "B" / "C" / "D" / "E" / "F"
|
|
84
100
|
BINDIG = %x30-31
|
|
85
101
|
|
|
86
102
|
S = *WS
|
|
87
103
|
WS = SP / NL
|
|
88
104
|
SP = %x20
|
|
89
105
|
NL = COMMENT / CRLF
|
|
90
|
-
COMMENT = ";" *
|
|
91
|
-
|
|
106
|
+
COMMENT = ";" *PCHAR CRLF
|
|
107
|
+
PCHAR = %x20-7E / NONASCII
|
|
108
|
+
NONASCII = %xA0-D7FF / %xE000-10FFFD
|
|
92
109
|
CRLF = %x0A / %x0D.0A
|
|
93
|
-
|
data/lib/cddl.rb
CHANGED
|
@@ -2,6 +2,7 @@ require 'abnc'
|
|
|
2
2
|
require 'pp'
|
|
3
3
|
require 'pathname'
|
|
4
4
|
require 'cbor-pure' unless defined?(CBOR::Tagged)
|
|
5
|
+
require 'half'
|
|
5
6
|
require 'cbor-deterministic'
|
|
6
7
|
require 'regexp-examples'
|
|
7
8
|
require 'abnftt'
|
|
@@ -9,6 +10,7 @@ require 'colorize'
|
|
|
9
10
|
require 'base64'
|
|
10
11
|
require 'base32'
|
|
11
12
|
require 'base45_lite'
|
|
13
|
+
require 'scanf'
|
|
12
14
|
|
|
13
15
|
module CDDL
|
|
14
16
|
|
|
@@ -38,6 +40,7 @@ module CDDL
|
|
|
38
40
|
[{}, {}]
|
|
39
41
|
end
|
|
40
42
|
|
|
43
|
+
CDDL_UNUSED_OK = ENV["CDDL_UNUSED_OK"]
|
|
41
44
|
|
|
42
45
|
class BackTrack < Exception; end
|
|
43
46
|
|
|
@@ -59,7 +62,7 @@ module CDDL
|
|
|
59
62
|
if upto - presult < 100
|
|
60
63
|
part2 = source_text[presult...upto]
|
|
61
64
|
else
|
|
62
|
-
part2 = source_text[presult, 50] + "......." + source_text[upto-50, 50]
|
|
65
|
+
part2 = source_text[presult, 50] + "......." + (source_text[upto-50, 50] || "")
|
|
63
66
|
end
|
|
64
67
|
warn "*** Look for syntax problems around the #{
|
|
65
68
|
"%%%".colorize(background: :light_yellow)} markers:\n#{
|
|
@@ -116,6 +119,16 @@ module CDDL
|
|
|
116
119
|
r.compact
|
|
117
120
|
end
|
|
118
121
|
|
|
122
|
+
def longest_initial_match(old, now)
|
|
123
|
+
md = /\A(.*)(.*)\n\1(.*)\z/.match([old,now].join("\n"))
|
|
124
|
+
md[1..3]
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def diff_message(old, now)
|
|
128
|
+
c, l, r = longest_initial_match(old, now)
|
|
129
|
+
"-- common: >#{c}< -- old: >#{l}< -- new: >#{r}<"
|
|
130
|
+
end
|
|
131
|
+
|
|
119
132
|
def cname(s)
|
|
120
133
|
s.to_s.gsub(/-/, "_")
|
|
121
134
|
end
|
|
@@ -202,7 +215,8 @@ module CDDL
|
|
|
202
215
|
ids = g.children(:id).map(&:to_s)
|
|
203
216
|
# puts ["ids", ids].inspect
|
|
204
217
|
if b = @generics[n]
|
|
205
|
-
fail "Duplicate generics definition #{n}
|
|
218
|
+
fail "Duplicate generics definition #{n} #{
|
|
219
|
+
diff_message(strip_nodes(b[0]).inspect, strip_nodes(rule_ast).inspect)}"
|
|
206
220
|
end
|
|
207
221
|
@generics[n] = [rule_ast, ids]
|
|
208
222
|
else
|
|
@@ -214,7 +228,7 @@ module CDDL
|
|
|
214
228
|
if a == b
|
|
215
229
|
warn "*** Warning: Identical redefinition of #{n} as #{a}"
|
|
216
230
|
else
|
|
217
|
-
fail "Duplicate rule definition #{n}
|
|
231
|
+
fail "Duplicate rule definition #{n} #{diff_message(b, a)}"
|
|
218
232
|
end
|
|
219
233
|
end
|
|
220
234
|
@rules[n] = rule_ast
|
|
@@ -246,7 +260,7 @@ module CDDL
|
|
|
246
260
|
r_process("used_in_cddl_prelude", @rules["used_in_cddl_prelude"])
|
|
247
261
|
@rules.each do |n, r|
|
|
248
262
|
# r_process(n, r) # debug only loop
|
|
249
|
-
warn "*** Unused rule #{n}" unless @stage1[n]
|
|
263
|
+
warn "*** Unused rule #{n}" unless @stage1[n] || CDDL_UNUSED_OK
|
|
250
264
|
end
|
|
251
265
|
if result[0] == :grpent
|
|
252
266
|
warn "Group at top -- first rule must be a type!"
|
|
@@ -300,6 +314,12 @@ module CDDL
|
|
|
300
314
|
abnfb: Encoding::BINARY
|
|
301
315
|
}
|
|
302
316
|
|
|
317
|
+
def myfrand(exp)
|
|
318
|
+
exprange = 1 << exp
|
|
319
|
+
expoffset= exprange >> 1
|
|
320
|
+
(rand(2)*2-1) * rand() * 2.0**(rand(exprange)-expoffset)
|
|
321
|
+
end
|
|
322
|
+
|
|
303
323
|
def generate
|
|
304
324
|
@recursion = 0
|
|
305
325
|
generate1(rules)
|
|
@@ -422,9 +442,17 @@ module CDDL
|
|
|
422
442
|
when 3
|
|
423
443
|
gen_word
|
|
424
444
|
when 6
|
|
425
|
-
|
|
445
|
+
tn = Integer === where[2] ? where[2] : generate1(where[2])
|
|
446
|
+
unless Integer === tn && tn >= 0
|
|
447
|
+
fail "Can't generate a tag number out of #{where[2]}"
|
|
448
|
+
end
|
|
449
|
+
CBOR::Tagged.new(tn, generate1(where[3]))
|
|
426
450
|
when 7
|
|
427
|
-
|
|
451
|
+
w2 = where[2]
|
|
452
|
+
if Array === w2
|
|
453
|
+
w2 = generate1(w2)
|
|
454
|
+
end
|
|
455
|
+
case w2
|
|
428
456
|
when nil
|
|
429
457
|
Math::PI
|
|
430
458
|
when 20
|
|
@@ -433,10 +461,22 @@ module CDDL
|
|
|
433
461
|
true
|
|
434
462
|
when 22
|
|
435
463
|
nil
|
|
436
|
-
when 23
|
|
437
|
-
|
|
438
|
-
when 25
|
|
439
|
-
|
|
464
|
+
when 0..19, 23, 32..255
|
|
465
|
+
CBOR::Simple.new(w2)
|
|
466
|
+
when 25
|
|
467
|
+
while !(hs = Half.encode_from_single_bytes([myfrand(5)].pack("g")))
|
|
468
|
+
end
|
|
469
|
+
Half.decode(hs)
|
|
470
|
+
when 26
|
|
471
|
+
while (a = [myfrand(8)].pack("g").unpack("g").first).to_cbor.size != 5
|
|
472
|
+
end
|
|
473
|
+
a
|
|
474
|
+
when 27
|
|
475
|
+
while (a = myfrand(11)).to_cbor.size != 9
|
|
476
|
+
end
|
|
477
|
+
a
|
|
478
|
+
else
|
|
479
|
+
fail "Can't generate prim #7.#{where[2].inspect}" # XXX retry array generate
|
|
440
480
|
end
|
|
441
481
|
else
|
|
442
482
|
fail "Can't generate prim #{where[1]}"
|
|
@@ -551,8 +591,7 @@ module CDDL
|
|
|
551
591
|
warn "HUH gen #{where.inspect} #{try.inspect}" unless try.nil?
|
|
552
592
|
end
|
|
553
593
|
end
|
|
554
|
-
|
|
555
|
-
content = generate1(target)
|
|
594
|
+
try_generate(target) do |content|
|
|
556
595
|
if validate1(content, where)
|
|
557
596
|
return content
|
|
558
597
|
end
|
|
@@ -598,29 +637,35 @@ module CDDL
|
|
|
598
637
|
end
|
|
599
638
|
content = JSON::dump(generate1(control))
|
|
600
639
|
content
|
|
601
|
-
when :decimal
|
|
640
|
+
when :decimal, :base10
|
|
641
|
+
if conop == :decimal
|
|
642
|
+
unless @decimal_warned
|
|
643
|
+
warn "** .decimal control operator is now called .base10"
|
|
644
|
+
@decimal_warned = true
|
|
645
|
+
end
|
|
646
|
+
end
|
|
602
647
|
unless target == [:prim, 3]
|
|
603
648
|
fail "Don't know yet how to generate #{where}"
|
|
604
649
|
end
|
|
605
650
|
content = Integer(generate1(control)).to_s
|
|
606
651
|
content
|
|
607
652
|
when :join
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
653
|
+
try_generate(control) do |content|
|
|
654
|
+
if Array === content &&
|
|
655
|
+
content.all? {|x| String === x} &&
|
|
656
|
+
Set[content.map {|x| x.encoding}].size == 1
|
|
657
|
+
content = content.join
|
|
658
|
+
if validate1(content, target)
|
|
659
|
+
return content
|
|
660
|
+
end
|
|
661
|
+
end
|
|
614
662
|
end
|
|
615
|
-
|
|
616
|
-
content
|
|
663
|
+
fail "Don't know yet how to generate #{where}"
|
|
617
664
|
when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
|
618
665
|
:b45, :b32, :h32, :hex, :hexlc, :hexuc
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
end
|
|
623
|
-
content = case conop
|
|
666
|
+
try_generate(control) do |content|
|
|
667
|
+
if String === content
|
|
668
|
+
content = case conop
|
|
624
669
|
when :b64u, :"b64u-sloppy"
|
|
625
670
|
Base64.urlsafe_encode64(content, padding: false)
|
|
626
671
|
when :b64c, :"b64c-sloppy"
|
|
@@ -639,10 +684,33 @@ module CDDL
|
|
|
639
684
|
content.unpack("H*")[0]
|
|
640
685
|
else fail "Cannot happen"
|
|
641
686
|
end
|
|
642
|
-
|
|
687
|
+
if validate1(content, target)
|
|
688
|
+
return content
|
|
689
|
+
end
|
|
690
|
+
end
|
|
691
|
+
end
|
|
692
|
+
fail "Not smart enough to generate #{where}"
|
|
693
|
+
when :printf
|
|
694
|
+
try_generate(control) do |content|
|
|
695
|
+
if Array === content && content.size >= 1
|
|
696
|
+
fmt, *data = content
|
|
697
|
+
if String === fmt
|
|
698
|
+
begin
|
|
699
|
+
content = fmt % data
|
|
700
|
+
if validate1(content, target)
|
|
701
|
+
return content
|
|
702
|
+
end
|
|
703
|
+
rescue ArgumentError => e
|
|
704
|
+
# be verbose about mismatches here
|
|
705
|
+
@last_message << "\n** #{fmt.inspect} ArgumentError #{e}"
|
|
706
|
+
end
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
fail "Not smart enough to generate #{where}#{@last_message}"
|
|
643
711
|
when :within, :and
|
|
644
|
-
|
|
645
|
-
|
|
712
|
+
try_generate(target) do |content|
|
|
713
|
+
$features ||= Hash.new {|h, k| h[k] = {}}
|
|
646
714
|
if validate1(content, control)
|
|
647
715
|
return content
|
|
648
716
|
elsif conop == :within
|
|
@@ -670,22 +738,41 @@ module CDDL
|
|
|
670
738
|
end
|
|
671
739
|
end
|
|
672
740
|
|
|
741
|
+
def try_generate(target)
|
|
742
|
+
32.times do
|
|
743
|
+
content = generate1(target)
|
|
744
|
+
yield content # should return if success
|
|
745
|
+
end
|
|
746
|
+
end
|
|
747
|
+
|
|
673
748
|
VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
|
|
674
749
|
SIMPLE_VALUE = {
|
|
675
750
|
[:prim, 7, 20] => [true, false, :bool],
|
|
676
751
|
[:prim, 7, 21] => [true, true, :bool],
|
|
677
752
|
[:prim, 7, 22] => [true, nil, :nil],
|
|
678
|
-
[:prim, 7, 23] => [true, :undefined, :undefined],
|
|
679
753
|
}
|
|
754
|
+
SIMPLE_VALUE_SIMPLE = Set[23] + (0..19) + (32..255)
|
|
680
755
|
|
|
681
756
|
def extract_value(t) # []
|
|
682
757
|
if vt = VALUE_TYPE[t[0]]
|
|
683
758
|
[true, t[1], vt]
|
|
684
|
-
elsif
|
|
685
|
-
|
|
759
|
+
elsif t[0] == :prim && t[1] == 7
|
|
760
|
+
case t2 = t[2]
|
|
761
|
+
when Integer
|
|
762
|
+
when Array
|
|
763
|
+
a, b, c = extract_value(t2)
|
|
764
|
+
if a && c == Integer
|
|
765
|
+
t2 = b
|
|
766
|
+
end
|
|
767
|
+
end
|
|
768
|
+
if v = SIMPLE_VALUE[[:prim, 7, t2]]
|
|
769
|
+
v
|
|
770
|
+
elsif SIMPLE_VALUE_SIMPLE === t2
|
|
771
|
+
[true, CBOR::Simple.new(t2), :simple]
|
|
772
|
+
end
|
|
686
773
|
elsif t[0] == :anno
|
|
687
774
|
_, conop, target, control = t
|
|
688
|
-
|
|
775
|
+
warn ["EXV0", conop, target, control].inspect if ENV["CDDL_TRACE"]
|
|
689
776
|
if conop == :cat || conop == :plus || conop == :det
|
|
690
777
|
ok1, v1, vt1 = extract_value(target)
|
|
691
778
|
ok2, v2, vt2 = extract_value(control)
|
|
@@ -717,6 +804,19 @@ module CDDL
|
|
|
717
804
|
}]
|
|
718
805
|
end
|
|
719
806
|
|
|
807
|
+
|
|
808
|
+
def extract_arg0(t)
|
|
809
|
+
return [false] unless t[0] == :array
|
|
810
|
+
[true,
|
|
811
|
+
(el = t[1]
|
|
812
|
+
return [false] unless el[0..3] == [:member, 1, 1, nil]
|
|
813
|
+
ok, v, vt = extract_value(el[4])
|
|
814
|
+
return [false] unless ok
|
|
815
|
+
[v, vt]
|
|
816
|
+
),
|
|
817
|
+
*t[2..-1]]
|
|
818
|
+
end
|
|
819
|
+
|
|
720
820
|
def extract_feature(control, d)
|
|
721
821
|
ok, v, vt = extract_value(control)
|
|
722
822
|
if ok
|
|
@@ -905,6 +1005,19 @@ module CDDL
|
|
|
905
1005
|
}
|
|
906
1006
|
end
|
|
907
1007
|
|
|
1008
|
+
def validate1a_ignore_encoding(d, where)
|
|
1009
|
+
if String === d
|
|
1010
|
+
validate1a(d.force_encoding(Encoding::BINARY), where) or (
|
|
1011
|
+
text = d.force_encoding(Encoding::UTF_8).scrub {
|
|
1012
|
+
fail "can't use bytes as text"
|
|
1013
|
+
} rescue :NOT_A_TEXT_STRING
|
|
1014
|
+
validate1a(text, where)
|
|
1015
|
+
)
|
|
1016
|
+
else
|
|
1017
|
+
validate1a(d, where)
|
|
1018
|
+
end
|
|
1019
|
+
end
|
|
1020
|
+
|
|
908
1021
|
def validate1a(d, where)
|
|
909
1022
|
if ann = validate1(d, where)
|
|
910
1023
|
here = [d, where]
|
|
@@ -917,6 +1030,8 @@ module CDDL
|
|
|
917
1030
|
end
|
|
918
1031
|
|
|
919
1032
|
OPERATORS = {lt: :<, le: :<=, gt: :>, ge: :>=, eq: :==, ne: :!=}
|
|
1033
|
+
OPERATORS_MATCH = {eq: true, ne: false}
|
|
1034
|
+
FLOAT_AI_FROM_SIZE = {3 => 25, 5 => 26, 9 => 27}
|
|
920
1035
|
|
|
921
1036
|
def validate1(d, where)
|
|
922
1037
|
if ENV["CDDL_TRACE"]
|
|
@@ -927,6 +1042,9 @@ module CDDL
|
|
|
927
1042
|
@last_data = d
|
|
928
1043
|
@last_rule = where
|
|
929
1044
|
ann = nil
|
|
1045
|
+
if CBOR::Tagged === d && d.tag === 888 && ENV["CDDL_888"]
|
|
1046
|
+
return []
|
|
1047
|
+
end
|
|
930
1048
|
case where[0]
|
|
931
1049
|
when :type1
|
|
932
1050
|
if where[1..-1].any? {|r| ann = validate1a(d, r)}
|
|
@@ -963,7 +1081,7 @@ module CDDL
|
|
|
963
1081
|
if conop == :cat || conop == :plus || conop == :det
|
|
964
1082
|
ok1, v1, vt1 = extract_value(target)
|
|
965
1083
|
ok2, v2, vt2 = extract_value(control)
|
|
966
|
-
|
|
1084
|
+
warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
|
|
967
1085
|
if ok1 && ok2
|
|
968
1086
|
v2 = Integer(v2) if vt1 == Integer
|
|
969
1087
|
if conop == :det
|
|
@@ -972,6 +1090,30 @@ module CDDL
|
|
|
972
1090
|
end
|
|
973
1091
|
# warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
|
|
974
1092
|
[] if d == v1 + v2 # XXX Focus ArgumentError
|
|
1093
|
+
elsif conop == :cat && String === d
|
|
1094
|
+
warn ["CAT-L", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
|
|
1095
|
+
if ok1 && vt1 == String
|
|
1096
|
+
# d and lhs (v1) need to agree in encoding
|
|
1097
|
+
if d.encoding == v1.encoding
|
|
1098
|
+
if d[0...v1.length] == v1
|
|
1099
|
+
d2 = d[v1.length..-1]
|
|
1100
|
+
warn ["CAT-L1", d2, d2.encoding, control].inspect if ENV["CDDL_TRACE"]
|
|
1101
|
+
validate1a_ignore_encoding(d2, control)
|
|
1102
|
+
end
|
|
1103
|
+
end
|
|
1104
|
+
elsif ok2 && vt2 == String
|
|
1105
|
+
warn ["CAT-R", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
|
|
1106
|
+
if d[-v2.length..-1] == v2
|
|
1107
|
+
d1 = d[0...-v2.length]
|
|
1108
|
+
validate1a(d1, control)
|
|
1109
|
+
end
|
|
1110
|
+
end
|
|
1111
|
+
elsif conop == :plus && Integer === d
|
|
1112
|
+
if ok1 && vt1 == Integer
|
|
1113
|
+
validate1a(d - Integer(v1), control)
|
|
1114
|
+
elsif ok2 && vt2 == Integer
|
|
1115
|
+
validate1a(d - Integer(v2), target)
|
|
1116
|
+
end
|
|
975
1117
|
end
|
|
976
1118
|
elsif ann = validate1a(d, target)
|
|
977
1119
|
case conop
|
|
@@ -1022,6 +1164,11 @@ module CDDL
|
|
|
1022
1164
|
ok, v, _vt = extract_value(control)
|
|
1023
1165
|
if ok
|
|
1024
1166
|
ann if d.send(op, v) rescue nil # XXX Focus ArgumentError
|
|
1167
|
+
else
|
|
1168
|
+
needs_to_match = OPERATORS_MATCH[conop]
|
|
1169
|
+
unless needs_to_match.nil?
|
|
1170
|
+
ann if !!validate1(d, control) == needs_to_match
|
|
1171
|
+
end
|
|
1025
1172
|
end
|
|
1026
1173
|
when :regexp
|
|
1027
1174
|
ann if (
|
|
@@ -1074,21 +1221,89 @@ module CDDL
|
|
|
1074
1221
|
end
|
|
1075
1222
|
when :json
|
|
1076
1223
|
ann if validate1((JSON::load(d) rescue :BAD_JSON), control)
|
|
1077
|
-
when :decimal
|
|
1224
|
+
when :decimal, :base10
|
|
1225
|
+
if conop == :decimal
|
|
1226
|
+
unless @decimal_warned
|
|
1227
|
+
warn "** .decimal control operator is now called .base10"
|
|
1228
|
+
@decimal_warned = true
|
|
1229
|
+
end
|
|
1230
|
+
end
|
|
1231
|
+
|
|
1078
1232
|
ann if (
|
|
1079
1233
|
if /\A0|-?[1-9][0-9]*\z/ === d
|
|
1080
1234
|
validate1((d.to_i rescue :BAD_JSON), control)
|
|
1081
1235
|
end
|
|
1082
1236
|
)
|
|
1083
1237
|
when :join
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1238
|
+
t = control
|
|
1239
|
+
v = if t[0] == :array
|
|
1240
|
+
t[1..-1].map { |el|
|
|
1241
|
+
if el[0..2] == [:member, 1, 1]
|
|
1242
|
+
ok, v, vt = extract_value(el[4])
|
|
1243
|
+
if ok
|
|
1244
|
+
[true, v, vt]
|
|
1245
|
+
else
|
|
1246
|
+
[false, el[4]]
|
|
1247
|
+
end
|
|
1248
|
+
end
|
|
1249
|
+
}
|
|
1250
|
+
end
|
|
1251
|
+
warn "@@@JOIN@@@ #{v.inspect}" if ENV["CDDL_TRACE"]
|
|
1252
|
+
ok = true
|
|
1253
|
+
if v
|
|
1254
|
+
ix = 0
|
|
1255
|
+
rest = d.dup
|
|
1256
|
+
while ix < v.length
|
|
1257
|
+
if left = v[ix]
|
|
1258
|
+
if left[0] # match constant value first
|
|
1259
|
+
fail "Not a string for #{left.inspect} in #{where}" unless String == left[2]
|
|
1260
|
+
want = left[1]
|
|
1261
|
+
have = rest[0...left[1].length]
|
|
1262
|
+
if want == have
|
|
1263
|
+
rest[0...left[1].length] = ''
|
|
1264
|
+
ix += 1
|
|
1265
|
+
next
|
|
1266
|
+
else
|
|
1267
|
+
fail ".join: want #{want.inspect}, have #{have.inspect}"
|
|
1268
|
+
end
|
|
1269
|
+
else
|
|
1270
|
+
ix += 1
|
|
1271
|
+
if ix == v.length # match remaining
|
|
1272
|
+
warn "@@@JOIN ok in #{ok.inspect} rest #{rest.inspect}" if ENV["CDDL_TRACE"]
|
|
1273
|
+
ok &&= validate1(rest, left[1])
|
|
1274
|
+
warn "@@@JOIN ok out #{ok.inspect}" if ENV["CDDL_TRACE"]
|
|
1275
|
+
# more diag
|
|
1276
|
+
rest = ''
|
|
1277
|
+
next
|
|
1278
|
+
else
|
|
1279
|
+
if mid = v[ix]
|
|
1280
|
+
if mid[0] # have constant value to split over
|
|
1281
|
+
fail "Not a string for #{mid} in #{where}" unless String == mid[2]
|
|
1282
|
+
rest1, rest2 = rest.split(mid[1], 2)
|
|
1283
|
+
if rest2
|
|
1284
|
+
warn "@@@JOIN ok in #{ok.inspect} rest1 #{rest1.inspect}" if ENV["CDDL_TRACE"]
|
|
1285
|
+
ok &&= validate1(rest1, left[1])
|
|
1286
|
+
warn "@@@JOIN ok out #{ok.inspect}" if ENV["CDDL_TRACE"]
|
|
1287
|
+
rest = rest2
|
|
1288
|
+
ix += 1
|
|
1289
|
+
next
|
|
1290
|
+
else
|
|
1291
|
+
fail "Can't find #{mid[1].inspect} in #{rest.inspect}"
|
|
1292
|
+
end
|
|
1293
|
+
else
|
|
1294
|
+
fail "Cannot validate consecutive non-constant members of .join in #{where}"
|
|
1295
|
+
end
|
|
1296
|
+
else
|
|
1297
|
+
fail "Cannot handle .join over #{t[ix+1]} in #{where}"
|
|
1298
|
+
end
|
|
1299
|
+
end
|
|
1300
|
+
end
|
|
1301
|
+
else
|
|
1302
|
+
fail "Cannot handle .join over #{t[ix+1]} in #{where}"
|
|
1303
|
+
end
|
|
1304
|
+
end
|
|
1305
|
+
fail "Can't match #{rest.inspect} for .join in #{where}" if rest != ''
|
|
1306
|
+
ann if ok
|
|
1092
1307
|
else
|
|
1093
1308
|
fail "Don't know yet how to validate against #{where}"
|
|
1094
1309
|
end
|
|
@@ -1097,7 +1312,7 @@ module CDDL
|
|
|
1097
1312
|
String === d && (
|
|
1098
1313
|
decoded = case conop
|
|
1099
1314
|
when :b64u
|
|
1100
|
-
|
|
1315
|
+
/[+\/=]/ !~ d &&
|
|
1101
1316
|
Base64.urlsafe_decode64(d)
|
|
1102
1317
|
when :"b64u-sloppy"
|
|
1103
1318
|
/[-_=]/ !~ d &&
|
|
@@ -1126,6 +1341,21 @@ module CDDL
|
|
|
1126
1341
|
end
|
|
1127
1342
|
) && validate1(decoded.b, control)
|
|
1128
1343
|
)
|
|
1344
|
+
when :printf
|
|
1345
|
+
ann if String === d && (
|
|
1346
|
+
ok, fmt, *v = extract_arg0(control)
|
|
1347
|
+
if ok && String == fmt[1]
|
|
1348
|
+
fmt = fmt[0]
|
|
1349
|
+
# warn "** ok #{ok.inspect} fmt #{fmt.inspect} v #{v.inspect}"
|
|
1350
|
+
decoded = d.scanf(fmt) # this is a bit too lenient, so let's do:
|
|
1351
|
+
encode_again = fmt % decoded
|
|
1352
|
+
if encode_again != d
|
|
1353
|
+
warn "** fmt #{fmt.inspect} d #{d.inspect} decoded #{decoded.inspect} encode_again #{encode_again.inspect}"
|
|
1354
|
+
else
|
|
1355
|
+
validate1(decoded, [:array, *v])
|
|
1356
|
+
end
|
|
1357
|
+
end
|
|
1358
|
+
)
|
|
1129
1359
|
when :within
|
|
1130
1360
|
if validate1(d, control)
|
|
1131
1361
|
ann
|
|
@@ -1161,20 +1391,35 @@ module CDDL
|
|
|
1161
1391
|
end
|
|
1162
1392
|
d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
|
|
1163
1393
|
end
|
|
1164
|
-
CBOR::Tagged === d &&
|
|
1394
|
+
CBOR::Tagged === d && (
|
|
1395
|
+
Integer === where[2] ? d.tag == where[2] : validate1a(d.tag, where[2])
|
|
1396
|
+
) && validate1a(d.data, where[3])
|
|
1165
1397
|
when 7
|
|
1166
1398
|
t, v = extract_value(where)
|
|
1167
1399
|
if t
|
|
1168
1400
|
v.eql? d
|
|
1169
1401
|
else
|
|
1170
|
-
case where[2]
|
|
1402
|
+
case w2 = where[2]
|
|
1171
1403
|
when nil
|
|
1172
|
-
|
|
1173
|
-
|
|
1404
|
+
Float === d || CBOR::Simple === d || [false, true, nil].include?(d)
|
|
1405
|
+
when Array
|
|
1406
|
+
headnum = case d
|
|
1407
|
+
when Float
|
|
1408
|
+
FLOAT_AI_FROM_SIZE[d.to_cbor.size]
|
|
1409
|
+
when false
|
|
1410
|
+
20
|
|
1411
|
+
when true
|
|
1412
|
+
21
|
|
1413
|
+
when nil
|
|
1414
|
+
22
|
|
1415
|
+
when CBOR::Simple
|
|
1416
|
+
d.value
|
|
1417
|
+
end
|
|
1418
|
+
validate1a(headnum, w2)
|
|
1174
1419
|
when 25, 26, 27
|
|
1175
|
-
Float === d
|
|
1420
|
+
Float === d && FLOAT_AI_FROM_SIZE[d.to_cbor.size] == w2
|
|
1176
1421
|
else
|
|
1177
|
-
fail
|
|
1422
|
+
fail [:val7, d, where].inspect
|
|
1178
1423
|
end
|
|
1179
1424
|
end
|
|
1180
1425
|
else
|
|
@@ -1224,6 +1469,10 @@ module CDDL
|
|
|
1224
1469
|
else
|
|
1225
1470
|
[:type1]
|
|
1226
1471
|
end
|
|
1472
|
+
elsif s = ENV["CDDL_INVENT"]
|
|
1473
|
+
s = "_" if s == ""
|
|
1474
|
+
r = [:type1, [:text, "#{s}-#{name}"]]
|
|
1475
|
+
return r
|
|
1227
1476
|
end
|
|
1228
1477
|
end
|
|
1229
1478
|
if r
|
|
@@ -1269,6 +1518,18 @@ module CDDL
|
|
|
1269
1518
|
end
|
|
1270
1519
|
end
|
|
1271
1520
|
|
|
1521
|
+
STRING_ESCAPES = {
|
|
1522
|
+
"\"" => "\"",
|
|
1523
|
+
"/" => "/",
|
|
1524
|
+
"\\" => "\\",
|
|
1525
|
+
"'" => "'",
|
|
1526
|
+
"b" => "\b",
|
|
1527
|
+
"f" => "\f",
|
|
1528
|
+
"n" => "\n",
|
|
1529
|
+
"r" => "\r",
|
|
1530
|
+
"t" => "\t",
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1272
1533
|
def value(n)
|
|
1273
1534
|
# cheat:
|
|
1274
1535
|
# warn n
|
|
@@ -1278,7 +1539,20 @@ module CDDL
|
|
|
1278
1539
|
if parts[-1] != ""
|
|
1279
1540
|
warn "*** Problem decoding byte string #{s.inspect}"
|
|
1280
1541
|
end
|
|
1281
|
-
bsval = parts[0...-1].join("'").gsub(/\\(
|
|
1542
|
+
bsval = parts[0...-1].join("'").gsub(/\\u([Dd][89AaBb][0-9a-zA-Z]{2})\\u([Dd][CcDdEeFf][0-9a-zA-Z]{2})|\\u([0-9a-zA-Z]{4})|\\u\{([0-9a-zA-Z]+)\}|\r?(\n)|\\([^u])/) {
|
|
1543
|
+
if hex = $3 || $4
|
|
1544
|
+
hex.to_i(16).chr(Encoding::UTF_8)
|
|
1545
|
+
elsif lf = $5
|
|
1546
|
+
lf
|
|
1547
|
+
elsif escaped = $6
|
|
1548
|
+
STRING_ESCAPES[$6] or (
|
|
1549
|
+
fail "Invalid String Escape #{escaped.inspect} in #{s.inspect}"
|
|
1550
|
+
)
|
|
1551
|
+
else
|
|
1552
|
+
((($1.to_i(16) & 0x3ff) << 10) +
|
|
1553
|
+
($2.to_i(16) & 0x3ff) + 0x10000).chr(Encoding::UTF_8)
|
|
1554
|
+
end
|
|
1555
|
+
}
|
|
1282
1556
|
[:bytes,
|
|
1283
1557
|
case bsqual
|
|
1284
1558
|
when ""
|
|
@@ -1292,7 +1566,21 @@ module CDDL
|
|
|
1292
1566
|
end
|
|
1293
1567
|
]
|
|
1294
1568
|
else
|
|
1295
|
-
|
|
1569
|
+
if s[-1] == '"'
|
|
1570
|
+
s.gsub!(/\\u([Dd][89AaBb][0-9a-zA-Z]{2})\\u([Dd][CcDdEeFf][0-9a-zA-Z]{2})|\\([^u]|u[0-9a-zA-Z]{4})/) {
|
|
1571
|
+
if $3
|
|
1572
|
+
"\\#$3" # skip this, use eval parser
|
|
1573
|
+
else
|
|
1574
|
+
((($1.to_i(16) & 0x3ff) << 10) +
|
|
1575
|
+
($2.to_i(16) & 0x3ff) + 0x10000).chr(Encoding::UTF_8)
|
|
1576
|
+
end
|
|
1577
|
+
}
|
|
1578
|
+
end
|
|
1579
|
+
if s =~ /p.*\d\z/ # hexfloat
|
|
1580
|
+
val = s.scanf("%a").first
|
|
1581
|
+
else
|
|
1582
|
+
val = eval(s)
|
|
1583
|
+
end
|
|
1296
1584
|
# warn val
|
|
1297
1585
|
case val
|
|
1298
1586
|
when Integer; [:int, val]
|
|
@@ -1485,9 +1773,10 @@ module CDDL
|
|
|
1485
1773
|
:within, :and,
|
|
1486
1774
|
:default, :lt, :le, :gt, :ge, :eq, :ne,
|
|
1487
1775
|
:feature, :abnf, :abnfb, :det, :cat, :plus,
|
|
1488
|
-
:json, :decimal, :join,
|
|
1776
|
+
:json, :decimal, :base10, :join,
|
|
1489
1777
|
:b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
|
1490
1778
|
:b45, :b32, :h32, :hex, :hexlc, :hexuc,
|
|
1779
|
+
:printf,
|
|
1491
1780
|
]
|
|
1492
1781
|
|
|
1493
1782
|
def type1(n, canbegroup = false)
|
|
@@ -1520,6 +1809,13 @@ module CDDL
|
|
|
1520
1809
|
when /\A#(\d+)/
|
|
1521
1810
|
maj = $1.to_i
|
|
1522
1811
|
s = [:prim, maj, *n.children(:uint).map(&:to_s).map(&:to_i)]
|
|
1812
|
+
if tn = n.headnumber
|
|
1813
|
+
if ui = tn.uint
|
|
1814
|
+
s << ui.to_s.to_i
|
|
1815
|
+
elsif tt = tn.type
|
|
1816
|
+
s << type(tt)
|
|
1817
|
+
end
|
|
1818
|
+
end
|
|
1523
1819
|
if tagged_type = n.type
|
|
1524
1820
|
s << type(tagged_type)
|
|
1525
1821
|
end
|
data/test-data/cat-re.cddl
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
s = [text .decimal 4711, text .base10 4712]
|
data/test-data/enum.cddl
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
terminal-color = &basecolors
|
|
2
|
+
basecolors = (
|
|
3
|
+
black: 0, red: 1, green: 2, yellow: 3,
|
|
4
|
+
blue: 4, magenta: 5, cyan: 6, white: 7,
|
|
5
|
+
reserved: (8..255) .feature "extension"
|
|
6
|
+
)
|
|
7
|
+
; extended-color = &(
|
|
8
|
+
; basecolors,
|
|
9
|
+
; orange: 8, pink: 9, purple: 10, brown: 11,
|
|
10
|
+
; )
|
|
11
|
+
|
|
12
|
+
;;gp 10
|
|
13
|
+
;;vp 42
|
|
14
|
+
;;vp 433
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
terminal-color = $terminal-color / text .feature "extension"
|
|
2
|
+
$terminal-color /= &basecolors
|
|
3
|
+
basecolors = (
|
|
4
|
+
black: "black", red: "red", green: "green",
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
pastelcolors = ( pink: "pink", mauve: "mauve", peach: "peach", lavender: "lavender" )
|
|
8
|
+
$terminal-color /= &pastelcolors
|
|
9
|
+
|
|
10
|
+
;;gp 10
|
|
11
|
+
;;vp "florp"
|
|
12
|
+
;;vp "lavender"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
; JWT-JWS = text .join ([
|
|
2
|
+
; b64u<jwt-headers>, ".",
|
|
3
|
+
; b64u<jwt-payload>, ".",
|
|
4
|
+
; b64u<jwt-signature>])
|
|
5
|
+
; ; a = jwt-headers
|
|
6
|
+
; ; a = b64u<"abc"> ; fails
|
|
7
|
+
; ; a = b64u<'abc'> ; succeeds
|
|
8
|
+
; b64u<B> = text .b64u B
|
|
9
|
+
jwt-headers = '' .cat jwt-headers1
|
|
10
|
+
jwt-headers1 = text .json jwt-headermap
|
|
11
|
+
jwt-headermap = { * text => any } ; simplified
|
|
12
|
+
jwt-payload = bytes
|
|
13
|
+
jwt-signature = bytes
|
|
14
|
+
|
|
15
|
+
;;gp 10
|
data/test-data/jwt.cddl
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
JWT-JWS = text .join ([
|
|
2
|
+
b64u<jwt-headers>, ".",
|
|
3
|
+
b64u<jwt-payload>, ".",
|
|
4
|
+
b64u<jwt-signature>])
|
|
5
|
+
; a = jwt-headers
|
|
6
|
+
; a = b64u<"abc"> ; fails
|
|
7
|
+
; a = b64u<'abc'> ; succeeds
|
|
8
|
+
b64u<B> = text .b64u B
|
|
9
|
+
jwt-headers = '' .cat jwt-headers1
|
|
10
|
+
jwt-headers1 = text .json jwt-headermap
|
|
11
|
+
jwt-headermap = { * text => any } ; simplified
|
|
12
|
+
jwt-payload = bytes
|
|
13
|
+
jwt-signature = bytes
|
|
14
|
+
|
|
15
|
+
;;gp 10
|
data/test-data/prim.cddl
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
my_label = text .printf (["0x%x: %a", 4711, 81.5])
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
cwt = [
|
|
2
|
+
bstr .cbor protected-map,
|
|
3
|
+
unprotected-map,
|
|
4
|
+
bstr .cbor payload-map,
|
|
5
|
+
bstr ; signature
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
protected-map = {
|
|
9
|
+
&(alg: 1) => int,
|
|
10
|
+
? &(typ: 16) => text,
|
|
11
|
+
* key => any
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
unprotected-map = ()
|
|
15
|
+
key = "key"
|
|
16
|
+
payload-map = { payload: "map"}
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cddl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.14
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Carsten Bormann
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: cbor-diag
|
|
@@ -28,16 +27,16 @@ dependencies:
|
|
|
28
27
|
name: abnc
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
30
29
|
requirements:
|
|
31
|
-
- - "
|
|
30
|
+
- - "~>"
|
|
32
31
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
32
|
+
version: 0.1.1
|
|
34
33
|
type: :runtime
|
|
35
34
|
prerelease: false
|
|
36
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
36
|
requirements:
|
|
38
|
-
- - "
|
|
37
|
+
- - "~>"
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
39
|
+
version: 0.1.1
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
41
|
name: json_pure
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -70,16 +69,16 @@ dependencies:
|
|
|
70
69
|
name: regexp-examples
|
|
71
70
|
requirement: !ruby/object:Gem::Requirement
|
|
72
71
|
requirements:
|
|
73
|
-
- - "
|
|
72
|
+
- - "~>"
|
|
74
73
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
74
|
+
version: 1.5.1
|
|
76
75
|
type: :runtime
|
|
77
76
|
prerelease: false
|
|
78
77
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
78
|
requirements:
|
|
80
|
-
- - "
|
|
79
|
+
- - "~>"
|
|
81
80
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
81
|
+
version: 1.5.1
|
|
83
82
|
- !ruby/object:Gem::Dependency
|
|
84
83
|
name: colorize
|
|
85
84
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +107,34 @@ dependencies:
|
|
|
108
107
|
- - "~>"
|
|
109
108
|
- !ruby/object:Gem::Version
|
|
110
109
|
version: '0.3'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: base45_lite
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '1.0'
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '1.0'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: scanf
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '1.0'
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '1.0'
|
|
111
138
|
description: A parser, generator, and validator for CDDL
|
|
112
139
|
email: cabo@tzi.org
|
|
113
140
|
executables:
|
|
@@ -119,7 +146,6 @@ files:
|
|
|
119
146
|
- cddl.gemspec
|
|
120
147
|
- data/cddl.abnf
|
|
121
148
|
- data/prelude.cddl
|
|
122
|
-
- lib/base45_lite.rb
|
|
123
149
|
- lib/cbor-pp-play.rb
|
|
124
150
|
- lib/cbor-pp.rb
|
|
125
151
|
- lib/cddl.rb
|
|
@@ -136,6 +162,7 @@ files:
|
|
|
136
162
|
- test-data/b.cddl
|
|
137
163
|
- test-data/b64c-sloppy.cddl
|
|
138
164
|
- test-data/b64c.cddl
|
|
165
|
+
- test-data/b64u-strict.cddl
|
|
139
166
|
- test-data/b64u.cddl
|
|
140
167
|
- test-data/badaddr.cddl
|
|
141
168
|
- test-data/base32.cddl
|
|
@@ -146,6 +173,7 @@ files:
|
|
|
146
173
|
- test-data/bpv7a.cddl
|
|
147
174
|
- test-data/bpv7b.cddl
|
|
148
175
|
- test-data/cat-re.cddl
|
|
176
|
+
- test-data/catb64.cddl
|
|
149
177
|
- test-data/cdni-ct.cddl
|
|
150
178
|
- test-data/complex-occ.cddl
|
|
151
179
|
- test-data/coral.cddl
|
|
@@ -155,10 +183,17 @@ files:
|
|
|
155
183
|
- test-data/cose.cddl
|
|
156
184
|
- test-data/dcaf.cddl
|
|
157
185
|
- test-data/dcaf1.cddl
|
|
186
|
+
- test-data/decimal-warn.cddl
|
|
158
187
|
- test-data/decimal.cddl
|
|
159
188
|
- test-data/decimal2.cddl
|
|
160
189
|
- test-data/det1.cddl
|
|
190
|
+
- test-data/dotplus1.cddl
|
|
191
|
+
- test-data/dotplus2.cddl
|
|
192
|
+
- test-data/dotplus3.cddl
|
|
193
|
+
- test-data/dotplus4.cddl
|
|
161
194
|
- test-data/dotsize.cddl
|
|
195
|
+
- test-data/enum.cddl
|
|
196
|
+
- test-data/enum1.cddl
|
|
162
197
|
- test-data/extractor-demo.cddl
|
|
163
198
|
- test-data/feat1.cddl
|
|
164
199
|
- test-data/feature-controller.cddl
|
|
@@ -186,8 +221,10 @@ files:
|
|
|
186
221
|
- test-data/joini.cddl
|
|
187
222
|
- test-data/joinx.cddl
|
|
188
223
|
- test-data/json.cddl
|
|
224
|
+
- test-data/json1.cddl
|
|
189
225
|
- test-data/json2.cddl
|
|
190
226
|
- test-data/jsoniodef.cddl
|
|
227
|
+
- test-data/jwt.cddl
|
|
191
228
|
- test-data/kevin5.cddl
|
|
192
229
|
- test-data/lint1.cddl
|
|
193
230
|
- test-data/map-group.cddl
|
|
@@ -208,6 +245,12 @@ files:
|
|
|
208
245
|
- test-data/oidbat.cddl
|
|
209
246
|
- test-data/patch1.cddl
|
|
210
247
|
- test-data/plus.cddl
|
|
248
|
+
- test-data/prim.cddl
|
|
249
|
+
- test-data/printf.cddl
|
|
250
|
+
- test-data/printf0.cddl
|
|
251
|
+
- test-data/printf1.cddl
|
|
252
|
+
- test-data/printf2.cddl
|
|
253
|
+
- test-data/printf3.cddl
|
|
211
254
|
- test-data/reused_named_group.cddl
|
|
212
255
|
- test-data/sasl.cddl
|
|
213
256
|
- test-data/sequence.cddl
|
|
@@ -220,6 +263,7 @@ files:
|
|
|
220
263
|
- test-data/toerless0.cddl
|
|
221
264
|
- test-data/toerless1.cddl
|
|
222
265
|
- test-data/two_anonymous_groups.cddl
|
|
266
|
+
- test-data/valemb.cddl
|
|
223
267
|
- test-data/wrong1.cddl
|
|
224
268
|
- test-data/wrong1a.cddl
|
|
225
269
|
- test-data/wrong2.cddl
|
|
@@ -228,11 +272,10 @@ files:
|
|
|
228
272
|
- test-data/yangid.cddl
|
|
229
273
|
- test-data/yaron1.cddl
|
|
230
274
|
- test/test-cddl.rb
|
|
231
|
-
homepage:
|
|
275
|
+
homepage: https://www.rfc-editor.org/rfc/rfc8610#appendix-F
|
|
232
276
|
licenses:
|
|
233
277
|
- MIT
|
|
234
278
|
metadata: {}
|
|
235
|
-
post_install_message:
|
|
236
279
|
rdoc_options: []
|
|
237
280
|
require_paths:
|
|
238
281
|
- lib
|
|
@@ -240,15 +283,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
240
283
|
requirements:
|
|
241
284
|
- - ">="
|
|
242
285
|
- !ruby/object:Gem::Version
|
|
243
|
-
version: '2.
|
|
286
|
+
version: '2.3'
|
|
244
287
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
245
288
|
requirements:
|
|
246
289
|
- - ">="
|
|
247
290
|
- !ruby/object:Gem::Version
|
|
248
291
|
version: '0'
|
|
249
292
|
requirements: []
|
|
250
|
-
rubygems_version:
|
|
251
|
-
signing_key:
|
|
293
|
+
rubygems_version: 4.0.8
|
|
252
294
|
specification_version: 4
|
|
253
295
|
summary: CDDL generator and validator.
|
|
254
296
|
test_files: []
|
data/lib/base45_lite.rb
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright (c) 2022 Weihang Jian <https://tonytonyjan.net>
|
|
4
|
-
#
|
|
5
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
# in the Software without restriction, including without limitation the rights
|
|
8
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
# furnished to do so, subject to the following conditions:
|
|
11
|
-
#
|
|
12
|
-
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
# copies or substantial portions of the Software.
|
|
14
|
-
#
|
|
15
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
# SOFTWARE.
|
|
22
|
-
|
|
23
|
-
# An implementation of draft-faltstrom-base45-10, see
|
|
24
|
-
# https://datatracker.ietf.org/doc/draft-faltstrom-base45/
|
|
25
|
-
module Base45Lite
|
|
26
|
-
class Error < ::StandardError; end
|
|
27
|
-
class OverflowError < Error; end
|
|
28
|
-
class InvalidCharacterError < Error; end
|
|
29
|
-
class ForbiddenLengthError < Error; end
|
|
30
|
-
|
|
31
|
-
MAX_UINT18 = 2**16 - 1
|
|
32
|
-
SQUARED_45 = 45**2
|
|
33
|
-
MAPPING = [
|
|
34
|
-
*'0'..'9',
|
|
35
|
-
*'A'..'Z',
|
|
36
|
-
' ', '$', '%', '*', '+', '-', '.', '/', ':'
|
|
37
|
-
].map!.with_index { |x, i| [i, x] }.to_h.freeze
|
|
38
|
-
REVERSE_MAPPING = MAPPING.invert.freeze
|
|
39
|
-
|
|
40
|
-
def self.encode(input)
|
|
41
|
-
sequence = []
|
|
42
|
-
input.unpack('n*').map! do |uint16|
|
|
43
|
-
i, c = uint16.divmod(45)
|
|
44
|
-
i, d = i.divmod(45)
|
|
45
|
-
_, e = i.divmod(45)
|
|
46
|
-
sequence.push(c, d, e)
|
|
47
|
-
end
|
|
48
|
-
if input.bytesize.odd?
|
|
49
|
-
i, c = input.getbyte(-1).divmod(45)
|
|
50
|
-
_, d = i.divmod(45)
|
|
51
|
-
sequence.push(c, d)
|
|
52
|
-
end
|
|
53
|
-
sequence.map!{ |n| MAPPING[n] }.join
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def self.decode(input)
|
|
57
|
-
input
|
|
58
|
-
.chars.map! { |c| REVERSE_MAPPING[c] || raise(InvalidCharacterError) }
|
|
59
|
-
.each_slice(3).map do |slice|
|
|
60
|
-
c, d, e = slice
|
|
61
|
-
raise ForbiddenLengthError if d.nil?
|
|
62
|
-
|
|
63
|
-
sum = c + d * 45
|
|
64
|
-
sum += e * SQUARED_45 if e
|
|
65
|
-
raise OverflowError if sum > MAX_UINT18
|
|
66
|
-
|
|
67
|
-
sum
|
|
68
|
-
end
|
|
69
|
-
.pack((input.length % 3).zero? ? 'n*' : "n#{input.length / 3}C")
|
|
70
|
-
end
|
|
71
|
-
end
|