cddl 0.10.3 → 0.11.5
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 +3 -0
- data/cddl.gemspec +5 -3
- data/data/cddl.abnf +4 -1
- data/lib/cddl.rb +256 -44
- data/test-data/b64u-strict.cddl +10 -0
- data/test-data/cat-re.cddl +2 -0
- data/test-data/catb64.cddl +8 -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
- metadata +52 -9
- 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: 652f1e63847fbed19fceeca1ed0b695b25b5f8aa6d312b2bd17f21c0ac7c6549
|
|
4
|
+
data.tar.gz: d55f4a0bff69a37b1c6101b11eb003eb93c00df24ede1dded8d7be9844b4afb1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6622daf044d0f5a6d0ce4fe90ac57341526f7723aef0ce49e228edd2284711a44302ab0c3a1a28e3e156676db61afb4477a9b97b27269e1509034c41796ca8b9
|
|
7
|
+
data.tar.gz: 966fd633edc283925e0e4bbb5ca04cb40de60470044bbbd94e7df41fb05c185f59ff09ae4767d5dea2899491d3f82db50d3feb01a585fe03891d60f073e50557
|
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]"
|
data/cddl.gemspec
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
|
2
2
|
s.name = 'cddl'
|
|
3
|
-
s.version = '0.
|
|
3
|
+
s.version = '0.11.5'
|
|
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
10
|
s.add_dependency('regexp-examples') # , '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
19
|
s.default_executable = 'cddl'
|
|
18
|
-
s.required_ruby_version = '>= 2.
|
|
20
|
+
s.required_ruby_version = '>= 2.3'
|
|
19
21
|
s.author = "Carsten Bormann"
|
|
20
22
|
s.email = "cabo@tzi.org"
|
|
21
23
|
s.homepage = "http://github.com/cabo/cddl"
|
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 ")"
|
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
|
|
|
@@ -422,9 +424,17 @@ module CDDL
|
|
|
422
424
|
when 3
|
|
423
425
|
gen_word
|
|
424
426
|
when 6
|
|
425
|
-
|
|
427
|
+
tn = Integer === where[2] ? where[2] : generate1(where[2])
|
|
428
|
+
unless Integer === tn && tn >= 0
|
|
429
|
+
fail "Can't generate a tag number out of #{where[2]}"
|
|
430
|
+
end
|
|
431
|
+
CBOR::Tagged.new(tn, generate1(where[3]))
|
|
426
432
|
when 7
|
|
427
|
-
|
|
433
|
+
w2 = where[2]
|
|
434
|
+
if Array === w2
|
|
435
|
+
w2 = generate1(w2)
|
|
436
|
+
end
|
|
437
|
+
case w2
|
|
428
438
|
when nil
|
|
429
439
|
Math::PI
|
|
430
440
|
when 20
|
|
@@ -433,10 +443,22 @@ module CDDL
|
|
|
433
443
|
true
|
|
434
444
|
when 22
|
|
435
445
|
nil
|
|
436
|
-
when 23
|
|
437
|
-
|
|
438
|
-
when 25
|
|
439
|
-
rand()
|
|
446
|
+
when 0..19, 23, 32..255
|
|
447
|
+
CBOR::Simple.new(w2)
|
|
448
|
+
when 25
|
|
449
|
+
while !(hs = Half.encode_from_single_bytes([rand()].pack("g")))
|
|
450
|
+
end
|
|
451
|
+
Half.decode(hs)
|
|
452
|
+
when 26
|
|
453
|
+
while (a = [rand()].pack("g").unpack("g").first).to_cbor.size != 5
|
|
454
|
+
end
|
|
455
|
+
a
|
|
456
|
+
when 27
|
|
457
|
+
while (a = rand()).to_cbor.size != 9
|
|
458
|
+
end
|
|
459
|
+
a
|
|
460
|
+
else
|
|
461
|
+
fail "Can't generate prim #7.#{where[2].inspect}" # XXX retry array generate
|
|
440
462
|
end
|
|
441
463
|
else
|
|
442
464
|
fail "Can't generate prim #{where[1]}"
|
|
@@ -551,8 +573,7 @@ module CDDL
|
|
|
551
573
|
warn "HUH gen #{where.inspect} #{try.inspect}" unless try.nil?
|
|
552
574
|
end
|
|
553
575
|
end
|
|
554
|
-
|
|
555
|
-
content = generate1(target)
|
|
576
|
+
try_generate(target) do |content|
|
|
556
577
|
if validate1(content, where)
|
|
557
578
|
return content
|
|
558
579
|
end
|
|
@@ -605,22 +626,22 @@ module CDDL
|
|
|
605
626
|
content = Integer(generate1(control)).to_s
|
|
606
627
|
content
|
|
607
628
|
when :join
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
629
|
+
try_generate(control) do |content|
|
|
630
|
+
if Array === content &&
|
|
631
|
+
content.all? {|x| String === x} &&
|
|
632
|
+
Set[content.map {|x| x.encoding}].size == 1
|
|
633
|
+
content = content.join
|
|
634
|
+
if validate1(content, target)
|
|
635
|
+
return content
|
|
636
|
+
end
|
|
637
|
+
end
|
|
614
638
|
end
|
|
615
|
-
|
|
616
|
-
content
|
|
639
|
+
fail "Don't know yet how to generate #{where}"
|
|
617
640
|
when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
|
618
641
|
:b45, :b32, :h32, :hex, :hexlc, :hexuc
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
end
|
|
623
|
-
content = case conop
|
|
642
|
+
try_generate(control) do |content|
|
|
643
|
+
if String === content
|
|
644
|
+
content = case conop
|
|
624
645
|
when :b64u, :"b64u-sloppy"
|
|
625
646
|
Base64.urlsafe_encode64(content, padding: false)
|
|
626
647
|
when :b64c, :"b64c-sloppy"
|
|
@@ -639,10 +660,32 @@ module CDDL
|
|
|
639
660
|
content.unpack("H*")[0]
|
|
640
661
|
else fail "Cannot happen"
|
|
641
662
|
end
|
|
642
|
-
|
|
663
|
+
if validate1(content, target)
|
|
664
|
+
return content
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
end
|
|
668
|
+
fail "Not smart enough to generate #{where}"
|
|
669
|
+
when :printf
|
|
670
|
+
try_generate(control) do |content|
|
|
671
|
+
if Array === content && content.size >= 1
|
|
672
|
+
fmt, *data = content
|
|
673
|
+
if String === fmt
|
|
674
|
+
begin
|
|
675
|
+
content = fmt % data
|
|
676
|
+
if validate1(content, target)
|
|
677
|
+
return content
|
|
678
|
+
end
|
|
679
|
+
rescue ArgumentError => e
|
|
680
|
+
# be verbose about mismatches here
|
|
681
|
+
@last_message << "\n** #{fmt.inspect} ArgumentError #{e}"
|
|
682
|
+
end
|
|
683
|
+
end
|
|
684
|
+
end
|
|
685
|
+
end
|
|
686
|
+
fail "Not smart enough to generate #{where}#{@last_message}"
|
|
643
687
|
when :within, :and
|
|
644
|
-
|
|
645
|
-
content = generate1(target)
|
|
688
|
+
try_generate(target) do |content|
|
|
646
689
|
if validate1(content, control)
|
|
647
690
|
return content
|
|
648
691
|
elsif conop == :within
|
|
@@ -670,22 +713,41 @@ module CDDL
|
|
|
670
713
|
end
|
|
671
714
|
end
|
|
672
715
|
|
|
716
|
+
def try_generate(target)
|
|
717
|
+
32.times do
|
|
718
|
+
content = generate1(target)
|
|
719
|
+
yield content # should return if success
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
|
|
673
723
|
VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
|
|
674
724
|
SIMPLE_VALUE = {
|
|
675
725
|
[:prim, 7, 20] => [true, false, :bool],
|
|
676
726
|
[:prim, 7, 21] => [true, true, :bool],
|
|
677
727
|
[:prim, 7, 22] => [true, nil, :nil],
|
|
678
|
-
[:prim, 7, 23] => [true, :undefined, :undefined],
|
|
679
728
|
}
|
|
729
|
+
SIMPLE_VALUE_SIMPLE = Set[23] + (0..19) + (32..255)
|
|
680
730
|
|
|
681
731
|
def extract_value(t) # []
|
|
682
732
|
if vt = VALUE_TYPE[t[0]]
|
|
683
733
|
[true, t[1], vt]
|
|
684
|
-
elsif
|
|
685
|
-
|
|
734
|
+
elsif t[0] == :prim && t[1] == 7
|
|
735
|
+
case t2 = t[2]
|
|
736
|
+
when Integer
|
|
737
|
+
when Array
|
|
738
|
+
a, b, c = extract_value(t2)
|
|
739
|
+
if a && c == Integer
|
|
740
|
+
t2 = b
|
|
741
|
+
end
|
|
742
|
+
end
|
|
743
|
+
if v = SIMPLE_VALUE[[:prim, 7, t2]]
|
|
744
|
+
v
|
|
745
|
+
elsif SIMPLE_VALUE_SIMPLE === t2
|
|
746
|
+
[true, CBOR::Simple.new(t2), :simple]
|
|
747
|
+
end
|
|
686
748
|
elsif t[0] == :anno
|
|
687
749
|
_, conop, target, control = t
|
|
688
|
-
|
|
750
|
+
warn ["EXV0", conop, target, control].inspect if ENV["CDDL_TRACE"]
|
|
689
751
|
if conop == :cat || conop == :plus || conop == :det
|
|
690
752
|
ok1, v1, vt1 = extract_value(target)
|
|
691
753
|
ok2, v2, vt2 = extract_value(control)
|
|
@@ -717,6 +779,19 @@ module CDDL
|
|
|
717
779
|
}]
|
|
718
780
|
end
|
|
719
781
|
|
|
782
|
+
|
|
783
|
+
def extract_arg0(t)
|
|
784
|
+
return [false] unless t[0] == :array
|
|
785
|
+
[true,
|
|
786
|
+
(el = t[1]
|
|
787
|
+
return [false] unless el[0..3] == [:member, 1, 1, nil]
|
|
788
|
+
ok, v, vt = extract_value(el[4])
|
|
789
|
+
return [false] unless ok
|
|
790
|
+
[v, vt]
|
|
791
|
+
),
|
|
792
|
+
*t[2..-1]]
|
|
793
|
+
end
|
|
794
|
+
|
|
720
795
|
def extract_feature(control, d)
|
|
721
796
|
ok, v, vt = extract_value(control)
|
|
722
797
|
if ok
|
|
@@ -905,6 +980,19 @@ module CDDL
|
|
|
905
980
|
}
|
|
906
981
|
end
|
|
907
982
|
|
|
983
|
+
def validate1a_ignore_encoding(d, where)
|
|
984
|
+
if String === d
|
|
985
|
+
validate1a(d.force_encoding(Encoding::BINARY), where) or (
|
|
986
|
+
text = d.force_encoding(Encoding::UTF_8).scrub {
|
|
987
|
+
fail "can't use bytes as text"
|
|
988
|
+
} rescue :NOT_A_TEXT_STRING
|
|
989
|
+
validate1a(text, where)
|
|
990
|
+
)
|
|
991
|
+
else
|
|
992
|
+
validate1a(d, where)
|
|
993
|
+
end
|
|
994
|
+
end
|
|
995
|
+
|
|
908
996
|
def validate1a(d, where)
|
|
909
997
|
if ann = validate1(d, where)
|
|
910
998
|
here = [d, where]
|
|
@@ -917,6 +1005,7 @@ module CDDL
|
|
|
917
1005
|
end
|
|
918
1006
|
|
|
919
1007
|
OPERATORS = {lt: :<, le: :<=, gt: :>, ge: :>=, eq: :==, ne: :!=}
|
|
1008
|
+
FLOAT_AI_FROM_SIZE = {3 => 25, 5 => 26, 9 => 27}
|
|
920
1009
|
|
|
921
1010
|
def validate1(d, where)
|
|
922
1011
|
if ENV["CDDL_TRACE"]
|
|
@@ -963,7 +1052,7 @@ module CDDL
|
|
|
963
1052
|
if conop == :cat || conop == :plus || conop == :det
|
|
964
1053
|
ok1, v1, vt1 = extract_value(target)
|
|
965
1054
|
ok2, v2, vt2 = extract_value(control)
|
|
966
|
-
|
|
1055
|
+
warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
|
|
967
1056
|
if ok1 && ok2
|
|
968
1057
|
v2 = Integer(v2) if vt1 == Integer
|
|
969
1058
|
if conop == :det
|
|
@@ -972,6 +1061,30 @@ module CDDL
|
|
|
972
1061
|
end
|
|
973
1062
|
# warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
|
|
974
1063
|
[] if d == v1 + v2 # XXX Focus ArgumentError
|
|
1064
|
+
elsif conop == :cat && String === d
|
|
1065
|
+
warn ["CAT-L", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
|
|
1066
|
+
if ok1 && vt1 == String
|
|
1067
|
+
# d and lhs (v1) need to agree in encoding
|
|
1068
|
+
if d.encoding == v1.encoding
|
|
1069
|
+
if d[0...v1.length] == v1
|
|
1070
|
+
d2 = d[v1.length..-1]
|
|
1071
|
+
warn ["CAT-L1", d2, d2.encoding, control].inspect if ENV["CDDL_TRACE"]
|
|
1072
|
+
validate1a_ignore_encoding(d2, control)
|
|
1073
|
+
end
|
|
1074
|
+
end
|
|
1075
|
+
elsif ok2 && vt2 == String
|
|
1076
|
+
warn ["CAT-R", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
|
|
1077
|
+
if d[-v2.length..-1] == v2
|
|
1078
|
+
d1 = d[0...-v2.length]
|
|
1079
|
+
validate1a(d1, control)
|
|
1080
|
+
end
|
|
1081
|
+
end
|
|
1082
|
+
elsif conop == :plus && Integer === d
|
|
1083
|
+
if ok1 && vt1 == Integer
|
|
1084
|
+
validate1a(d - Integer(v1), control)
|
|
1085
|
+
elsif ok2 && vt2 == Integer
|
|
1086
|
+
validate1a(d - Integer(v2), target)
|
|
1087
|
+
end
|
|
975
1088
|
end
|
|
976
1089
|
elsif ann = validate1a(d, target)
|
|
977
1090
|
case conop
|
|
@@ -1081,14 +1194,75 @@ module CDDL
|
|
|
1081
1194
|
end
|
|
1082
1195
|
)
|
|
1083
1196
|
when :join
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1197
|
+
t = control
|
|
1198
|
+
v = if t[0] == :array
|
|
1199
|
+
t[1..-1].map { |el|
|
|
1200
|
+
if el[0..2] == [:member, 1, 1]
|
|
1201
|
+
ok, v, vt = extract_value(el[4])
|
|
1202
|
+
if ok
|
|
1203
|
+
[true, v, vt]
|
|
1204
|
+
else
|
|
1205
|
+
[false, el[4]]
|
|
1206
|
+
end
|
|
1207
|
+
end
|
|
1208
|
+
}
|
|
1209
|
+
end
|
|
1210
|
+
warn "@@@JOIN@@@ #{v.inspect}" if ENV["CDDL_TRACE"]
|
|
1211
|
+
ok = true
|
|
1212
|
+
if v
|
|
1213
|
+
ix = 0
|
|
1214
|
+
rest = d.dup
|
|
1215
|
+
while ix < v.length
|
|
1216
|
+
if left = v[ix]
|
|
1217
|
+
if left[0] # match constant value first
|
|
1218
|
+
fail "Not a string for #{left.inspect} in #{where}" unless String == left[2]
|
|
1219
|
+
want = left[1]
|
|
1220
|
+
have = rest[0...left[1].length]
|
|
1221
|
+
if want == have
|
|
1222
|
+
rest[0...left[1].length] = ''
|
|
1223
|
+
ix += 1
|
|
1224
|
+
next
|
|
1225
|
+
else
|
|
1226
|
+
fail ".join: want #{want.inspect}, have #{have.inspect}"
|
|
1227
|
+
end
|
|
1228
|
+
else
|
|
1229
|
+
ix += 1
|
|
1230
|
+
if ix == v.length # match remaining
|
|
1231
|
+
warn "@@@JOIN ok in #{ok.inspect} rest #{rest.inspect}" if ENV["CDDL_TRACE"]
|
|
1232
|
+
ok &&= validate1(rest, left[1])
|
|
1233
|
+
warn "@@@JOIN ok out #{ok.inspect}" if ENV["CDDL_TRACE"]
|
|
1234
|
+
# more diag
|
|
1235
|
+
rest = ''
|
|
1236
|
+
next
|
|
1237
|
+
else
|
|
1238
|
+
if mid = v[ix]
|
|
1239
|
+
if mid[0] # have constant value to split over
|
|
1240
|
+
fail "Not a string for #{mid} in #{where}" unless String == mid[2]
|
|
1241
|
+
rest1, rest2 = rest.split(mid[1], 2)
|
|
1242
|
+
if rest2
|
|
1243
|
+
warn "@@@JOIN ok in #{ok.inspect} rest1 #{rest1.inspect}" if ENV["CDDL_TRACE"]
|
|
1244
|
+
ok &&= validate1(rest1, left[1])
|
|
1245
|
+
warn "@@@JOIN ok out #{ok.inspect}" if ENV["CDDL_TRACE"]
|
|
1246
|
+
rest = rest2
|
|
1247
|
+
ix += 1
|
|
1248
|
+
next
|
|
1249
|
+
else
|
|
1250
|
+
fail "Can't find #{mid[1].inspect} in #{rest.inspect}"
|
|
1251
|
+
end
|
|
1252
|
+
else
|
|
1253
|
+
fail "Cannot validate consecutive non-constant members of .join in #{where}"
|
|
1254
|
+
end
|
|
1255
|
+
else
|
|
1256
|
+
fail "Cannot handle .join over #{t[ix+1]} in #{where}"
|
|
1257
|
+
end
|
|
1258
|
+
end
|
|
1259
|
+
end
|
|
1260
|
+
else
|
|
1261
|
+
fail "Cannot handle .join over #{t[ix+1]} in #{where}"
|
|
1262
|
+
end
|
|
1263
|
+
end
|
|
1264
|
+
fail "Can't match #{rest.inspect} for .join in #{where}" if rest != ''
|
|
1265
|
+
ann if ok
|
|
1092
1266
|
else
|
|
1093
1267
|
fail "Don't know yet how to validate against #{where}"
|
|
1094
1268
|
end
|
|
@@ -1097,7 +1271,7 @@ module CDDL
|
|
|
1097
1271
|
String === d && (
|
|
1098
1272
|
decoded = case conop
|
|
1099
1273
|
when :b64u
|
|
1100
|
-
|
|
1274
|
+
/[+\/=]/ !~ d &&
|
|
1101
1275
|
Base64.urlsafe_decode64(d)
|
|
1102
1276
|
when :"b64u-sloppy"
|
|
1103
1277
|
/[-_=]/ !~ d &&
|
|
@@ -1126,6 +1300,21 @@ module CDDL
|
|
|
1126
1300
|
end
|
|
1127
1301
|
) && validate1(decoded.b, control)
|
|
1128
1302
|
)
|
|
1303
|
+
when :printf
|
|
1304
|
+
ann if String === d && (
|
|
1305
|
+
ok, fmt, *v = extract_arg0(control)
|
|
1306
|
+
if ok && String == fmt[1]
|
|
1307
|
+
fmt = fmt[0]
|
|
1308
|
+
# warn "** ok #{ok.inspect} fmt #{fmt.inspect} v #{v.inspect}"
|
|
1309
|
+
decoded = d.scanf(fmt) # this is a bit too lenient, so let's do:
|
|
1310
|
+
encode_again = fmt % decoded
|
|
1311
|
+
if encode_again != d
|
|
1312
|
+
warn "** fmt #{fmt.inspect} d #{d.inspect} decoded #{decoded.inspect} encode_again #{encode_again.inspect}"
|
|
1313
|
+
else
|
|
1314
|
+
validate1(decoded, [:array, *v])
|
|
1315
|
+
end
|
|
1316
|
+
end
|
|
1317
|
+
)
|
|
1129
1318
|
when :within
|
|
1130
1319
|
if validate1(d, control)
|
|
1131
1320
|
ann
|
|
@@ -1161,20 +1350,35 @@ module CDDL
|
|
|
1161
1350
|
end
|
|
1162
1351
|
d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
|
|
1163
1352
|
end
|
|
1164
|
-
CBOR::Tagged === d &&
|
|
1353
|
+
CBOR::Tagged === d && (
|
|
1354
|
+
Integer === where[2] ? d.tag == where[2] : validate1a(d.tag, where[2])
|
|
1355
|
+
) && validate1a(d.data, where[3])
|
|
1165
1356
|
when 7
|
|
1166
1357
|
t, v = extract_value(where)
|
|
1167
1358
|
if t
|
|
1168
1359
|
v.eql? d
|
|
1169
1360
|
else
|
|
1170
|
-
case where[2]
|
|
1361
|
+
case w2 = where[2]
|
|
1171
1362
|
when nil
|
|
1172
|
-
|
|
1173
|
-
|
|
1363
|
+
Float === d || CBOR::Simple === d || [false, true, nil].include?(d)
|
|
1364
|
+
when Array
|
|
1365
|
+
headnum = case d
|
|
1366
|
+
when Float
|
|
1367
|
+
FLOAT_AI_FROM_SIZE[d.to_cbor.size]
|
|
1368
|
+
when false
|
|
1369
|
+
20
|
|
1370
|
+
when true
|
|
1371
|
+
21
|
|
1372
|
+
when nil
|
|
1373
|
+
22
|
|
1374
|
+
when CBOR::Simple
|
|
1375
|
+
d.value
|
|
1376
|
+
end
|
|
1377
|
+
validate1a(headnum, w2)
|
|
1174
1378
|
when 25, 26, 27
|
|
1175
|
-
Float === d
|
|
1379
|
+
Float === d && FLOAT_AI_FROM_SIZE[d.to_cbor.size] == w2
|
|
1176
1380
|
else
|
|
1177
|
-
fail
|
|
1381
|
+
fail [:val7, d, where].inspect
|
|
1178
1382
|
end
|
|
1179
1383
|
end
|
|
1180
1384
|
else
|
|
@@ -1488,6 +1692,7 @@ module CDDL
|
|
|
1488
1692
|
:json, :decimal, :join,
|
|
1489
1693
|
:b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
|
1490
1694
|
:b45, :b32, :h32, :hex, :hexlc, :hexuc,
|
|
1695
|
+
:printf,
|
|
1491
1696
|
]
|
|
1492
1697
|
|
|
1493
1698
|
def type1(n, canbegroup = false)
|
|
@@ -1520,6 +1725,13 @@ module CDDL
|
|
|
1520
1725
|
when /\A#(\d+)/
|
|
1521
1726
|
maj = $1.to_i
|
|
1522
1727
|
s = [:prim, maj, *n.children(:uint).map(&:to_s).map(&:to_i)]
|
|
1728
|
+
if tn = n.headnumber
|
|
1729
|
+
if ui = tn.uint
|
|
1730
|
+
s << ui.to_s.to_i
|
|
1731
|
+
elsif tt = tn.type
|
|
1732
|
+
s << type(tt)
|
|
1733
|
+
end
|
|
1734
|
+
end
|
|
1523
1735
|
if tagged_type = n.type
|
|
1524
1736
|
s << type(tagged_type)
|
|
1525
1737
|
end
|
data/test-data/cat-re.cddl
CHANGED
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])
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cddl
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.11.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Carsten Bormann
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-04-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cbor-diag
|
|
@@ -28,16 +28,16 @@ dependencies:
|
|
|
28
28
|
name: abnc
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version:
|
|
33
|
+
version: 0.1.1
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version:
|
|
40
|
+
version: 0.1.1
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: json_pure
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -108,6 +108,34 @@ dependencies:
|
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0.3'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: base45_lite
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '1.0'
|
|
118
|
+
type: :runtime
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '1.0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: scanf
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '1.0'
|
|
132
|
+
type: :runtime
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '1.0'
|
|
111
139
|
description: A parser, generator, and validator for CDDL
|
|
112
140
|
email: cabo@tzi.org
|
|
113
141
|
executables:
|
|
@@ -119,7 +147,6 @@ files:
|
|
|
119
147
|
- cddl.gemspec
|
|
120
148
|
- data/cddl.abnf
|
|
121
149
|
- data/prelude.cddl
|
|
122
|
-
- lib/base45_lite.rb
|
|
123
150
|
- lib/cbor-pp-play.rb
|
|
124
151
|
- lib/cbor-pp.rb
|
|
125
152
|
- lib/cddl.rb
|
|
@@ -136,6 +163,7 @@ files:
|
|
|
136
163
|
- test-data/b.cddl
|
|
137
164
|
- test-data/b64c-sloppy.cddl
|
|
138
165
|
- test-data/b64c.cddl
|
|
166
|
+
- test-data/b64u-strict.cddl
|
|
139
167
|
- test-data/b64u.cddl
|
|
140
168
|
- test-data/badaddr.cddl
|
|
141
169
|
- test-data/base32.cddl
|
|
@@ -146,6 +174,7 @@ files:
|
|
|
146
174
|
- test-data/bpv7a.cddl
|
|
147
175
|
- test-data/bpv7b.cddl
|
|
148
176
|
- test-data/cat-re.cddl
|
|
177
|
+
- test-data/catb64.cddl
|
|
149
178
|
- test-data/cdni-ct.cddl
|
|
150
179
|
- test-data/complex-occ.cddl
|
|
151
180
|
- test-data/coral.cddl
|
|
@@ -158,7 +187,13 @@ files:
|
|
|
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
|
|
@@ -240,14 +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: 3.4
|
|
293
|
+
rubygems_version: 3.5.4
|
|
251
294
|
signing_key:
|
|
252
295
|
specification_version: 4
|
|
253
296
|
summary: CDDL generator and validator.
|
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
|