cddl 0.1.4 → 0.1.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 +4 -4
- data/bin/cddl +9 -1
- data/cddl.gemspec +1 -1
- data/lib/cddl.rb +50 -26
- data/test/test-cddl.rb +76 -24
- metadata +3 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae990c0c1e630a5f206d115bc5ae8cbc2e5612cd
|
|
4
|
+
data.tar.gz: 7ff78e8928e1cd3e7f60fa1086e6b055b23e39d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 25cb1b61914141616819edfbcfa2a7de955295a1c1863f22ed6af85700f5cc1fa9897c6cbf51a9bcd65814f927f026e389fd80c916713e07a195a2b42dbb5136
|
|
7
|
+
data.tar.gz: 042f0f7497d609872bfce8b95da45d98a273a06092c67d2816704618497067910add06f4bf88abfa7d066cc90dff30f19ead71f43dc2ddcceb10e61b57866a23
|
data/bin/cddl
CHANGED
|
@@ -15,8 +15,16 @@ def usage
|
|
|
15
15
|
exit 1
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def read_arg(arg)
|
|
19
|
+
if arg == "-"
|
|
20
|
+
STDIN.read
|
|
21
|
+
else
|
|
22
|
+
File.read(arg)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
18
26
|
def parser
|
|
19
|
-
@parser ||= CDDL::Parser.new(
|
|
27
|
+
@parser ||= CDDL::Parser.new(read_arg(ARGV[0]))
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
case ARGV[1]
|
data/cddl.gemspec
CHANGED
data/lib/cddl.rb
CHANGED
|
@@ -10,6 +10,8 @@ module CDDL
|
|
|
10
10
|
PRELUDE = File.read("#{DATA_DIR}/prelude.cddl")
|
|
11
11
|
ABNF_SPEC = File.read("#{DATA_DIR}/cddl.abnf")
|
|
12
12
|
|
|
13
|
+
MANY = Float::INFINITY
|
|
14
|
+
|
|
13
15
|
class Parser
|
|
14
16
|
def initialize(source_text)
|
|
15
17
|
@abnf = Peggy::ABNF.new
|
|
@@ -27,6 +29,8 @@ module CDDL
|
|
|
27
29
|
end
|
|
28
30
|
puts @abnf.ast? if $debug_ast
|
|
29
31
|
@ast = @abnf.ast?
|
|
32
|
+
# our little argument stack for rule processing
|
|
33
|
+
@insides = []
|
|
30
34
|
end
|
|
31
35
|
|
|
32
36
|
def apr # for debugging
|
|
@@ -72,12 +76,11 @@ module CDDL
|
|
|
72
76
|
generate(where[rand(where.size-1)+1])
|
|
73
77
|
when :map
|
|
74
78
|
Hash[where[1..-1].flat_map {|m| generate(m, true)}]
|
|
75
|
-
when :array
|
|
79
|
+
when :array, :grpent
|
|
76
80
|
where[1..-1].flat_map {|m| generate(m).map{|e| e[1]}}
|
|
77
81
|
when :member
|
|
78
82
|
s = where[1]
|
|
79
|
-
e = where[2]
|
|
80
|
-
e = 4 if e == -1
|
|
83
|
+
e = [where[2], [s, 4].max].min # truncate to 4 unless must be more
|
|
81
84
|
s += rand(e + 1 - s) if e != s
|
|
82
85
|
kr = where[3]
|
|
83
86
|
vr = where[4]
|
|
@@ -164,6 +167,36 @@ module CDDL
|
|
|
164
167
|
)
|
|
165
168
|
end
|
|
166
169
|
|
|
170
|
+
def validate_forward(d, start, where)
|
|
171
|
+
i = 0
|
|
172
|
+
where[1..-1].each { |r|
|
|
173
|
+
t, s, e, _k, v = r # XXX
|
|
174
|
+
fail unless t == :member
|
|
175
|
+
occ = 0
|
|
176
|
+
while ((occ < e) && i != d.size && (n = validate_linear(d, start+i, v)))
|
|
177
|
+
i += n
|
|
178
|
+
occ += 1
|
|
179
|
+
end
|
|
180
|
+
if occ < s
|
|
181
|
+
@last_message = "occur not reached in array #{d} for #{where}"
|
|
182
|
+
return false
|
|
183
|
+
end
|
|
184
|
+
}
|
|
185
|
+
i
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# returns number of matches or false for breakage
|
|
189
|
+
def validate_linear(d, start, where)
|
|
190
|
+
fail unless Array === d
|
|
191
|
+
case where[0]
|
|
192
|
+
when :grpent
|
|
193
|
+
# must be inside an array with nested occurrences
|
|
194
|
+
validate_forward(d, start, where)
|
|
195
|
+
else
|
|
196
|
+
validate1(d[start], where) ? 1 : false
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
167
200
|
def validate1(d, where=rules)
|
|
168
201
|
# puts "DATA: #{d.inspect}"
|
|
169
202
|
# puts "RULE: #{where.inspect}"
|
|
@@ -205,21 +238,7 @@ module CDDL
|
|
|
205
238
|
when :array
|
|
206
239
|
if Array === d
|
|
207
240
|
# validate1 against the record
|
|
208
|
-
|
|
209
|
-
i = 0
|
|
210
|
-
where[1..-1].each { |r|
|
|
211
|
-
t, s, e, _k, v = r # XXX
|
|
212
|
-
fail unless t == :member
|
|
213
|
-
occ = 0
|
|
214
|
-
while ((e == -1 || occ < e) && i != d.size && validate1(d[i], v))
|
|
215
|
-
i += 1
|
|
216
|
-
occ += 1
|
|
217
|
-
end
|
|
218
|
-
if occ < s
|
|
219
|
-
@last_message = "occur not reached in array #{d} for #{where}"
|
|
220
|
-
return false
|
|
221
|
-
end
|
|
222
|
-
}
|
|
241
|
+
i = validate_forward(d, 0, where)
|
|
223
242
|
validate_result(i == d.size) { "cannot complete array #{d} for #{where}" }
|
|
224
243
|
end
|
|
225
244
|
when :string, :int, :float
|
|
@@ -310,25 +329,27 @@ module CDDL
|
|
|
310
329
|
else
|
|
311
330
|
type1(n.type1, true) # type1 can be a group here!
|
|
312
331
|
end
|
|
313
|
-
if t[0] == :grpent
|
|
332
|
+
if t[0] == :grpent && (@insides.last == :map || occ == [1, 1])
|
|
314
333
|
# go through the members here and multiply the occs
|
|
315
|
-
# XXX only do this for maps. Keep the structure up for the arrays!
|
|
316
334
|
t1 = t[1..-1].flatten(1)
|
|
317
335
|
t1.flat_map {|t2|
|
|
318
336
|
if t2[0] == :member
|
|
319
337
|
[t2]
|
|
320
338
|
else
|
|
321
|
-
fail unless t2[0] == :grpent
|
|
339
|
+
fail unless t2[0] == :grpent # XXX Where is the nested multiplication here?
|
|
322
340
|
t2[1..-1]
|
|
323
341
|
end
|
|
324
342
|
}.map {|mem|
|
|
325
343
|
# p mem
|
|
326
344
|
mem[1] *= occ[0]
|
|
327
|
-
mem[2] *=
|
|
345
|
+
mem[2] *= occ[1] # Does all the infinity magic
|
|
328
346
|
# p mem
|
|
329
347
|
mem
|
|
330
348
|
}
|
|
331
349
|
else
|
|
350
|
+
if t[0] == :grpent
|
|
351
|
+
t = [t[0], *t[1..-1].flatten(1)]
|
|
352
|
+
end
|
|
332
353
|
[[:member, *occ, nil, t]]
|
|
333
354
|
end
|
|
334
355
|
end
|
|
@@ -407,15 +428,18 @@ module CDDL
|
|
|
407
428
|
when /\A\(/
|
|
408
429
|
type(n.type)
|
|
409
430
|
when /\A[\[{]/
|
|
410
|
-
s = n.children(:group).flat_map {|ch| group(ch)}
|
|
411
431
|
type = BRACE[str[0]]
|
|
432
|
+
@insides << type
|
|
433
|
+
s = n.children(:group).flat_map {|ch| group(ch)}
|
|
434
|
+
@insides.pop
|
|
412
435
|
if type == :map
|
|
413
436
|
s.each do |member|
|
|
414
437
|
fail unless member[0] == :member
|
|
415
438
|
fail "map entry without member key given: #{member}" unless member[3]
|
|
416
439
|
end
|
|
417
|
-
# XXX do the occurrence multiplier here
|
|
440
|
+
# XXX could do the occurrence multiplier here
|
|
418
441
|
end
|
|
442
|
+
# warn s.inspect
|
|
419
443
|
[type, *s]
|
|
420
444
|
else
|
|
421
445
|
"unimplemented #{n}"
|
|
@@ -441,7 +465,7 @@ module CDDL
|
|
|
441
465
|
when ""
|
|
442
466
|
[1, 1]
|
|
443
467
|
when "+"
|
|
444
|
-
[1,
|
|
468
|
+
[1, MANY]
|
|
445
469
|
when "?"
|
|
446
470
|
[0, 1]
|
|
447
471
|
when /\A(\d*)\*(\d*)\z/
|
|
@@ -451,7 +475,7 @@ module CDDL
|
|
|
451
475
|
s = s.to_i
|
|
452
476
|
end
|
|
453
477
|
if (e = $2) == ""
|
|
454
|
-
e =
|
|
478
|
+
e = MANY
|
|
455
479
|
else
|
|
456
480
|
e = e.to_i
|
|
457
481
|
end
|
data/test/test-cddl.rb
CHANGED
|
@@ -21,7 +21,7 @@ class TestABNF < Test::Unit::TestCase
|
|
|
21
21
|
[:array,
|
|
22
22
|
[:member,
|
|
23
23
|
0,
|
|
24
|
-
|
|
24
|
+
CDDL::MANY,
|
|
25
25
|
nil,
|
|
26
26
|
[:map,
|
|
27
27
|
[:member, 1, 1, [:string, "rater"], [:prim, 3]],
|
|
@@ -33,7 +33,7 @@ class TestABNF < Test::Unit::TestCase
|
|
|
33
33
|
[:member, 0, 1, [:string, "sample-size"], [:prim, 0]],
|
|
34
34
|
[:member, 0, 1, [:string, "generated"], [:prim, 0]],
|
|
35
35
|
[:member, 0, 1, [:string, "expires"], [:prim, 0]],
|
|
36
|
-
[:member, 0,
|
|
36
|
+
[:member, 0, CDDL::MANY, [:type1, [:prim]], [:prim]]]]]]]]
|
|
37
37
|
|
|
38
38
|
def test_aa_rfc7071_concise
|
|
39
39
|
parser1 = CDDL::Parser.new(File.read("#{TEST_DATA_DIR}/7071-concise.cddl"))
|
|
@@ -56,7 +56,6 @@ HERE
|
|
|
56
56
|
assert_equal [0x4711, 0b1011001110001111000], parser.generate
|
|
57
57
|
end
|
|
58
58
|
|
|
59
|
-
|
|
60
59
|
def test_validate_person_occurs
|
|
61
60
|
person = <<HERE
|
|
62
61
|
person = (
|
|
@@ -67,19 +66,25 @@ HERE
|
|
|
67
66
|
parser1 = CDDL::Parser.new "unlimitedpersons = [* person ]" + person
|
|
68
67
|
parser2 = CDDL::Parser.new "oneortwoPerson = [1*2 person ]" + person
|
|
69
68
|
parser3 = CDDL::Parser.new "min2Person = [2* person ]" + person
|
|
70
|
-
|
|
69
|
+
|
|
71
70
|
assert parser1.validate([])
|
|
72
71
|
refute parser2.validate([], false)
|
|
73
72
|
refute parser3.validate([], false)
|
|
74
73
|
assert parser1.validate(["Methuselah", 969])
|
|
75
74
|
assert parser2.validate(["Methuselah", 969])
|
|
76
75
|
refute parser3.validate(["Methuselah", 969], false)
|
|
77
|
-
assert parser1.validate(["Methuselah", "Methuselah", 969
|
|
78
|
-
assert parser2.validate(["Methuselah", "Methuselah", 969
|
|
79
|
-
assert parser3.validate(["Methuselah", "Methuselah", 969
|
|
80
|
-
assert parser1.validate(["Methuselah", "Methuselah", "Methuselah", 969
|
|
76
|
+
assert parser1.validate(["Methuselah", 969, "Methuselah", 969])
|
|
77
|
+
assert parser2.validate(["Methuselah", 969, "Methuselah", 969])
|
|
78
|
+
assert parser3.validate(["Methuselah", 969, "Methuselah", 969])
|
|
79
|
+
assert parser1.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969])
|
|
80
|
+
refute parser2.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969], false)
|
|
81
|
+
assert parser3.validate(["Methuselah", 969, "Methuselah", 969, "Methuselah", 969])
|
|
82
|
+
refute parser1.validate(["Methuselah", "Methuselah", 969, 969], false)
|
|
83
|
+
refute parser2.validate(["Methuselah", "Methuselah", 969, 969], false)
|
|
84
|
+
refute parser3.validate(["Methuselah", "Methuselah", 969, 969], false)
|
|
85
|
+
refute parser1.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
|
|
81
86
|
refute parser2.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
|
|
82
|
-
|
|
87
|
+
refute parser3.validate(["Methuselah", "Methuselah", "Methuselah", 969, 969], false)
|
|
83
88
|
end
|
|
84
89
|
|
|
85
90
|
def test_validate
|
|
@@ -215,9 +220,9 @@ HERE
|
|
|
215
220
|
# pp parser.apr
|
|
216
221
|
assert parser.validate([])
|
|
217
222
|
assert parser.validate([1, 2])
|
|
218
|
-
assert parser.validate([1,
|
|
219
|
-
refute parser.validate([1,
|
|
220
|
-
|
|
223
|
+
assert parser.validate([1, 2, 1, 2])
|
|
224
|
+
refute parser.validate([1, 1, 2, 2], false)
|
|
225
|
+
refute parser.validate([1], false)
|
|
221
226
|
refute parser.validate([1, 2, 1], false)
|
|
222
227
|
end
|
|
223
228
|
|
|
@@ -251,7 +256,7 @@ HERE
|
|
|
251
256
|
# puts "APR:"
|
|
252
257
|
# pp parser.apr
|
|
253
258
|
assert parser.validate([])
|
|
254
|
-
|
|
259
|
+
refute parser.validate([1], false)
|
|
255
260
|
assert parser.validate([1, 2])
|
|
256
261
|
refute parser.validate([2, 1], false)
|
|
257
262
|
refute parser.validate([1, 1, 2, 2], false)
|
|
@@ -273,8 +278,8 @@ HERE
|
|
|
273
278
|
refute parser.validate([1], false)
|
|
274
279
|
assert parser.validate([1, 2])
|
|
275
280
|
refute parser.validate([2, 1], false)
|
|
276
|
-
|
|
277
|
-
|
|
281
|
+
refute parser.validate([1, 1, 2, 2], false)
|
|
282
|
+
assert parser.validate([1, 2, 1, 2])
|
|
278
283
|
refute parser.validate([1, 2, 1], false)
|
|
279
284
|
end
|
|
280
285
|
|
|
@@ -289,15 +294,15 @@ HERE
|
|
|
289
294
|
# puts "APR:"
|
|
290
295
|
# pp parser.apr
|
|
291
296
|
assert parser.validate([])
|
|
292
|
-
|
|
297
|
+
refute parser.validate([1], false)
|
|
293
298
|
assert parser.validate([1, 2])
|
|
294
299
|
refute parser.validate([2, 1], false)
|
|
295
|
-
|
|
296
|
-
|
|
300
|
+
refute parser.validate([1, 1, 2, 2], false)
|
|
301
|
+
assert parser.validate([1, 2, 1, 2])
|
|
297
302
|
refute parser.validate([1, 2, 1], false)
|
|
298
303
|
end
|
|
299
304
|
|
|
300
|
-
|
|
305
|
+
|
|
301
306
|
def test_validate_occur23 # XXX need indirection for now
|
|
302
307
|
# $debug_ast = true
|
|
303
308
|
parser = CDDL::Parser.new <<HERE
|
|
@@ -313,11 +318,35 @@ HERE
|
|
|
313
318
|
refute parser.validate([1], false)
|
|
314
319
|
refute parser.validate([1, 2], false)
|
|
315
320
|
refute parser.validate([2, 1], false)
|
|
316
|
-
assert parser.validate([1,
|
|
317
|
-
assert parser.validate([1,
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
refute parser.validate([1,
|
|
321
|
+
assert parser.validate([1, 2, 1, 2])
|
|
322
|
+
assert parser.validate([1, 2, 1, 2, 1, 2])
|
|
323
|
+
refute parser.validate([1, 2, 1, 2, 1, 2, 1, 2], false)
|
|
324
|
+
refute parser.validate([1, 1, 2, 2, 2], false)
|
|
325
|
+
refute parser.validate([1, 1, 1, 2, 2, 2], false)
|
|
326
|
+
refute parser.validate([1, 2, 1], false)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def test_validate_occur12plus1 # XXX need indirection for now
|
|
331
|
+
# $debug_ast = true
|
|
332
|
+
parser = CDDL::Parser.new <<HERE
|
|
333
|
+
test = [1*2 test1 1*1 test1]
|
|
334
|
+
test1 = (one: 1, two: 2)
|
|
335
|
+
HERE
|
|
336
|
+
# puts "RULES:"
|
|
337
|
+
# pp parser.rules
|
|
338
|
+
# puts "APR:"
|
|
339
|
+
# pp parser.apr
|
|
340
|
+
pp parser.generate
|
|
341
|
+
refute parser.validate([], false)
|
|
342
|
+
refute parser.validate([1], false)
|
|
343
|
+
refute parser.validate([1, 2], false)
|
|
344
|
+
refute parser.validate([2, 1], false)
|
|
345
|
+
refute parser.validate([1, 2, 1, 2], false) # !!! PEG semantics gets us here
|
|
346
|
+
assert parser.validate([1, 2, 1, 2, 1, 2])
|
|
347
|
+
refute parser.validate([1, 2, 1, 2, 1, 2, 1, 2], false)
|
|
348
|
+
refute parser.validate([1, 1, 2, 2, 2], false)
|
|
349
|
+
refute parser.validate([1, 1, 1, 2, 2, 2], false)
|
|
321
350
|
refute parser.validate([1, 2, 1], false)
|
|
322
351
|
end
|
|
323
352
|
|
|
@@ -363,5 +392,28 @@ HERE
|
|
|
363
392
|
refute parser.validate(CBOR::Tagged.new(55799, CBOR::Tagged.new(999, [0, "barley", 1])), false)
|
|
364
393
|
end
|
|
365
394
|
|
|
395
|
+
def test_nested_group_many1
|
|
396
|
+
parser = CDDL::Parser.new <<HERE
|
|
397
|
+
foo = {* bar}
|
|
398
|
+
bar = (* b: 1)
|
|
399
|
+
HERE
|
|
400
|
+
assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def test_nested_group_many2
|
|
404
|
+
parser = CDDL::Parser.new <<HERE
|
|
405
|
+
foo = {* bar}
|
|
406
|
+
bar = (b: 1)
|
|
407
|
+
HERE
|
|
408
|
+
assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
def test_nested_group_many3
|
|
412
|
+
parser = CDDL::Parser.new <<HERE
|
|
413
|
+
foo = {* bar}
|
|
414
|
+
bar = (4*6 b: 1)
|
|
415
|
+
HERE
|
|
416
|
+
assert_equal [:type1, [:map, [:member, 0, CDDL::MANY, [:string, "b"], [:int, 1]]]], parser.rules
|
|
417
|
+
end
|
|
366
418
|
|
|
367
419
|
end
|
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.1.
|
|
4
|
+
version: 0.1.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: 2015-03-
|
|
11
|
+
date: 2015-03-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cbor-diag
|
|
@@ -92,9 +92,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
92
92
|
version: '0'
|
|
93
93
|
requirements: []
|
|
94
94
|
rubyforge_project:
|
|
95
|
-
rubygems_version: 2.4.
|
|
95
|
+
rubygems_version: 2.4.6
|
|
96
96
|
signing_key:
|
|
97
97
|
specification_version: 4
|
|
98
98
|
summary: CDDL generator and validator.
|
|
99
99
|
test_files: []
|
|
100
|
-
has_rdoc:
|