cddl 0.10.2 → 0.10.5

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: 33adef2ddb191ca70e7ad3742684cea679e675fe0169a139c9fa5bcc59abfaa6
4
- data.tar.gz: 7b7b7d2cd0623645d6dca87c5c7a8a3d40540e7eec390411e9cbf3adcc6f7c9d
3
+ metadata.gz: b3b0177b945919083ba2e0595570d098809b87839cb86e823dd54c62f225ad6b
4
+ data.tar.gz: 45302758ba30682f746f9b515cd293a5ac0883b2b126d6f74cd13a4911286e9e
5
5
  SHA512:
6
- metadata.gz: b4a8ccd11e9dbf1b0ebf2541c03691a94a8430538fbe81db3bd178a2fab1732626114689d305048e88fb54c3336f0e95853c86f8336586d722df90639f82efa6
7
- data.tar.gz: 1c6494a0fa4ead8ea548f61f3af5595dde99707359ce8aa8695c074288248334849f2452cae52620541bb762c9cf3979b159f415a1b787009d1061df54d849b5
6
+ metadata.gz: d613c36a0b4e7e1a18c68c1a2c5df9b0c46389936fdc063465bc8c130ba470b5c6467872fd55befa47972ea8cce8362f45a2164e2ee32c02539f29bd45fb1279
7
+ data.tar.gz: 6dca2e75e676eb00aba31e03671b2baf37568a2e4eb8fb0b506c8b02829efb88d6efda323891962e6ca3644be4added36482ee555bbf4d13565517c59cbaf397
data/cddl.gemspec CHANGED
@@ -1,21 +1,23 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.10.2'
3
+ s.version = '0.10.5'
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
- s.add_dependency('abnc')
7
+ s.add_dependency('abnc', '~> 0.1.1')
8
8
  s.add_dependency('json_pure')
9
9
  s.add_dependency('abnftt')
10
10
  s.add_dependency('regexp-examples') # , '1.1.0')
11
11
  s.add_dependency('colorize')
12
12
  s.add_dependency('base32', '~> 0.3')
13
+ s.add_dependency('base45_lite', '~> 1.0')
14
+ s.add_dependency('scanf', '~> 1.0')
13
15
  s.files = `git ls-files`.split("\n").grep(/^[a-z]/)
14
16
  s.files = Dir['lib/**/*.rb'] + %w(cddl.gemspec) + Dir['data/**/*.abnf'] + Dir['data/**/*.cddl'] + Dir['test-data/**/*.cddl'] + Dir['test/**/*.rb']
15
17
  s.require_path = 'lib'
16
18
  s.executables = ['cddl']
17
19
  s.default_executable = 'cddl'
18
- s.required_ruby_version = '>= 2.0'
20
+ s.required_ruby_version = '>= 2.3'
19
21
  s.author = "Carsten Bormann"
20
22
  s.email = "cabo@tzi.org"
21
23
  s.homepage = "http://github.com/cabo/cddl"
data/data/cddl.abnf CHANGED
@@ -13,7 +13,7 @@ genericarg = "<" S type1 S *("," S type1 S ) ">"
13
13
  type = type1 S *("/" S type1 S)
14
14
 
15
15
  type1 = type2 [S (rangeop / annotator) S type2]
16
- / "#" "6" ["." uint] "(" S type S ")" ; note no space!
16
+ / "#" "6" ["." tagnumber] "(" S type S ")" ; note no space!
17
17
  / "#" DIGIT ["." uint] ; major/ai
18
18
  / "#" ; any
19
19
  / "~" S typename [genericarg]
@@ -22,6 +22,8 @@ type1 = type2 [S (rangeop / annotator) S type2]
22
22
  / "&" S "(" S group S ")"
23
23
  / "&" S groupname [genericarg]
24
24
 
25
+ tagnumber = uint / ("<" type ">")
26
+
25
27
  type2 = value
26
28
  / typename [genericarg]
27
29
  / "(" type ")"
data/lib/cddl.rb CHANGED
@@ -2,11 +2,14 @@ require 'abnc'
2
2
  require 'pp'
3
3
  require 'pathname'
4
4
  require 'cbor-pure' unless defined?(CBOR::Tagged)
5
+ require 'cbor-deterministic'
5
6
  require 'regexp-examples'
6
7
  require 'abnftt'
7
8
  require 'colorize'
8
9
  require 'base64'
9
10
  require 'base32'
11
+ require 'base45_lite'
12
+ require 'scanf'
10
13
 
11
14
  module CDDL
12
15
 
@@ -267,6 +270,21 @@ module CDDL
267
270
  l.map {|l| l.sub(/^ {0,#{indent}}/, "")}.join
268
271
  end
269
272
 
273
+ def unpack_array_to_sequence(content, where)
274
+ # remove the first head
275
+ n = case content.getbyte(0) - (4 << 5)
276
+ when 0..23; 1
277
+ when 24; 2
278
+ when 25; 3
279
+ when 26; 5
280
+ when 27; 9 # unlikely :-)
281
+ else fail ".cborseq sequence for #{where} not an array"
282
+ end
283
+ content[0...n] = ''
284
+ content
285
+ end
286
+
287
+
270
288
  # Memoize a bit here
271
289
 
272
290
  REGEXP_FOR_STRING = Hash.new {|h, k|
@@ -405,7 +423,11 @@ module CDDL
405
423
  when 3
406
424
  gen_word
407
425
  when 6
408
- CBOR::Tagged.new(where[2], generate1(where[3]))
426
+ tn = Integer === where[2] ? where[2] : generate1(where[2])
427
+ unless Integer === tn && tn >= 0
428
+ fail "Can't generate a tag number out of #{where[2]}"
429
+ end
430
+ CBOR::Tagged.new(tn, generate1(where[3]))
409
431
  when 7
410
432
  case where[2]
411
433
  when nil
@@ -534,8 +556,7 @@ module CDDL
534
556
  warn "HUH gen #{where.inspect} #{try.inspect}" unless try.nil?
535
557
  end
536
558
  end
537
- 32.times do
538
- content = generate1(target)
559
+ try_generate(target) do |content|
539
560
  if validate1(content, where)
540
561
  return content
541
562
  end
@@ -561,22 +582,18 @@ module CDDL
561
582
  end
562
583
  enc = bytes ? Encoding::BINARY : Encoding::UTF_8
563
584
  out.force_encoding(enc)
564
- when :cbor, :cborseq
585
+ when :cbor, :cborseq, :cbordet, :cborseqdet
565
586
  unless target == [:prim, 2]
566
587
  fail "Don't know yet how to generate #{where}"
567
588
  end
568
- content = CBOR::encode(generate1(control))
569
- if conop == :cborseq
589
+ input = generate1(control)
590
+ if conop == :cbordet || conop == :cborseqdet
591
+ input = input.cbor_prepare_deterministic
592
+ end
593
+ content = CBOR::encode(input)
594
+ if conop == :cborseq || conop == :cborseqdet
570
595
  # remove the first head
571
- n = case content.getbyte(0) - (4 << 5)
572
- when 0..23; 1
573
- when 24; 2
574
- when 25; 3
575
- when 26; 5
576
- when 27; 9 # unlikely :-)
577
- else fail "Generated .cborseq sequence for #{where} not an array"
578
- end
579
- content[0...n] = ''
596
+ content = unpack_array_to_sequence(content, where)
580
597
  end
581
598
  content
582
599
  when :json
@@ -592,25 +609,28 @@ module CDDL
592
609
  content = Integer(generate1(control)).to_s
593
610
  content
594
611
  when :join
595
- content = generate1(control)
596
- unless Array === content &&
597
- content.all? {|x| String === x &&
598
- ((target == [:prim, 2] && x.encoding == Encoding::BINARY) ||
599
- (target == [:prim, 3] && x.encoding != Encoding::BINARY))}
600
- fail "Don't know yet how to generate #{where}"
601
- end
602
- content = content.join
603
- content
604
- when :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc
605
- content = generate1(control)
606
- unless String === content
607
- fail "Don't know yet how to generate #{where}"
612
+ try_generate(control) do |content|
613
+ if Array === content &&
614
+ content.all? {|x| String === x} &&
615
+ Set[content.map {|x| x.encoding}].size == 1
616
+ content = content.join
617
+ if validate1(content, target)
618
+ return content
619
+ end
620
+ end
608
621
  end
609
- content = case conop
610
- when :b64u
622
+ fail "Don't know yet how to generate #{where}"
623
+ when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
624
+ :b45, :b32, :h32, :hex, :hexlc, :hexuc
625
+ try_generate(control) do |content|
626
+ if String === content
627
+ content = case conop
628
+ when :b64u, :"b64u-sloppy"
611
629
  Base64.urlsafe_encode64(content, padding: false)
612
- when :b64c
630
+ when :b64c, :"b64c-sloppy"
613
631
  Base64.strict_encode64(content)
632
+ when :b45
633
+ Base45Lite.encode(content)
614
634
  when :b32
615
635
  Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
616
636
  Base32.encode(content).gsub("=", "")
@@ -623,10 +643,32 @@ module CDDL
623
643
  content.unpack("H*")[0]
624
644
  else fail "Cannot happen"
625
645
  end
626
- content
646
+ if validate1(content, target)
647
+ return content
648
+ end
649
+ end
650
+ end
651
+ fail "Not smart enough to generate #{where}"
652
+ when :printf
653
+ try_generate(control) do |content|
654
+ if Array === content && content.size >= 1
655
+ fmt, *data = content
656
+ if String === fmt
657
+ begin
658
+ content = fmt % data
659
+ if validate1(content, target)
660
+ return content
661
+ end
662
+ rescue ArgumentError => e
663
+ # be verbose about mismatches here
664
+ @last_message << "\n** #{fmt.inspect} ArgumentError #{e}"
665
+ end
666
+ end
667
+ end
668
+ end
669
+ fail "Not smart enough to generate #{where}#{@last_message}"
627
670
  when :within, :and
628
- 32.times do
629
- content = generate1(target)
671
+ try_generate(target) do |content|
630
672
  if validate1(content, control)
631
673
  return content
632
674
  elsif conop == :within
@@ -654,6 +696,13 @@ module CDDL
654
696
  end
655
697
  end
656
698
 
699
+ def try_generate(target)
700
+ 32.times do
701
+ content = generate1(target)
702
+ yield content # should return if success
703
+ end
704
+ end
705
+
657
706
  VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
658
707
  SIMPLE_VALUE = {
659
708
  [:prim, 7, 20] => [true, false, :bool],
@@ -701,6 +750,19 @@ module CDDL
701
750
  }]
702
751
  end
703
752
 
753
+
754
+ def extract_arg0(t)
755
+ return [false] unless t[0] == :array
756
+ [true,
757
+ (el = t[1]
758
+ return [false] unless el[0..3] == [:member, 1, 1, nil]
759
+ ok, v, vt = extract_value(el[4])
760
+ return [false] unless ok
761
+ [v, vt]
762
+ ),
763
+ *t[2..-1]]
764
+ end
765
+
704
766
  def extract_feature(control, d)
705
767
  ok, v, vt = extract_value(control)
706
768
  if ok
@@ -1040,6 +1102,22 @@ module CDDL
1040
1102
  ann if validate1((CBOR::decode(d) rescue :BAD_CBOR), control)
1041
1103
  when :cborseq
1042
1104
  ann if validate1((CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR), control)
1105
+ when :cbordet
1106
+ decoded = CBOR::decode(d) rescue :BAD_CBOR
1107
+ if d != decoded.to_deterministic_cbor
1108
+ @last_message = "CBOR #{d.inspect} not deterministically encoded"
1109
+ nil
1110
+ else
1111
+ ann if validate1(decoded, control)
1112
+ end
1113
+ when :cborseqdet
1114
+ decoded = CBOR::decode("\x9f".b << d << "\xff".b) rescue :BAD_CBOR
1115
+ if d != unpack_array_to_sequence(decoded.to_deterministic_cbor, d.inspect)
1116
+ @last_message = "CBOR Sequence #{d.inspect} not deterministically encoded"
1117
+ nil
1118
+ else
1119
+ ann if validate1(decoded, control)
1120
+ end
1043
1121
  when :json
1044
1122
  ann if validate1((JSON::load(d) rescue :BAD_JSON), control)
1045
1123
  when :decimal
@@ -1060,19 +1138,26 @@ module CDDL
1060
1138
  else
1061
1139
  fail "Don't know yet how to validate against #{where}"
1062
1140
  end
1063
- when :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc
1141
+ when :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy", :b45, :b32, :h32, :hex, :hexlc, :hexuc
1064
1142
  ann if (
1065
1143
  String === d && (
1066
1144
  decoded = case conop
1067
1145
  when :b64u
1068
1146
  /=/ !~ d &&
1069
1147
  Base64.urlsafe_decode64(d)
1148
+ when :"b64u-sloppy"
1149
+ /[-_=]/ !~ d &&
1150
+ Base64.decode64(d.tr("+/", "-_"))
1070
1151
  when :b64c
1071
1152
  Base64.strict_decode64(d)
1153
+ when :"b64c-sloppy"
1154
+ Base64.decode64(d)
1072
1155
  when :b32
1073
1156
  /=/ !~ d &&
1074
1157
  (Base32.table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567") &&
1075
1158
  Base32.decode(d)
1159
+ when :b45
1160
+ Base45Lite.decode(d)
1076
1161
  when :h32
1077
1162
  /=/ !~ d &&
1078
1163
  (Base32.table = "0123456789ABCDEFGHIJKLMNOPQRSTUV") &&
@@ -1087,6 +1172,21 @@ module CDDL
1087
1172
  end
1088
1173
  ) && validate1(decoded.b, control)
1089
1174
  )
1175
+ when :printf
1176
+ ann if String === d && (
1177
+ ok, fmt, *v = extract_arg0(control)
1178
+ if ok && String == fmt[1]
1179
+ fmt = fmt[0]
1180
+ # warn "** ok #{ok.inspect} fmt #{fmt.inspect} v #{v.inspect}"
1181
+ decoded = d.scanf(fmt) # this is a bit too lenient, so let's do:
1182
+ encode_again = fmt % decoded
1183
+ if encode_again != d
1184
+ warn "** fmt #{fmt.inspect} d #{d.inspect} decoded #{decoded.inspect} encode_again #{encode_again.inspect}"
1185
+ else
1186
+ validate1(decoded, [:array, *v])
1187
+ end
1188
+ end
1189
+ )
1090
1190
  when :within
1091
1191
  if validate1(d, control)
1092
1192
  ann
@@ -1122,7 +1222,9 @@ module CDDL
1122
1222
  end
1123
1223
  d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
1124
1224
  end
1125
- CBOR::Tagged === d && d.tag == where[2] && validate1a(d.data, where[3])
1225
+ CBOR::Tagged === d && (
1226
+ Integer === where[2] ? d.tag == where[2] : validate1a(d.tag, where[2])
1227
+ ) && validate1a(d.data, where[3])
1126
1228
  when 7
1127
1229
  t, v = extract_value(where)
1128
1230
  if t
@@ -1441,11 +1543,15 @@ module CDDL
1441
1543
 
1442
1544
  BRACE = {"{" => :map, "[" => :array}
1443
1545
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
1444
- SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
1546
+ SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp,
1547
+ :cbor, :cborseq, :cbordet, :cborseqdet,
1548
+ :within, :and,
1445
1549
  :default, :lt, :le, :gt, :ge, :eq, :ne,
1446
1550
  :feature, :abnf, :abnfb, :det, :cat, :plus,
1447
1551
  :json, :decimal, :join,
1448
- :b64u, :b64c, :b32, :h32, :hex, :hexlc, :hexuc,
1552
+ :b64u, :"b64u-sloppy", :b64c, :"b64c-sloppy",
1553
+ :b45, :b32, :h32, :hex, :hexlc, :hexuc,
1554
+ :printf,
1449
1555
  ]
1450
1556
 
1451
1557
  def type1(n, canbegroup = false)
@@ -1477,7 +1583,14 @@ module CDDL
1477
1583
  [:prim]
1478
1584
  when /\A#(\d+)/
1479
1585
  maj = $1.to_i
1480
- s = [:prim, maj, *n.children(:uint).map(&:to_s).map(&:to_i)]
1586
+ s = [:prim, maj]
1587
+ if tn = n.tagnumber
1588
+ if ui = tn.uint
1589
+ s << ui.to_s.to_i
1590
+ elsif tt = tn.type
1591
+ s << type(tt)
1592
+ end
1593
+ end
1481
1594
  if tagged_type = n.type
1482
1595
  s << type(tagged_type)
1483
1596
  end
@@ -0,0 +1 @@
1
+ a = text .b64c-sloppy 'mnoabcdue=='
@@ -0,0 +1,2 @@
1
+ a = text .printf (["%8d %06d", ~arr])
2
+ arr = [uint, uint]
@@ -0,0 +1 @@
1
+ my_label = text .printf (["0x%x: %a", 4711, 81.5])
@@ -0,0 +1,2 @@
1
+ my_alg_sha = hexlabel<4>
2
+ hexlabel<K> = text .printf (["0x%04x", K])
@@ -0,0 +1,2 @@
1
+ my_alg_sha = hexlabel<int>
2
+ hexlabel<K> = text .printf (["0x%04x", K])
@@ -0,0 +1,2 @@
1
+ any_alg = hexlabel<1..20>
2
+ hexlabel<K> = text .printf (["0x%04x", K])
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.10.2
4
+ version: 0.10.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-25 00:00:00.000000000 Z
11
+ date: 2024-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: abnc
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: 0.1.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: 0.1.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: json_pure
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,34 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.3'
111
+ - !ruby/object:Gem::Dependency
112
+ name: base45_lite
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: scanf
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '1.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '1.0'
111
139
  description: A parser, generator, and validator for CDDL
112
140
  email: cabo@tzi.org
113
141
  executables:
@@ -133,6 +161,7 @@ files:
133
161
  - test-data/abnf3.cddl
134
162
  - test-data/ambig.cddl
135
163
  - test-data/b.cddl
164
+ - test-data/b64c-sloppy.cddl
136
165
  - test-data/b64c.cddl
137
166
  - test-data/b64u.cddl
138
167
  - test-data/badaddr.cddl
@@ -206,6 +235,11 @@ files:
206
235
  - test-data/oidbat.cddl
207
236
  - test-data/patch1.cddl
208
237
  - test-data/plus.cddl
238
+ - test-data/printf.cddl
239
+ - test-data/printf0.cddl
240
+ - test-data/printf1.cddl
241
+ - test-data/printf2.cddl
242
+ - test-data/printf3.cddl
209
243
  - test-data/reused_named_group.cddl
210
244
  - test-data/sasl.cddl
211
245
  - test-data/sequence.cddl
@@ -238,14 +272,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
238
272
  requirements:
239
273
  - - ">="
240
274
  - !ruby/object:Gem::Version
241
- version: '2.0'
275
+ version: '2.3'
242
276
  required_rubygems_version: !ruby/object:Gem::Requirement
243
277
  requirements:
244
278
  - - ">="
245
279
  - !ruby/object:Gem::Version
246
280
  version: '0'
247
281
  requirements: []
248
- rubygems_version: 3.4.2
282
+ rubygems_version: 3.4.10
249
283
  signing_key:
250
284
  specification_version: 4
251
285
  summary: CDDL generator and validator.