cddl 0.8.26 → 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 +19 -3
- data/cddl.gemspec +9 -7
- data/data/cddl.abnf +29 -13
- data/lib/cbor-pp-play.rb +1 -0
- data/lib/cddl.rb +533 -70
- data/test/test-cddl.rb +2 -2
- data/test-data/b64c-sloppy.cddl +1 -0
- data/test-data/b64c.cddl +1 -0
- data/test-data/b64u-strict.cddl +12 -0
- data/test-data/b64u.cddl +1 -0
- data/test-data/base32.cddl +1 -0
- data/test-data/base32hex.cddl +1 -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/decimal.cddl +1 -0
- data/test-data/decimal2.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/hex.cddl +1 -0
- data/test-data/hexlc.cddl +1 -0
- data/test-data/hexuc.cddl +1 -0
- data/test-data/join.cddl +1 -0
- data/test-data/joini.cddl +1 -0
- data/test-data/joinx.cddl +1 -0
- data/test-data/json.cddl +1 -0
- data/test-data/json1.cddl +15 -0
- data/test-data/json2.cddl +1 -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 +89 -17
data/lib/cddl.rb
CHANGED
|
@@ -2,10 +2,15 @@ require 'abnc'
|
|
|
2
2
|
require 'pp'
|
|
3
3
|
require 'pathname'
|
|
4
4
|
require 'cbor-pure' unless defined?(CBOR::Tagged)
|
|
5
|
+
require 'half'
|
|
6
|
+
require 'cbor-deterministic'
|
|
5
7
|
require 'regexp-examples'
|
|
6
8
|
require 'abnftt'
|
|
7
9
|
require 'colorize'
|
|
8
10
|
require 'base64'
|
|
11
|
+
require 'base32'
|
|
12
|
+
require 'base45_lite'
|
|
13
|
+
require 'scanf'
|
|
9
14
|
|
|
10
15
|
module CDDL
|
|
11
16
|
|
|
@@ -22,6 +27,21 @@ module CDDL
|
|
|
22
27
|
|
|
23
28
|
class Parser
|
|
24
29
|
|
|
30
|
+
FEATURE_REJECT_RE = /\A\^/
|
|
31
|
+
# CDDL_FEATURE_OK=cbor,^json
|
|
32
|
+
CDDL_FEATURE_OK, CDDL_FEATURE_REJECT =
|
|
33
|
+
if ok = ENV["CDDL_FEATURE_OK"]
|
|
34
|
+
ok.split(/,\s*/)
|
|
35
|
+
.partition{|s| s[0] !~ FEATURE_REJECT_RE}
|
|
36
|
+
.map {|l| Hash[l.map {|feature|
|
|
37
|
+
[feature.sub(FEATURE_REJECT_RE, ''),
|
|
38
|
+
true]}]}
|
|
39
|
+
else
|
|
40
|
+
[{}, {}]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
CDDL_UNUSED_OK = ENV["CDDL_UNUSED_OK"]
|
|
44
|
+
|
|
25
45
|
class BackTrack < Exception; end
|
|
26
46
|
|
|
27
47
|
def initialize(source_text)
|
|
@@ -42,7 +62,7 @@ module CDDL
|
|
|
42
62
|
if upto - presult < 100
|
|
43
63
|
part2 = source_text[presult...upto]
|
|
44
64
|
else
|
|
45
|
-
part2 = source_text[presult, 50] + "......." + source_text[upto-50, 50]
|
|
65
|
+
part2 = source_text[presult, 50] + "......." + (source_text[upto-50, 50] || "")
|
|
46
66
|
end
|
|
47
67
|
warn "*** Look for syntax problems around the #{
|
|
48
68
|
"%%%".colorize(background: :light_yellow)} markers:\n#{
|
|
@@ -99,6 +119,16 @@ module CDDL
|
|
|
99
119
|
r.compact
|
|
100
120
|
end
|
|
101
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
|
+
|
|
102
132
|
def cname(s)
|
|
103
133
|
s.to_s.gsub(/-/, "_")
|
|
104
134
|
end
|
|
@@ -130,7 +160,7 @@ module CDDL
|
|
|
130
160
|
if subtree[0] == :type1 && subtree[1..-1].all? {|x| x[0] == :int}
|
|
131
161
|
if enumname = subtree.cbor_annotations rescue nil
|
|
132
162
|
enumname = cname(enumname.first)
|
|
133
|
-
subtree[1..-1].each do |x|
|
|
163
|
+
subtree[1..-1].each do |x|
|
|
134
164
|
if memname = x.cbor_annotations
|
|
135
165
|
memname = "#{enumname}_#{cname(memname.first)}"
|
|
136
166
|
add.(memname, x[1].to_s)
|
|
@@ -185,7 +215,8 @@ module CDDL
|
|
|
185
215
|
ids = g.children(:id).map(&:to_s)
|
|
186
216
|
# puts ["ids", ids].inspect
|
|
187
217
|
if b = @generics[n]
|
|
188
|
-
fail "Duplicate generics definition #{n}
|
|
218
|
+
fail "Duplicate generics definition #{n} #{
|
|
219
|
+
diff_message(strip_nodes(b[0]).inspect, strip_nodes(rule_ast).inspect)}"
|
|
189
220
|
end
|
|
190
221
|
@generics[n] = [rule_ast, ids]
|
|
191
222
|
else
|
|
@@ -197,7 +228,7 @@ module CDDL
|
|
|
197
228
|
if a == b
|
|
198
229
|
warn "*** Warning: Identical redefinition of #{n} as #{a}"
|
|
199
230
|
else
|
|
200
|
-
fail "Duplicate rule definition #{n}
|
|
231
|
+
fail "Duplicate rule definition #{n} #{diff_message(b, a)}"
|
|
201
232
|
end
|
|
202
233
|
end
|
|
203
234
|
@rules[n] = rule_ast
|
|
@@ -229,7 +260,7 @@ module CDDL
|
|
|
229
260
|
r_process("used_in_cddl_prelude", @rules["used_in_cddl_prelude"])
|
|
230
261
|
@rules.each do |n, r|
|
|
231
262
|
# r_process(n, r) # debug only loop
|
|
232
|
-
warn "*** Unused rule #{n}" unless @stage1[n]
|
|
263
|
+
warn "*** Unused rule #{n}" unless @stage1[n] || CDDL_UNUSED_OK
|
|
233
264
|
end
|
|
234
265
|
if result[0] == :grpent
|
|
235
266
|
warn "Group at top -- first rule must be a type!"
|
|
@@ -252,10 +283,25 @@ module CDDL
|
|
|
252
283
|
l.map {|l| l.sub(/^ {0,#{indent}}/, "")}.join
|
|
253
284
|
end
|
|
254
285
|
|
|
286
|
+
def unpack_array_to_sequence(content, where)
|
|
287
|
+
# remove the first head
|
|
288
|
+
n = case content.getbyte(0) - (4 << 5)
|
|
289
|
+
when 0..23; 1
|
|
290
|
+
when 24; 2
|
|
291
|
+
when 25; 3
|
|
292
|
+
when 26; 5
|
|
293
|
+
when 27; 9 # unlikely :-)
|
|
294
|
+
else fail ".cborseq sequence for #{where} not an array"
|
|
295
|
+
end
|
|
296
|
+
content[0...n] = ''
|
|
297
|
+
content
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
|
|
255
301
|
# Memoize a bit here
|
|
256
302
|
|
|
257
303
|
REGEXP_FOR_STRING = Hash.new {|h, k|
|
|
258
|
-
h[k] = Regexp.new("\\A
|
|
304
|
+
h[k] = Regexp.new("\\A(?:#{k})\\z")
|
|
259
305
|
}
|
|
260
306
|
|
|
261
307
|
ABNF_PARSER_FOR_STRING = Hash.new {|h, k|
|
|
@@ -268,6 +314,12 @@ module CDDL
|
|
|
268
314
|
abnfb: Encoding::BINARY
|
|
269
315
|
}
|
|
270
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
|
+
|
|
271
323
|
def generate
|
|
272
324
|
@recursion = 0
|
|
273
325
|
generate1(rules)
|
|
@@ -390,9 +442,17 @@ module CDDL
|
|
|
390
442
|
when 3
|
|
391
443
|
gen_word
|
|
392
444
|
when 6
|
|
393
|
-
|
|
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]))
|
|
394
450
|
when 7
|
|
395
|
-
|
|
451
|
+
w2 = where[2]
|
|
452
|
+
if Array === w2
|
|
453
|
+
w2 = generate1(w2)
|
|
454
|
+
end
|
|
455
|
+
case w2
|
|
396
456
|
when nil
|
|
397
457
|
Math::PI
|
|
398
458
|
when 20
|
|
@@ -401,10 +461,22 @@ module CDDL
|
|
|
401
461
|
true
|
|
402
462
|
when 22
|
|
403
463
|
nil
|
|
404
|
-
when 23
|
|
405
|
-
|
|
406
|
-
when 25
|
|
407
|
-
|
|
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
|
|
408
480
|
end
|
|
409
481
|
else
|
|
410
482
|
fail "Can't generate prim #{where[1]}"
|
|
@@ -459,6 +531,11 @@ module CDDL
|
|
|
459
531
|
end
|
|
460
532
|
generate1(target, inmap)
|
|
461
533
|
when :feature
|
|
534
|
+
feature, = extract_feature(control, nil)
|
|
535
|
+
# warn "@@@ GENFEAT #{feature.inspect} #{CDDL_FEATURE_REJECT[feature].inspect}"
|
|
536
|
+
if CDDL_FEATURE_REJECT[feature]
|
|
537
|
+
fail BackTrack.new("Feature '#{feature}' rejected")
|
|
538
|
+
end
|
|
462
539
|
generate1(target, inmap)
|
|
463
540
|
when :cat, :det
|
|
464
541
|
lhs = generate1(target, inmap)
|
|
@@ -514,8 +591,7 @@ module CDDL
|
|
|
514
591
|
warn "HUH gen #{where.inspect} #{try.inspect}" unless try.nil?
|
|
515
592
|
end
|
|
516
593
|
end
|
|
517
|
-
|
|
518
|
-
content = generate1(target)
|
|
594
|
+
try_generate(target) do |content|
|
|
519
595
|
if validate1(content, where)
|
|
520
596
|
return content
|
|
521
597
|
end
|
|
@@ -534,33 +610,107 @@ module CDDL
|
|
|
534
610
|
unless !bytes.nil? && String === grammar
|
|
535
611
|
fail "Don't know yet how to generate #{where}"
|
|
536
612
|
end
|
|
613
|
+
grammar << "\n" unless grammar =~ /\n\z/
|
|
537
614
|
out = ABNF_PARSER_FOR_STRING[grammar].generate
|
|
538
615
|
if conop == :abnfb
|
|
539
616
|
out = out.codepoints.pack("C*")
|
|
540
617
|
end
|
|
541
618
|
enc = bytes ? Encoding::BINARY : Encoding::UTF_8
|
|
542
619
|
out.force_encoding(enc)
|
|
543
|
-
when :cbor, :cborseq
|
|
620
|
+
when :cbor, :cborseq, :cbordet, :cborseqdet
|
|
544
621
|
unless target == [:prim, 2]
|
|
545
622
|
fail "Don't know yet how to generate #{where}"
|
|
546
623
|
end
|
|
547
|
-
|
|
548
|
-
if conop == :
|
|
624
|
+
input = generate1(control)
|
|
625
|
+
if conop == :cbordet || conop == :cborseqdet
|
|
626
|
+
input = input.cbor_prepare_deterministic
|
|
627
|
+
end
|
|
628
|
+
content = CBOR::encode(input)
|
|
629
|
+
if conop == :cborseq || conop == :cborseqdet
|
|
549
630
|
# remove the first head
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
631
|
+
content = unpack_array_to_sequence(content, where)
|
|
632
|
+
end
|
|
633
|
+
content
|
|
634
|
+
when :json
|
|
635
|
+
unless target == [:prim, 3]
|
|
636
|
+
fail "Don't know yet how to generate #{where}"
|
|
637
|
+
end
|
|
638
|
+
content = JSON::dump(generate1(control))
|
|
639
|
+
content
|
|
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
|
|
647
|
+
unless target == [:prim, 3]
|
|
648
|
+
fail "Don't know yet how to generate #{where}"
|
|
559
649
|
end
|
|
650
|
+
content = Integer(generate1(control)).to_s
|
|
560
651
|
content
|
|
652
|
+
when :join
|
|
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
|
|
662
|
+
end
|
|
663
|
+
fail "Don't know yet how to generate #{where}"
|
|
664
|
+
when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
|
665
|
+
:b45, :b32, :h32, :hex, :hexlc, :hexuc
|
|
666
|
+
try_generate(control) do |content|
|
|
667
|
+
if String === content
|
|
668
|
+
content = case conop
|
|
669
|
+
when :b64u, :"b64u-sloppy"
|
|
670
|
+
Base64.urlsafe_encode64(content, padding: false)
|
|
671
|
+
when :b64c, :"b64c-sloppy"
|
|
672
|
+
Base64.strict_encode64(content)
|
|
673
|
+
when :b45
|
|
674
|
+
Base45Lite.encode(content)
|
|
675
|
+
when :b32
|
|
676
|
+
Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
|
677
|
+
Base32.encode(content).gsub("=", "")
|
|
678
|
+
when :h32
|
|
679
|
+
Base32.table = "0123456789ABCDEFGHIJKLMNOPQRSTUV"
|
|
680
|
+
Base32.encode(content).gsub("=", "")
|
|
681
|
+
when :hex, :hexuc
|
|
682
|
+
content.unpack("H*")[0].upcase
|
|
683
|
+
when :hexlc
|
|
684
|
+
content.unpack("H*")[0]
|
|
685
|
+
else fail "Cannot happen"
|
|
686
|
+
end
|
|
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}"
|
|
561
711
|
when :within, :and
|
|
562
|
-
|
|
563
|
-
|
|
712
|
+
try_generate(target) do |content|
|
|
713
|
+
$features ||= Hash.new {|h, k| h[k] = {}}
|
|
564
714
|
if validate1(content, control)
|
|
565
715
|
return content
|
|
566
716
|
elsif conop == :within
|
|
@@ -588,22 +738,41 @@ module CDDL
|
|
|
588
738
|
end
|
|
589
739
|
end
|
|
590
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
|
+
|
|
591
748
|
VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
|
|
592
749
|
SIMPLE_VALUE = {
|
|
593
750
|
[:prim, 7, 20] => [true, false, :bool],
|
|
594
751
|
[:prim, 7, 21] => [true, true, :bool],
|
|
595
752
|
[:prim, 7, 22] => [true, nil, :nil],
|
|
596
|
-
[:prim, 7, 23] => [true, :undefined, :undefined],
|
|
597
753
|
}
|
|
754
|
+
SIMPLE_VALUE_SIMPLE = Set[23] + (0..19) + (32..255)
|
|
598
755
|
|
|
599
756
|
def extract_value(t) # []
|
|
600
757
|
if vt = VALUE_TYPE[t[0]]
|
|
601
758
|
[true, t[1], vt]
|
|
602
|
-
elsif
|
|
603
|
-
|
|
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
|
|
604
773
|
elsif t[0] == :anno
|
|
605
774
|
_, conop, target, control = t
|
|
606
|
-
|
|
775
|
+
warn ["EXV0", conop, target, control].inspect if ENV["CDDL_TRACE"]
|
|
607
776
|
if conop == :cat || conop == :plus || conop == :det
|
|
608
777
|
ok1, v1, vt1 = extract_value(target)
|
|
609
778
|
ok2, v2, vt2 = extract_value(control)
|
|
@@ -635,6 +804,38 @@ module CDDL
|
|
|
635
804
|
}]
|
|
636
805
|
end
|
|
637
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
|
+
|
|
820
|
+
def extract_feature(control, d)
|
|
821
|
+
ok, v, vt = extract_value(control)
|
|
822
|
+
if ok
|
|
823
|
+
nm = v
|
|
824
|
+
det = d
|
|
825
|
+
warn "*** feature controller should be a string: #{control.inspect}" unless String == vt
|
|
826
|
+
else
|
|
827
|
+
ok, *v = extract_array(control)
|
|
828
|
+
if ok && v.size == 2
|
|
829
|
+
nm = v[0][0]
|
|
830
|
+
det = v[1][0]
|
|
831
|
+
warn "*** first element of feature controller should be a string: #{control.inspect}" unless String === nm
|
|
832
|
+
else
|
|
833
|
+
warn "*** feature controller not implemented: #{control.inspect}"
|
|
834
|
+
end
|
|
835
|
+
end
|
|
836
|
+
[nm, det]
|
|
837
|
+
end
|
|
838
|
+
|
|
638
839
|
def validate_diag
|
|
639
840
|
[@last_data, @last_rule, @last_message]
|
|
640
841
|
end
|
|
@@ -646,9 +847,8 @@ module CDDL
|
|
|
646
847
|
if warn
|
|
647
848
|
if result
|
|
648
849
|
if $features != {}
|
|
649
|
-
|
|
650
|
-
# warn
|
|
651
|
-
features = $features.reject {|k, v| ok.include? k.to_s }
|
|
850
|
+
features = $features.reject {|k, v| CDDL_FEATURE_OK[k.to_s] }
|
|
851
|
+
# warn "@@@ FEAT #{CDDL_FEATURE_OK.inspect} #{CDDL_FEATURE_REJECT.inspect}"
|
|
652
852
|
warn "** Features potentially used (#$fn): #{features.map {|k, v| "#{k}: #{v.keys}"}.join(", ")}" if features != {}
|
|
653
853
|
end
|
|
654
854
|
else
|
|
@@ -805,6 +1005,19 @@ module CDDL
|
|
|
805
1005
|
}
|
|
806
1006
|
end
|
|
807
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
|
+
|
|
808
1021
|
def validate1a(d, where)
|
|
809
1022
|
if ann = validate1(d, where)
|
|
810
1023
|
here = [d, where]
|
|
@@ -817,6 +1030,8 @@ module CDDL
|
|
|
817
1030
|
end
|
|
818
1031
|
|
|
819
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}
|
|
820
1035
|
|
|
821
1036
|
def validate1(d, where)
|
|
822
1037
|
if ENV["CDDL_TRACE"]
|
|
@@ -827,6 +1042,9 @@ module CDDL
|
|
|
827
1042
|
@last_data = d
|
|
828
1043
|
@last_rule = where
|
|
829
1044
|
ann = nil
|
|
1045
|
+
if CBOR::Tagged === d && d.tag === 888 && ENV["CDDL_888"]
|
|
1046
|
+
return []
|
|
1047
|
+
end
|
|
830
1048
|
case where[0]
|
|
831
1049
|
when :type1
|
|
832
1050
|
if where[1..-1].any? {|r| ann = validate1a(d, r)}
|
|
@@ -863,7 +1081,7 @@ module CDDL
|
|
|
863
1081
|
if conop == :cat || conop == :plus || conop == :det
|
|
864
1082
|
ok1, v1, vt1 = extract_value(target)
|
|
865
1083
|
ok2, v2, vt2 = extract_value(control)
|
|
866
|
-
|
|
1084
|
+
warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
|
|
867
1085
|
if ok1 && ok2
|
|
868
1086
|
v2 = Integer(v2) if vt1 == Integer
|
|
869
1087
|
if conop == :det
|
|
@@ -872,6 +1090,30 @@ module CDDL
|
|
|
872
1090
|
end
|
|
873
1091
|
# warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
|
|
874
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
|
|
875
1117
|
end
|
|
876
1118
|
elsif ann = validate1a(d, target)
|
|
877
1119
|
case conop
|
|
@@ -914,28 +1156,19 @@ module CDDL
|
|
|
914
1156
|
end
|
|
915
1157
|
ann
|
|
916
1158
|
when :feature
|
|
917
|
-
|
|
918
|
-
if ok
|
|
919
|
-
nm = v
|
|
920
|
-
det = d
|
|
921
|
-
warn "*** feature controller should be a string: #{control.inspect}" unless String == vt
|
|
922
|
-
else
|
|
923
|
-
ok, *v = extract_array(control)
|
|
924
|
-
if ok && v.size == 2
|
|
925
|
-
nm = v[0][0]
|
|
926
|
-
det = v[1][0]
|
|
927
|
-
warn "*** first element of feature controller should be a string: #{control.inspect}" unless String === nm
|
|
928
|
-
else
|
|
929
|
-
warn "*** feature controller not implemented: #{control.inspect}"
|
|
930
|
-
end
|
|
931
|
-
end
|
|
1159
|
+
nm, det = extract_feature(control, d)
|
|
932
1160
|
$features[nm][det] = true
|
|
933
|
-
ann
|
|
1161
|
+
ann if !CDDL_FEATURE_REJECT[nm]
|
|
934
1162
|
when :lt, :le, :gt, :ge, :eq, :ne
|
|
935
1163
|
op = OPERATORS[conop]
|
|
936
1164
|
ok, v, _vt = extract_value(control)
|
|
937
1165
|
if ok
|
|
938
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
|
|
939
1172
|
end
|
|
940
1173
|
when :regexp
|
|
941
1174
|
ann if (
|
|
@@ -970,6 +1203,159 @@ module CDDL
|
|
|
970
1203
|
ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
|
|
971
1204
|
when :cborseq
|
|
972
1205
|
ann if validate1((CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR), control)
|
|
1206
|
+
when :cbordet
|
|
1207
|
+
decoded = CBOR::decode(d) rescue :BAD_CBOR
|
|
1208
|
+
if d != decoded.to_deterministic_cbor
|
|
1209
|
+
@last_message = "CBOR #{d.inspect} not deterministically encoded"
|
|
1210
|
+
nil
|
|
1211
|
+
else
|
|
1212
|
+
ann if validate1(decoded, control)
|
|
1213
|
+
end
|
|
1214
|
+
when :cborseqdet
|
|
1215
|
+
decoded = CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR
|
|
1216
|
+
if d != unpack_array_to_sequence(decoded.to_deterministic_cbor, d.inspect)
|
|
1217
|
+
@last_message = "CBOR Sequence #{d.inspect} not deterministically encoded"
|
|
1218
|
+
nil
|
|
1219
|
+
else
|
|
1220
|
+
ann if validate1(decoded, control)
|
|
1221
|
+
end
|
|
1222
|
+
when :json
|
|
1223
|
+
ann if validate1((JSON::load(d) rescue :BAD_JSON), control)
|
|
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
|
+
|
|
1232
|
+
ann if (
|
|
1233
|
+
if /\A0|-?[1-9][0-9]*\z/ === d
|
|
1234
|
+
validate1((d.to_i rescue :BAD_JSON), control)
|
|
1235
|
+
end
|
|
1236
|
+
)
|
|
1237
|
+
when :join
|
|
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
|
|
1307
|
+
else
|
|
1308
|
+
fail "Don't know yet how to validate against #{where}"
|
|
1309
|
+
end
|
|
1310
|
+
when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy", :b45, :b32, :h32, :hex, :hexlc, :hexuc
|
|
1311
|
+
ann if (
|
|
1312
|
+
String === d && (
|
|
1313
|
+
decoded = case conop
|
|
1314
|
+
when :b64u
|
|
1315
|
+
/[+\/=]/ !~ d &&
|
|
1316
|
+
Base64.urlsafe_decode64(d)
|
|
1317
|
+
when :"b64u-sloppy"
|
|
1318
|
+
/[-_=]/ !~ d &&
|
|
1319
|
+
Base64.decode64(d.tr("+/", "-_"))
|
|
1320
|
+
when :b64c
|
|
1321
|
+
Base64.strict_decode64(d)
|
|
1322
|
+
when :"b64c-sloppy"
|
|
1323
|
+
Base64.decode64(d)
|
|
1324
|
+
when :b32
|
|
1325
|
+
/=/ !~ d &&
|
|
1326
|
+
(Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567") &&
|
|
1327
|
+
Base32.decode(d)
|
|
1328
|
+
when :b45
|
|
1329
|
+
Base45Lite.decode(d)
|
|
1330
|
+
when :h32
|
|
1331
|
+
/=/ !~ d &&
|
|
1332
|
+
(Base32.table = "0123456789ABCDEFGHIJKLMNOPQRSTUV") &&
|
|
1333
|
+
Base32.decode(d)
|
|
1334
|
+
when :hex
|
|
1335
|
+
/\A[0-9a-fA-F]*\z/ =~ d && [d].pack("H*")
|
|
1336
|
+
when :hexuc
|
|
1337
|
+
/\A[0-9A-F]*\z/ =~ d && [d].pack("H*")
|
|
1338
|
+
when :hexlc
|
|
1339
|
+
/\A[0-9a-f]*\z/ =~ d && [d].pack("H*")
|
|
1340
|
+
else fail "Cannot happen"
|
|
1341
|
+
end
|
|
1342
|
+
) && validate1(decoded.b, control)
|
|
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
|
+
)
|
|
973
1359
|
when :within
|
|
974
1360
|
if validate1(d, control)
|
|
975
1361
|
ann
|
|
@@ -1005,20 +1391,35 @@ module CDDL
|
|
|
1005
1391
|
end
|
|
1006
1392
|
d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
|
|
1007
1393
|
end
|
|
1008
|
-
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])
|
|
1009
1397
|
when 7
|
|
1010
1398
|
t, v = extract_value(where)
|
|
1011
1399
|
if t
|
|
1012
1400
|
v.eql? d
|
|
1013
1401
|
else
|
|
1014
|
-
case where[2]
|
|
1402
|
+
case w2 = where[2]
|
|
1015
1403
|
when nil
|
|
1016
|
-
|
|
1017
|
-
|
|
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)
|
|
1018
1419
|
when 25, 26, 27
|
|
1019
|
-
Float === d
|
|
1420
|
+
Float === d && FLOAT_AI_FROM_SIZE[d.to_cbor.size] == w2
|
|
1020
1421
|
else
|
|
1021
|
-
fail
|
|
1422
|
+
fail [:val7, d, where].inspect
|
|
1022
1423
|
end
|
|
1023
1424
|
end
|
|
1024
1425
|
else
|
|
@@ -1068,6 +1469,10 @@ module CDDL
|
|
|
1068
1469
|
else
|
|
1069
1470
|
[:type1]
|
|
1070
1471
|
end
|
|
1472
|
+
elsif s = ENV["CDDL_INVENT"]
|
|
1473
|
+
s = "_" if s == ""
|
|
1474
|
+
r = [:type1, [:text, "#{s}-#{name}"]]
|
|
1475
|
+
return r
|
|
1071
1476
|
end
|
|
1072
1477
|
end
|
|
1073
1478
|
if r
|
|
@@ -1113,29 +1518,69 @@ module CDDL
|
|
|
1113
1518
|
end
|
|
1114
1519
|
end
|
|
1115
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
|
+
|
|
1116
1533
|
def value(n)
|
|
1117
1534
|
# cheat:
|
|
1118
1535
|
# warn n
|
|
1119
1536
|
s = n.to_s
|
|
1120
1537
|
if s[-1] == "'"
|
|
1121
|
-
parts = s.split("'",
|
|
1122
|
-
if parts[
|
|
1123
|
-
warn "***
|
|
1538
|
+
bsqual, *parts = s.split("'", -1)
|
|
1539
|
+
if parts[-1] != ""
|
|
1540
|
+
warn "*** Problem decoding byte string #{s.inspect}"
|
|
1124
1541
|
end
|
|
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
|
+
}
|
|
1125
1556
|
[:bytes,
|
|
1126
|
-
case
|
|
1557
|
+
case bsqual
|
|
1127
1558
|
when ""
|
|
1128
|
-
|
|
1559
|
+
bsval.b
|
|
1129
1560
|
when "h"
|
|
1130
|
-
|
|
1561
|
+
bsval.gsub(/\s/, "").chars.each_slice(2).map{ |x| Integer(x.join, 16).chr("BINARY") }.join.b
|
|
1131
1562
|
when "b64"
|
|
1132
|
-
Base64.urlsafe_decode64(
|
|
1563
|
+
Base64.urlsafe_decode64(bsval)
|
|
1133
1564
|
else
|
|
1134
|
-
warn "*** Can't handle byte string type #{
|
|
1565
|
+
warn "*** Can't handle byte string type #{bsqual.inspect} yet"
|
|
1135
1566
|
end
|
|
1136
1567
|
]
|
|
1137
1568
|
else
|
|
1138
|
-
|
|
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
|
|
1139
1584
|
# warn val
|
|
1140
1585
|
case val
|
|
1141
1586
|
when Integer; [:int, val]
|
|
@@ -1241,9 +1686,13 @@ module CDDL
|
|
|
1241
1686
|
def g_process(name, g, genericargs)
|
|
1242
1687
|
r, ids = g
|
|
1243
1688
|
args = genericargs.children(:type1).map {|x| type1(x, true)}
|
|
1689
|
+
# warn "** args #{args.inspect}"
|
|
1244
1690
|
fail "number of args #{name} #{ids.size} #{args.size}" if ids.size != args.size
|
|
1245
1691
|
bindings = Hash[ids.zip(args)]
|
|
1246
|
-
|
|
1692
|
+
# warn "** bindings: #{bindings.inspect}"
|
|
1693
|
+
genname = "#{name}<#{args.inspect}>" # XXX this works up to a RECURSE...
|
|
1694
|
+
# warn "** genname #{genname}"
|
|
1695
|
+
r_process(genname, r, bindings)
|
|
1247
1696
|
end
|
|
1248
1697
|
|
|
1249
1698
|
def type_recall(name, canbegroup, genericargs)
|
|
@@ -1319,9 +1768,16 @@ module CDDL
|
|
|
1319
1768
|
|
|
1320
1769
|
BRACE = {"{" => :map, "[" => :array}
|
|
1321
1770
|
RANGE_EXCLUDE_END = {".." => false, "..." => true}
|
|
1322
|
-
SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp,
|
|
1771
|
+
SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp,
|
|
1772
|
+
:cbor, :cborseq, :cbordet, :cborseqdet,
|
|
1773
|
+
:within, :and,
|
|
1323
1774
|
:default, :lt, :le, :gt, :ge, :eq, :ne,
|
|
1324
|
-
:feature, :abnf, :abnfb, :det, :cat, :plus
|
|
1775
|
+
:feature, :abnf, :abnfb, :det, :cat, :plus,
|
|
1776
|
+
:json, :decimal, :base10, :join,
|
|
1777
|
+
:b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
|
|
1778
|
+
:b45, :b32, :h32, :hex, :hexlc, :hexuc,
|
|
1779
|
+
:printf,
|
|
1780
|
+
]
|
|
1325
1781
|
|
|
1326
1782
|
def type1(n, canbegroup = false)
|
|
1327
1783
|
# puts "NVALUE #{n.value.inspect}"
|
|
@@ -1353,6 +1809,13 @@ module CDDL
|
|
|
1353
1809
|
when /\A#(\d+)/
|
|
1354
1810
|
maj = $1.to_i
|
|
1355
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
|
|
1356
1819
|
if tagged_type = n.type
|
|
1357
1820
|
s << type(tagged_type)
|
|
1358
1821
|
end
|