cddl 0.8.15 → 0.8.20

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7b1df5544e11b299155468f15b649f61bf3d281644a0917be5eec9aa099f8bd
4
- data.tar.gz: c29c65aec8cec554d0ca3e837dafd2cbb18bdec41552666c6f81db52f189e491
3
+ metadata.gz: 400024278cc4fce962a5e51e60ba6025ec371cd5768685c0ce10534a06393fa2
4
+ data.tar.gz: cbac2ff6008501c65984cb816cc95b79a8adc361609c4858ba518c073e317937
5
5
  SHA512:
6
- metadata.gz: 5ba99f5a974fb235e2dfeea4fd55dd8feb2fa15a558e5fe77c1c8a921ccacd83c7f292bb767bda835616cb484d86015cd8c2d6a81a675f889c7f751079d62a54
7
- data.tar.gz: b5b18dada347123ed8d7b664987a441820ff73c8ead7146b00b310249f54ef8a6f6ed156c90cf32dd92ad682f9c974664e3986066240ecc7ae996520ae37b231
6
+ metadata.gz: 71babdced5f362b46a1877fdb8676faf2efec9594069b9b95c80daecdfb9aad5bf13ca73577437089fb1dd4819506b00311c003699831110fbba464c06d86fad
7
+ data.tar.gz: 2a29deef318b1c31a830e8937618d776fc439bc6a5b792b7daa79545ed29aedb028f6e78ce3f3b04f36767f21cf38ff349f6251ff3d83103f02c94a124132f34
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.15'
3
+ s.version = '0.8.20'
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, :bat
445
462
  lhs = generate1(target, inmap)
446
463
  rhs = generate1(control)
464
+ rhs = remove_indentation(rhs) if conop == :bat
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 == :bat
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 == :bat
581
613
  [true, v1 + v2, vt1] if vt1 == vt2
582
614
  end
583
615
  end rescue nil
@@ -606,7 +638,10 @@ module CDDL
606
638
  if warn
607
639
  if result
608
640
  if $features != {}
609
- warn "** Features potentially used: #{$features.map {|k, v| "#{k}: #{v.keys}"}.join(", ")}"
641
+ ok = ENV["CDDL_FEATURE_OK"] and ok = ok.split(/,\s*/) or ok = []
642
+ # warn([:OK, ok, $features].inspect)
643
+ features = $features.reject {|k, v| ok.include? k.to_s }
644
+ warn "** Features potentially used: #{features.map {|k, v| "#{k}: #{v.keys}"}.join(", ")}" if features != {}
610
645
  end
611
646
  else
612
647
  warn "CDDL validation failure (#{result.inspect} for #{d.inspect}):"
@@ -619,7 +654,7 @@ module CDDL
619
654
 
620
655
  def validate_result(check)
621
656
  check || (
622
- @last_message = yield
657
+ @last_message << yield
623
658
  false
624
659
  )
625
660
  end
@@ -652,7 +687,9 @@ module CDDL
652
687
  ann.concat(ann2)
653
688
  end
654
689
  if occ < s
655
- @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}"
656
693
  return [false, ann]
657
694
  end
658
695
  end
@@ -817,6 +854,7 @@ module CDDL
817
854
  # warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect
818
855
  if ok1 && ok2
819
856
  v2 = Integer(v2) if vt1 == Integer
857
+ v2 = remove_indentation(v2) if conop == :bat
820
858
  # warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
821
859
  [] if d == v1 + v2 # XXX Focus ArgumentError
822
860
  end
@@ -893,6 +931,24 @@ module CDDL
893
931
  end
894
932
  end
895
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
+ )
896
952
  when :cbor
897
953
  ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
898
954
  when :cborseq
@@ -1247,7 +1303,8 @@ module CDDL
1247
1303
  BRACE = {"{" => :map, "[" => :array}
1248
1304
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
1249
1305
  SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
1250
- :default, :lt, :le, :gt, :ge, :eq, :ne, :feature, :cat, :plus]
1306
+ :default, :lt, :le, :gt, :ge, :eq, :ne,
1307
+ :feature, :abnf, :abnfb, :bat, :cat, :plus]
1251
1308
 
1252
1309
  def type1(n, canbegroup = false)
1253
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,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,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.15
4
+ version: 0.8.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-24 00:00:00.000000000 Z
11
+ date: 2021-02-27 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,6 +114,9 @@ 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
@@ -107,6 +124,7 @@ files:
107
124
  - test-data/bpv7.cddl
108
125
  - test-data/bpv7a.cddl
109
126
  - test-data/bpv7b.cddl
127
+ - test-data/cat-re.cddl
110
128
  - test-data/cdni-ct.cddl
111
129
  - test-data/coral.cddl
112
130
  - test-data/coral1.cddl
@@ -148,8 +166,10 @@ files:
148
166
  - test-data/mon-val.cddl
149
167
  - test-data/multipart-ct.cddl
150
168
  - test-data/named-group.cddl
169
+ - test-data/oid.cddl
151
170
  - test-data/patch1.cddl
152
171
  - test-data/reused_named_group.cddl
172
+ - test-data/sasl.cddl
153
173
  - test-data/sequence.cddl
154
174
  - test-data/structure.cddl
155
175
  - test-data/test-gen.cddl
@@ -181,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
181
201
  - !ruby/object:Gem::Version
182
202
  version: '0'
183
203
  requirements: []
184
- rubygems_version: 3.1.2
204
+ rubygems_version: 3.2.3
185
205
  signing_key:
186
206
  specification_version: 4
187
207
  summary: CDDL generator and validator.