cddl 0.10.7 → 0.11.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: cd34ee2aa2fc9a5d0d504d0dc48222f4e94722b4e19086d4932b8bcc82980e92
4
- data.tar.gz: b397db50185a9f899c6b3d4bc9ce63946a1f57c6989cb7cf55215eb1d6da9868
3
+ metadata.gz: 652f1e63847fbed19fceeca1ed0b695b25b5f8aa6d312b2bd17f21c0ac7c6549
4
+ data.tar.gz: d55f4a0bff69a37b1c6101b11eb003eb93c00df24ede1dded8d7be9844b4afb1
5
5
  SHA512:
6
- metadata.gz: 96be7107033f0e3ef5da1ee747738bcd712eeb5af8230e11f128d64d0649920c8d15f5f4a13c5ccfb0ececad19dac7da1a145337f6e1a322ffe3573d7af4c689
7
- data.tar.gz: d3edd46ef0698fde296cb18509101f98700568c942652e77e6d36abdd7a9a79e27d2fb920a3a5efc46160466feff0ecaa0ae0fda45411a94d234ed4ace037deb
6
+ metadata.gz: 6622daf044d0f5a6d0ce4fe90ac57341526f7723aef0ce49e228edd2284711a44302ab0c3a1a28e3e156676db61afb4477a9b97b27269e1509034c41796ca8b9
7
+ data.tar.gz: 966fd633edc283925e0e4bbb5ca04cb40de60470044bbbd94e7df41fb05c185f59ff09ae4767d5dea2899491d3f82db50d3feb01a585fe03891d60f073e50557
data/bin/cddl CHANGED
@@ -7,10 +7,13 @@ require 'json'
7
7
 
8
8
  Encoding.default_external = "UTF-8" # wake up, smell the coffee
9
9
 
10
+ CDDL_VERSION = Gem.loaded_specs["cddl"].version rescue "unknown-version"
11
+
10
12
  EX_USAGE = 64
11
13
  EX_DATAERR = 65
12
14
 
13
15
  def usage
16
+ warn "cddl tool version #{CDDL_VERSION}"
14
17
  warn "Usage:"
15
18
  warn "#$0 spec.cddl generate [n]"
16
19
  warn "#$0 spec.cddl json-generate [n]"
data/cddl.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.10.7'
3
+ s.version = '0.11.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')
data/data/cddl.abnf CHANGED
@@ -13,7 +13,8 @@ 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" ["." tagnumber] "(" S type S ")" ; note no space!
16
+ / "#" "6" ["." headnumber] "(" S type S ")" ; note no space!
17
+ / "#" "7" ["." headnumber] ; note no space!
17
18
  / "#" DIGIT ["." uint] ; major/ai
18
19
  / "#" ; any
19
20
  / "~" S typename [genericarg]
@@ -22,7 +23,7 @@ type1 = type2 [S (rangeop / annotator) S type2]
22
23
  / "&" S "(" S group S ")"
23
24
  / "&" S groupname [genericarg]
24
25
 
25
- tagnumber = uint / ("<" type ">")
26
+ headnumber = uint / ("<" type ">")
26
27
 
27
28
  type2 = value
28
29
  / typename [genericarg]
data/lib/cddl.rb CHANGED
@@ -2,6 +2,7 @@ require 'abnc'
2
2
  require 'pp'
3
3
  require 'pathname'
4
4
  require 'cbor-pure' unless defined?(CBOR::Tagged)
5
+ require 'half'
5
6
  require 'cbor-deterministic'
6
7
  require 'regexp-examples'
7
8
  require 'abnftt'
@@ -429,7 +430,11 @@ module CDDL
429
430
  end
430
431
  CBOR::Tagged.new(tn, generate1(where[3]))
431
432
  when 7
432
- case where[2]
433
+ w2 = where[2]
434
+ if Array === w2
435
+ w2 = generate1(w2)
436
+ end
437
+ case w2
433
438
  when nil
434
439
  Math::PI
435
440
  when 20
@@ -439,9 +444,21 @@ module CDDL
439
444
  when 22
440
445
  nil
441
446
  when 0..19, 23, 32..255
442
- CBOR::Simple.new(where[2])
443
- when 25, 26, 27
444
- rand()
447
+ CBOR::Simple.new(w2)
448
+ when 25
449
+ while !(hs = Half.encode_from_single_bytes([rand()].pack("g")))
450
+ end
451
+ Half.decode(hs)
452
+ when 26
453
+ while (a = [rand()].pack("g").unpack("g").first).to_cbor.size != 5
454
+ end
455
+ a
456
+ when 27
457
+ while (a = rand()).to_cbor.size != 9
458
+ end
459
+ a
460
+ else
461
+ fail "Can't generate prim #7.#{where[2].inspect}" # XXX retry array generate
445
462
  end
446
463
  else
447
464
  fail "Can't generate prim #{where[1]}"
@@ -710,20 +727,27 @@ module CDDL
710
727
  [:prim, 7, 22] => [true, nil, :nil],
711
728
  }
712
729
  SIMPLE_VALUE_SIMPLE = Set[23] + (0..19) + (32..255)
713
- SIMPLE_VALUE.default_proc = proc { |hash, t|
714
- if t[0] == :prim && t[1] == 7 && SIMPLE_VALUE_SIMPLE.include?(t[2])
715
- [true, CBOR::Simple.new(t[2]), :simple]
716
- end
717
- }
718
730
 
719
731
  def extract_value(t) # []
720
732
  if vt = VALUE_TYPE[t[0]]
721
733
  [true, t[1], vt]
722
- elsif v = SIMPLE_VALUE[t]
723
- v
734
+ elsif t[0] == :prim && t[1] == 7
735
+ case t2 = t[2]
736
+ when Integer
737
+ when Array
738
+ a, b, c = extract_value(t2)
739
+ if a && c == Integer
740
+ t2 = b
741
+ end
742
+ end
743
+ if v = SIMPLE_VALUE[[:prim, 7, t2]]
744
+ v
745
+ elsif SIMPLE_VALUE_SIMPLE === t2
746
+ [true, CBOR::Simple.new(t2), :simple]
747
+ end
724
748
  elsif t[0] == :anno
725
749
  _, conop, target, control = t
726
- # warn ["EXV0", conop, target, control].inspect
750
+ warn ["EXV0", conop, target, control].inspect if ENV["CDDL_TRACE"]
727
751
  if conop == :cat || conop == :plus || conop == :det
728
752
  ok1, v1, vt1 = extract_value(target)
729
753
  ok2, v2, vt2 = extract_value(control)
@@ -956,6 +980,19 @@ module CDDL
956
980
  }
957
981
  end
958
982
 
983
+ def validate1a_ignore_encoding(d, where)
984
+ if String === d
985
+ validate1a(d.force_encoding(Encoding::BINARY), where) or (
986
+ text = d.force_encoding(Encoding::UTF_8).scrub {
987
+ fail "can't use bytes as text"
988
+ } rescue :NOT_A_TEXT_STRING
989
+ validate1a(text, where)
990
+ )
991
+ else
992
+ validate1a(d, where)
993
+ end
994
+ end
995
+
959
996
  def validate1a(d, where)
960
997
  if ann = validate1(d, where)
961
998
  here = [d, where]
@@ -968,6 +1005,7 @@ module CDDL
968
1005
  end
969
1006
 
970
1007
  OPERATORS = {lt: :<, le: :<=, gt: :>, ge: :>=, eq: :==, ne: :!=}
1008
+ FLOAT_AI_FROM_SIZE = {3 => 25, 5 => 26, 9 => 27}
971
1009
 
972
1010
  def validate1(d, where)
973
1011
  if ENV["CDDL_TRACE"]
@@ -1014,7 +1052,7 @@ module CDDL
1014
1052
  if conop == :cat || conop == :plus || conop == :det
1015
1053
  ok1, v1, vt1 = extract_value(target)
1016
1054
  ok2, v2, vt2 = extract_value(control)
1017
- # warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect
1055
+ warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
1018
1056
  if ok1 && ok2
1019
1057
  v2 = Integer(v2) if vt1 == Integer
1020
1058
  if conop == :det
@@ -1023,6 +1061,30 @@ module CDDL
1023
1061
  end
1024
1062
  # warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
1025
1063
  [] if d == v1 + v2 # XXX Focus ArgumentError
1064
+ elsif conop == :cat && String === d
1065
+ warn ["CAT-L", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
1066
+ if ok1 && vt1 == String
1067
+ # d and lhs (v1) need to agree in encoding
1068
+ if d.encoding == v1.encoding
1069
+ if d[0...v1.length] == v1
1070
+ d2 = d[v1.length..-1]
1071
+ warn ["CAT-L1", d2, d2.encoding, control].inspect if ENV["CDDL_TRACE"]
1072
+ validate1a_ignore_encoding(d2, control)
1073
+ end
1074
+ end
1075
+ elsif ok2 && vt2 == String
1076
+ warn ["CAT-R", ok1, v1, vt1, ok2, v2, vt2, d].inspect if ENV["CDDL_TRACE"]
1077
+ if d[-v2.length..-1] == v2
1078
+ d1 = d[0...-v2.length]
1079
+ validate1a(d1, control)
1080
+ end
1081
+ end
1082
+ elsif conop == :plus && Integer === d
1083
+ if ok1 && vt1 == Integer
1084
+ validate1a(d - Integer(v1), control)
1085
+ elsif ok2 && vt2 == Integer
1086
+ validate1a(d - Integer(v2), target)
1087
+ end
1026
1088
  end
1027
1089
  elsif ann = validate1a(d, target)
1028
1090
  case conop
@@ -1132,14 +1194,75 @@ module CDDL
1132
1194
  end
1133
1195
  )
1134
1196
  when :join
1135
- ok, *v = extract_array(control)
1136
- # warn "@@@JJJ@@@ #{ok.inspect} #{v.inspect}"
1137
- if ok
1138
- expected = v.map {|ve|
1139
- fail "Not a string in #{where}" unless String === ve[0]
1140
- ve[0]
1141
- }.join
1142
- ann if d == expected
1197
+ t = control
1198
+ v = if t[0] == :array
1199
+ t[1..-1].map { |el|
1200
+ if el[0..2] == [:member, 1, 1]
1201
+ ok, v, vt = extract_value(el[4])
1202
+ if ok
1203
+ [true, v, vt]
1204
+ else
1205
+ [false, el[4]]
1206
+ end
1207
+ end
1208
+ }
1209
+ end
1210
+ warn "@@@JOIN@@@ #{v.inspect}" if ENV["CDDL_TRACE"]
1211
+ ok = true
1212
+ if v
1213
+ ix = 0
1214
+ rest = d.dup
1215
+ while ix < v.length
1216
+ if left = v[ix]
1217
+ if left[0] # match constant value first
1218
+ fail "Not a string for #{left.inspect} in #{where}" unless String == left[2]
1219
+ want = left[1]
1220
+ have = rest[0...left[1].length]
1221
+ if want == have
1222
+ rest[0...left[1].length] = ''
1223
+ ix += 1
1224
+ next
1225
+ else
1226
+ fail ".join: want #{want.inspect}, have #{have.inspect}"
1227
+ end
1228
+ else
1229
+ ix += 1
1230
+ if ix == v.length # match remaining
1231
+ warn "@@@JOIN ok in #{ok.inspect} rest #{rest.inspect}" if ENV["CDDL_TRACE"]
1232
+ ok &&= validate1(rest, left[1])
1233
+ warn "@@@JOIN ok out #{ok.inspect}" if ENV["CDDL_TRACE"]
1234
+ # more diag
1235
+ rest = ''
1236
+ next
1237
+ else
1238
+ if mid = v[ix]
1239
+ if mid[0] # have constant value to split over
1240
+ fail "Not a string for #{mid} in #{where}" unless String == mid[2]
1241
+ rest1, rest2 = rest.split(mid[1], 2)
1242
+ if rest2
1243
+ warn "@@@JOIN ok in #{ok.inspect} rest1 #{rest1.inspect}" if ENV["CDDL_TRACE"]
1244
+ ok &&= validate1(rest1, left[1])
1245
+ warn "@@@JOIN ok out #{ok.inspect}" if ENV["CDDL_TRACE"]
1246
+ rest = rest2
1247
+ ix += 1
1248
+ next
1249
+ else
1250
+ fail "Can't find #{mid[1].inspect} in #{rest.inspect}"
1251
+ end
1252
+ else
1253
+ fail "Cannot validate consecutive non-constant members of .join in #{where}"
1254
+ end
1255
+ else
1256
+ fail "Cannot handle .join over #{t[ix+1]} in #{where}"
1257
+ end
1258
+ end
1259
+ end
1260
+ else
1261
+ fail "Cannot handle .join over #{t[ix+1]} in #{where}"
1262
+ end
1263
+ end
1264
+ fail "Can't match #{rest.inspect} for .join in #{where}" if rest != ''
1265
+ ann if ok
1143
1266
  else
1144
1267
  fail "Don't know yet how to validate against #{where}"
1145
1268
  end
@@ -1148,7 +1271,7 @@ module CDDL
1148
1271
  String === d && (
1149
1272
  decoded = case conop
1150
1273
  when :b64u
1151
- /=/ !~ d &&
1274
+ /[+\/=]/ !~ d &&
1152
1275
  Base64.urlsafe_decode64(d)
1153
1276
  when :"b64u-sloppy"
1154
1277
  /[-_=]/ !~ d &&
@@ -1235,12 +1358,25 @@ module CDDL
1235
1358
  if t
1236
1359
  v.eql? d
1237
1360
  else
1238
- case where[2]
1361
+ case w2 = where[2]
1239
1362
  when nil
1240
- # XXX
1241
- fail [:valnil, d, where].inspect
1363
+ Float === d || CBOR::Simple === d || [false, true, nil].include?(d)
1364
+ when Array
1365
+ headnum = case d
1366
+ when Float
1367
+ FLOAT_AI_FROM_SIZE[d.to_cbor.size]
1368
+ when false
1369
+ 20
1370
+ when true
1371
+ 21
1372
+ when nil
1373
+ 22
1374
+ when CBOR::Simple
1375
+ d.value
1376
+ end
1377
+ validate1a(headnum, w2)
1242
1378
  when 25, 26, 27
1243
- Float === d
1379
+ Float === d && FLOAT_AI_FROM_SIZE[d.to_cbor.size] == w2
1244
1380
  else
1245
1381
  fail [:val7, d, where].inspect
1246
1382
  end
@@ -1589,7 +1725,7 @@ module CDDL
1589
1725
  when /\A#(\d+)/
1590
1726
  maj = $1.to_i
1591
1727
  s = [:prim, maj, *n.children(:uint).map(&:to_s).map(&:to_i)]
1592
- if tn = n.tagnumber
1728
+ if tn = n.headnumber
1593
1729
  if ui = tn.uint
1594
1730
  s << ui.to_s.to_i
1595
1731
  elsif tt = tn.type
@@ -0,0 +1,10 @@
1
+ a = text .b64u bytes
2
+
3
+ ;;gp 10
4
+
5
+ ;;vp "AAAA"
6
+ ;;vp "AAA-"
7
+ ;;vp "AAA_"
8
+ ;;vp "AAA+"
9
+ ;;vp "AAA/"
10
+ ;;vp "AAA="
@@ -1,2 +1,4 @@
1
1
  foo = text .regexp myregexp
2
2
  myregexp = "A" .cat "B"
3
+
4
+ ;;gp 10
@@ -0,0 +1,8 @@
1
+ a1 = '' .cat a2
2
+ a2 = text .b64u ain
3
+ ; a = "e30" .b64u ain
4
+ ain = '{}'
5
+
6
+ ;;gp 3
7
+ ;;vp 'e30'
8
+ ;;vp "e30"
@@ -0,0 +1,3 @@
1
+ a = b<13..15>
2
+ b<T> = #7.<32 .plus T>
3
+ ; cddl dotplus1.cddl gp 10
@@ -0,0 +1,3 @@
1
+ a = d<17..19>
2
+ d<T> = #7.<T .plus 32>
3
+ ; cddl dotplus.cddl gp 10
@@ -0,0 +1,3 @@
1
+ a = d<17..19>
2
+ d<T> = 32.5 .plus T
3
+ ; cddl dotplus4.cddl gp 10
@@ -0,0 +1,3 @@
1
+ a = d<17..19>
2
+ d<T> = T .plus 32.5
3
+ ; cddl dotplus4.cddl gp 10
@@ -0,0 +1,14 @@
1
+ terminal-color = &basecolors
2
+ basecolors = (
3
+ black: 0, red: 1, green: 2, yellow: 3,
4
+ blue: 4, magenta: 5, cyan: 6, white: 7,
5
+ reserved: (8..255) .feature "extension"
6
+ )
7
+ ; extended-color = &(
8
+ ; basecolors,
9
+ ; orange: 8, pink: 9, purple: 10, brown: 11,
10
+ ; )
11
+
12
+ ;;gp 10
13
+ ;;vp 42
14
+ ;;vp 433
@@ -0,0 +1,12 @@
1
+ terminal-color = $terminal-color / text .feature "extension"
2
+ $terminal-color /= &basecolors
3
+ basecolors = (
4
+ black: "black", red: "red", green: "green",
5
+ )
6
+
7
+ pastelcolors = ( pink: "pink", mauve: "mauve", peach: "peach", lavender: "lavender" )
8
+ $terminal-color /= &pastelcolors
9
+
10
+ ;;gp 10
11
+ ;;vp "florp"
12
+ ;;vp "lavender"
@@ -0,0 +1,15 @@
1
+ ; JWT-JWS = text .join ([
2
+ ; b64u<jwt-headers>, ".",
3
+ ; b64u<jwt-payload>, ".",
4
+ ; b64u<jwt-signature>])
5
+ ; ; a = jwt-headers
6
+ ; ; a = b64u<"abc"> ; fails
7
+ ; ; a = b64u<'abc'> ; succeeds
8
+ ; b64u<B> = text .b64u B
9
+ jwt-headers = '' .cat jwt-headers1
10
+ jwt-headers1 = text .json jwt-headermap
11
+ jwt-headermap = { * text => any } ; simplified
12
+ jwt-payload = bytes
13
+ jwt-signature = bytes
14
+
15
+ ;;gp 10
@@ -0,0 +1,15 @@
1
+ JWT-JWS = text .join ([
2
+ b64u<jwt-headers>, ".",
3
+ b64u<jwt-payload>, ".",
4
+ b64u<jwt-signature>])
5
+ ; a = jwt-headers
6
+ ; a = b64u<"abc"> ; fails
7
+ ; a = b64u<'abc'> ; succeeds
8
+ b64u<B> = text .b64u B
9
+ jwt-headers = '' .cat jwt-headers1
10
+ jwt-headers1 = text .json jwt-headermap
11
+ jwt-headermap = { * text => any } ; simplified
12
+ jwt-payload = bytes
13
+ jwt-signature = bytes
14
+
15
+ ;;gp 10
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.7
4
+ version: 0.11.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: 2024-02-26 00:00:00.000000000 Z
11
+ date: 2024-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -163,6 +163,7 @@ files:
163
163
  - test-data/b.cddl
164
164
  - test-data/b64c-sloppy.cddl
165
165
  - test-data/b64c.cddl
166
+ - test-data/b64u-strict.cddl
166
167
  - test-data/b64u.cddl
167
168
  - test-data/badaddr.cddl
168
169
  - test-data/base32.cddl
@@ -173,6 +174,7 @@ files:
173
174
  - test-data/bpv7a.cddl
174
175
  - test-data/bpv7b.cddl
175
176
  - test-data/cat-re.cddl
177
+ - test-data/catb64.cddl
176
178
  - test-data/cdni-ct.cddl
177
179
  - test-data/complex-occ.cddl
178
180
  - test-data/coral.cddl
@@ -185,7 +187,13 @@ files:
185
187
  - test-data/decimal.cddl
186
188
  - test-data/decimal2.cddl
187
189
  - test-data/det1.cddl
190
+ - test-data/dotplus1.cddl
191
+ - test-data/dotplus2.cddl
192
+ - test-data/dotplus3.cddl
193
+ - test-data/dotplus4.cddl
188
194
  - test-data/dotsize.cddl
195
+ - test-data/enum.cddl
196
+ - test-data/enum1.cddl
189
197
  - test-data/extractor-demo.cddl
190
198
  - test-data/feat1.cddl
191
199
  - test-data/feature-controller.cddl
@@ -213,8 +221,10 @@ files:
213
221
  - test-data/joini.cddl
214
222
  - test-data/joinx.cddl
215
223
  - test-data/json.cddl
224
+ - test-data/json1.cddl
216
225
  - test-data/json2.cddl
217
226
  - test-data/jsoniodef.cddl
227
+ - test-data/jwt.cddl
218
228
  - test-data/kevin5.cddl
219
229
  - test-data/lint1.cddl
220
230
  - test-data/map-group.cddl
@@ -280,7 +290,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
280
290
  - !ruby/object:Gem::Version
281
291
  version: '0'
282
292
  requirements: []
283
- rubygems_version: 3.4.10
293
+ rubygems_version: 3.5.4
284
294
  signing_key:
285
295
  specification_version: 4
286
296
  summary: CDDL generator and validator.