cddl 0.8.16 → 0.8.21

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