cddl 0.8.15 → 0.8.20

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: 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.