cddl 0.8.16 → 0.8.21

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