cddl 0.1.0 → 0.8.8

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.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/bin/cddl +80 -23
  3. data/cddl.gemspec +4 -2
  4. data/data/cddl.abnf +50 -20
  5. data/data/prelude.cddl +9 -3
  6. data/lib/cbor-pp-play.rb +13 -0
  7. data/lib/cbor-pp.rb +213 -0
  8. data/lib/cddl.rb +1001 -163
  9. data/test/test-cddl.rb +1620 -93
  10. data/test-data/7071-concise-cut.cddl +48 -0
  11. data/test-data/7071-concise.cddl +1 -1
  12. data/test-data/7071-verbose.cddl +1 -1
  13. data/test-data/a.cddl +9 -0
  14. data/test-data/ambig.cddl +2 -0
  15. data/test-data/b.cddl +3 -0
  16. data/test-data/badaddr.cddl +1 -0
  17. data/test-data/basic_syntax_example.cddl +7 -0
  18. data/test-data/cdni-ct.cddl +72 -0
  19. data/test-data/cose.cddl +68 -0
  20. data/test-data/dcaf.cddl +58 -0
  21. data/test-data/dcaf1.cddl +48 -0
  22. data/test-data/dotsize.cddl +7 -0
  23. data/test-data/extractor-demo.cddl +14 -0
  24. data/test-data/grasp-01-extract.cddl +91 -0
  25. data/test-data/grasp-01-test.cddl +90 -0
  26. data/test-data/grasp-01.cddl +90 -0
  27. data/test-data/grasp-09.cddl +108 -0
  28. data/test-data/grasp-v1.cddl +97 -0
  29. data/test-data/grasp-v2X.cddl +89 -0
  30. data/test-data/ifmap-base-2.0v17.cddl +392 -0
  31. data/test-data/ifmap-base-2.2v9_fh-cabo.cddl +149 -0
  32. data/test-data/ifmap-metadata-2.2v9_fh-cabo.cddl +239 -0
  33. data/test-data/ifmap2.cddl +21 -0
  34. data/test-data/jcr-ex.cddl +42 -0
  35. data/test-data/kevin5.cddl +5 -0
  36. data/test-data/map-group.cddl +13 -0
  37. data/test-data/mapkey.cddl +2 -0
  38. data/test-data/minimal.cddl +1 -0
  39. data/test-data/patch1.cddl +13 -0
  40. data/test-data/reused_named_group.cddl +14 -0
  41. data/test-data/structure.cddl +9 -0
  42. data/test-data/toerless0.cddl +14 -0
  43. data/test-data/toerless1.cddl +11 -0
  44. data/test-data/two_anonymous_groups.cddl +13 -0
  45. data/test-data/wrong1.cddl +17 -0
  46. data/test-data/wrong1a.cddl +23 -0
  47. data/test-data/wrong2.cddl +17 -0
  48. data/test-data/wrong2a.cddl +17 -0
  49. data/test-data/xmlmig.cddl +15 -0
  50. metadata +72 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bc6439f876088c1d9355f78363bfa34eaa844613
4
- data.tar.gz: eb88cc041f3a03ef495aeecf4b663af0a2384673
2
+ SHA256:
3
+ metadata.gz: 6c877883cb125426e061f527ba4375c0f021d70dfef060336fe0bb0f5e2ca3d4
4
+ data.tar.gz: 7a3dc4065f3616bf57c229b410782b35140018ecada4418c0ef45056c62aef0b
5
5
  SHA512:
6
- metadata.gz: 449e97a60fb3ee5584b582dc8da13d54de607f99ce02020a5565d7495142a8547965429b9d429582a2c898f8c6680a64d089339ff6c8fe4def07887da9ddd782
7
- data.tar.gz: af6dd64fe9c1267fe4f86fbf4825e7da9faa4be03545991369b647c5766e5735fb1c760341bdf0afb7a4f07f3f7f06279bb1e900c459795eaf150c5c76cbb9a1
6
+ metadata.gz: b3987fbe82e80dddba2f650b1a12941ed6092708297302cf1a78dfe45b20b79d08e85901cb8739b5fc79eab8cde70ca8efb88698f4340da72c722a7a461565c6
7
+ data.tar.gz: 68c35688bac9b30411ee419e171860c463df28c3452bce1741399274e51295b609e0acc8df54e9876037f9d96ba02e369fd9465c2fe7c38bb9682d5ec19018cd
data/bin/cddl CHANGED
@@ -1,42 +1,99 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
+ # require_relative '../lib/cddl'
3
4
  require 'cddl'
4
5
  require 'cbor-diagnostic'
5
6
  require 'json'
6
7
 
7
8
  Encoding.default_external = "UTF-8" # wake up, smell the coffee
8
9
 
10
+ EX_USAGE = 64
11
+ EX_DATAERR = 65
12
+
9
13
  def usage
10
14
  warn "Usage:"
11
15
  warn "#$0 spec.cddl generate [n]"
12
16
  warn "#$0 spec.cddl json-generate [n]"
13
17
  warn "#$0 spec.cddl validate instance.cbor"
14
18
  warn "#$0 spec.cddl validate instance.json"
15
- exit 1
19
+ exit EX_USAGE
20
+ end
21
+
22
+ def read_arg(arg)
23
+ if arg == "-"
24
+ STDIN.read
25
+ else
26
+ usage unless arg
27
+ File.read(arg, mode: "rb")
28
+ end
29
+ end
30
+
31
+ def parser
32
+ @parser ||= CDDL::Parser.new(read_arg(ARGV[0]))
33
+ end
34
+
35
+ def my_pp(v)
36
+ if $annotate
37
+ CBOR::PP.pp v
38
+ else
39
+ pp v
40
+ end
41
+ end
42
+
43
+ def my_diag(v)
44
+ if $annotate
45
+ CBOR::PP.pp v
46
+ else
47
+ puts v.cbor_diagnostic
48
+ end
16
49
  end
17
50
 
18
- case ARGV[1]
19
- when /\Ag/
20
- parser = CDDL::Parser.new(File.read(ARGV[0]))
21
- n = 1
22
- n = ARGV[2].to_i if ARGV[2]
23
- n.times do
24
- g = parser.generate
25
- puts g.cbor_diagnostic
51
+ begin
52
+ case ARGV[1]
53
+ when /\A.p/
54
+ $annotate = true
55
+ require_relative '../lib/cbor-pp'
26
56
  end
27
- when /\Aj/
28
- parser = CDDL::Parser.new(File.read(ARGV[0]))
29
- n = 1
30
- n = ARGV[2].to_i if ARGV[2]
31
- n.times do
32
- g = parser.generate
33
- puts JSON.pretty_generate(g)
57
+ case ARGV[1]
58
+ when /\Ar/ # secret
59
+ $advanced = true
60
+ my_pp parser.rules
61
+ when /\Ae/ # secret
62
+ $advanced = true
63
+ puts parser.defines(ARGV[2])
64
+ when /\Ag/
65
+ n = 1
66
+ n = ARGV[2].to_i if ARGV[2]
67
+ n.times do
68
+ g = parser.generate
69
+ if $annotate
70
+ g = g.cbor_clone if ENV["EXPERIMENTAL_ANNOTATE"]
71
+ ann = parser.validate(g)
72
+ # my_pp ann
73
+ g.cbor_add_annotations_from(ann) rescue nil
74
+ end
75
+ my_diag(g)
76
+ end
77
+ when /\Aj/
78
+ n = 1
79
+ n = ARGV[2].to_i if ARGV[2]
80
+ n.times do
81
+ g = parser.generate
82
+ puts JSON.pretty_generate(g)
83
+ end
84
+ when /\Av/
85
+ instance = read_arg(ARGV[2])
86
+ instance = CBOR.decode(instance.b) rescue JSON.load(instance)
87
+ instance = instance.cbor_clone if $annotate && ENV["EXPERIMENTAL_ANNOTATE"]
88
+ ann = parser.validate(instance)
89
+ # my_pp ann
90
+ instance.cbor_add_annotations_from(ann) rescue nil
91
+ my_diag(instance) if $annotate
92
+ exit 1 unless ann
93
+ else
94
+ usage
34
95
  end
35
- when /\Av/
36
- parser = CDDL::Parser.new(File.read(ARGV[0]))
37
- instance = File.read(ARGV[2])
38
- instance = CBOR.decode(instance) rescue JSON.load(instance)
39
- p parser.validate(instance)
40
- else
41
- usage
96
+ rescue CDDL::ParseError => e
97
+ warn e.message
98
+ exit EX_DATAERR
42
99
  end
data/cddl.gemspec CHANGED
@@ -1,17 +1,19 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.1.0'
3
+ s.version = '0.8.8'
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('regexp-examples') # , '1.1.0')
10
+ s.add_dependency('colorize')
9
11
  s.files = `git ls-files`.split("\n").grep(/^[a-z]/)
10
12
  s.files = Dir['lib/**/*.rb'] + %w(cddl.gemspec) + Dir['data/**/*.abnf'] + Dir['data/**/*.cddl'] + Dir['test-data/**/*.cddl'] + Dir['test/**/*.rb']
11
13
  s.require_path = 'lib'
12
14
  s.executables = ['cddl']
13
15
  s.default_executable = 'cddl'
14
- s.required_ruby_version = '>= 1.9.2'
16
+ s.required_ruby_version = '>= 2.0'
15
17
  s.author = "Carsten Bormann"
16
18
  s.email = "cabo@tzi.org"
17
19
  s.homepage = "http://github.com/cabo/cddl"
data/data/cddl.abnf CHANGED
@@ -1,30 +1,45 @@
1
1
  cddl = S 1*rule
2
- rule = typename S "=" S type S
3
- / groupname S "=" S group S
2
+ rule = typename [genericparm] S assign S type S
3
+ / groupname [genericparm] S assign S grpent S
4
4
 
5
5
  typename = id
6
6
  groupname = id
7
7
 
8
+ assign = "=" / "/=" / "//="
9
+
10
+ genericparm = "<" S id S *("," S id S ) ">"
11
+ genericarg = "<" S type1 S *("," S type1 S ) ">"
12
+
8
13
  type = type1 S *("/" S type1 S)
9
14
 
10
- type1 = value
15
+ type1 = type2 [S (rangeop / annotator) S type2]
11
16
  / "#" "6" ["." uint] "(" S type S ")" ; note no space!
12
17
  / "#" DIGIT ["." uint] ; major/ai
13
18
  / "#" ; any
14
19
  / "{" S group S "}"
15
20
  / "[" S group S "]"
16
- / "(" type ")"
17
- / typename
21
+ / "&" S "(" S group S ")"
22
+ / "&" S groupname [genericarg]
23
+
24
+ type2 = value
25
+ / typename [genericarg]
26
+ / "(" type ")"
27
+
28
+ rangeop = "..." / ".."
29
+
30
+ annotator = "." id
18
31
 
19
- group = "(" S *grpent S ")"
20
- / *grpent
32
+ group = grpchoice S *("//" S grpchoice S)
21
33
 
22
- grpent = [occur S] [memberkey S] type1 optcom
23
- / [occur S] groupname optcom ; always preempted by previous...
34
+ grpchoice = *grpent
24
35
 
25
- memberkey = membername S ":"
26
- membername = bareword ; note that this can be a typename
27
- / type1 ; can be preempted by previous...
36
+ grpent = [occur S] [memberkey S] type optcom
37
+ / [occur S] groupname [genericarg] optcom ; preempted by above
38
+ / [occur S] "(" S group S ")" optcom
39
+
40
+ memberkey = type1 S "=>"
41
+ / bareword S ":"
42
+ / value S ":"
28
43
 
29
44
  bareword = id
30
45
 
@@ -34,25 +49,39 @@ occur = [uint] "*" [uint]
34
49
  / "+"
35
50
  / "?"
36
51
 
37
- uint = "0"
38
- / DIGIT1 *DIGIT
52
+ uint = DIGIT1 *DIGIT
53
+ / "0x" 1*HEXDIG
54
+ / "0b" 1*BINDIG
55
+ / "0"
39
56
 
40
- value = int
41
- / float
42
- / string
57
+ value = number
58
+ / text
59
+ / bytes
43
60
 
44
61
  int = ["-"] uint
45
62
 
46
- float = int ["." 1*DIGIT] ["e" int ]
63
+ ; This is a float if it has fraction or exponent; int otherwise
64
+ number = int ["." fraction] ["e" exponent ]
65
+ fraction = 1*DIGIT
66
+ exponent = int
47
67
 
48
- string = %x22 *SCHAR %x22
68
+ text = %x22 *SCHAR %x22
49
69
  SCHAR = %x20-21 / %x23-7E / SESC
50
70
  SESC = "\" %x20-7E
51
71
 
52
- id = ALPHA *(ALPHA / DIGIT / "_" / "-")
72
+ bytes = [bsqual] %x27 *BCHAR %x27
73
+ BCHAR = %x20-26 / %x28-7E / SESC / CRLF
74
+ bsqual = %x68 ; "h"
75
+ / %x62.36.34 ; "b64"
76
+
77
+ id = EALPHA *(*("-" / ".") (EALPHA / DIGIT))
53
78
  ALPHA = %x41-5A / %x61-7A
79
+ EALPHA = %x41-5A / %x61-7A / "@" / "_" / "$"
54
80
  DIGIT = %x30-39
55
81
  DIGIT1 = %x31-39
82
+ HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
83
+ BINDIG = %x30-31
84
+
56
85
  S = *WS
57
86
  WS = SP / NL
58
87
  SP = %x20
@@ -60,3 +89,4 @@ NL = COMMENT / CRLF
60
89
  COMMENT = ";" *(SP / VCHAR) CRLF
61
90
  VCHAR = %x21-7E
62
91
  CRLF = %x0A / %x0D.0A
92
+
data/data/prelude.cddl CHANGED
@@ -7,20 +7,23 @@ nint = #1
7
7
  int = uint / nint
8
8
 
9
9
  bstr = #2
10
+ bytes = bstr
10
11
  tstr = #3
12
+ text = tstr
11
13
 
12
- tdate = #6.0(tstr)
14
+ tdate = #6.0(tstr .regexp "\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\\d|3[0-1])[Tt]([0-1]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)(\\.\\d+)?([Zz]|[+\\-](?:[0-1]\\d|2[0-3]):[0-5]\\d)")
13
15
  time = #6.1(number)
14
16
  number = int / float
15
17
  biguint = #6.2(bstr)
16
18
  bignint = #6.3(bstr)
17
19
  bigint = biguint / bignint
18
20
  integer = int / bigint
21
+ unsigned = uint / biguint
19
22
  decfrac = #6.4([e10: int, m: integer])
20
23
  bigfloat = #6.5([e2: int, m: integer])
21
24
  eb64url = #6.21(any)
22
- eb64legacy = #6.21(any)
23
- eb16 = #6.21(any)
25
+ eb64legacy = #6.22(any)
26
+ eb16 = #6.23(any)
24
27
  encoded-cbor = #6.24(bstr)
25
28
  uri = #6.32(tstr)
26
29
  b64url = #6.33(tstr)
@@ -38,6 +41,9 @@ float = float16-32 / float64
38
41
 
39
42
  false = #7.20
40
43
  true = #7.21
44
+ bool = false / true
41
45
  nil = #7.22
46
+ null = nil
42
47
  undefined = #7.23
43
48
 
49
+ used_in_cddl_prelude = any / bytes / tdate / time / number / biguint / bignint / bigint / integer / unsigned / decfrac / bigfloat / eb64url / eb64legacy / eb16 / encoded-cbor / uri / b64url / b64legacy / regexp / mime-message / cbor-any / float16 / float32 / float64 / float16-32 / float32-64 / float / false / true / bool / null / undefined / uint / nint / int / text
@@ -0,0 +1,13 @@
1
+ require_relative "cbor-pp"
2
+
3
+ a = [1, {foo: "bar", busel: "basel", baz: "bass", ant: "cat", bat: "dog", eel: "fox"},
4
+ 2, 3, 4, [3]*55, "foo".b, 0.00006103515625, 0.0000099, 1e-7, nil]
5
+ a[1].cbor_annotation_add "fasel"
6
+ CBOR::PP.pp a
7
+
8
+ a = [1, "baz", 3]
9
+ a.cbor_annotation_add "foo"
10
+ a[1].cbor_annotation_add "bar"
11
+ CBOR::PP.pp(a)
12
+
13
+ p 1.cbor_annotation_format
data/lib/cbor-pp.rb ADDED
@@ -0,0 +1,213 @@
1
+ require 'prettyprint'
2
+ require 'cbor-diagnostic'
3
+ require 'delegate'
4
+
5
+ class CBOR::PP < PrettyPrint
6
+ # Outputs +obj+ to +out+ in pretty printed format of
7
+ # +width+ columns in width.
8
+ #
9
+ # If +out+ is omitted, <code>$></code> is assumed.
10
+ # If +width+ is omitted, 79 is assumed.
11
+ #
12
+ # CBOR::PP.pp returns +out+.
13
+ def self.pp(obj, out=$>, width=79)
14
+ q = new(out, width)
15
+ q.pp obj
16
+ q.flush
17
+ #$pp = q
18
+ out << "\n"
19
+ end
20
+
21
+ module PPMethods
22
+ # Adds +obj+ to the pretty printing buffer
23
+ # using Object#cbor_pp.
24
+ def pp(obj)
25
+ group {obj.cbor_pp self}
26
+ end
27
+
28
+ # XXX: a nested group that is broken should not have things added at the end
29
+ def comma_breakable
30
+ text ','
31
+ fill_breakable
32
+ end
33
+
34
+ def seplist(list, sep=nil, iter_method=:each) # :yield: element
35
+ sep ||= lambda { comma_breakable }
36
+ first = true
37
+ list.__send__(iter_method) {|*v|
38
+ if first
39
+ first = false
40
+ else
41
+ sep.call
42
+ end
43
+ yield(*v)
44
+ }
45
+ end
46
+
47
+ # A pretty print for a Hash
48
+ def pp_hash(obj, anno)
49
+ s = "#{anno}{"
50
+ group(1, s, '}') {
51
+ seplist(obj, nil, :each_pair) {|k, v|
52
+ group {
53
+ pp k
54
+ text ':'
55
+ group(1) {
56
+ breakable ' '
57
+ pp v
58
+ }
59
+ }
60
+ }
61
+ }
62
+ end
63
+ end
64
+
65
+ include PPMethods
66
+
67
+ module ObjectMixin # :nodoc:
68
+ def cbor_pp(q)
69
+ if @cbor_annotation
70
+ q.text cbor_annotation_format
71
+ end
72
+ q.text cbor_diagnostic
73
+ end
74
+ def cbor_annotation_add(v)
75
+ unless frozen?
76
+ @cbor_annotation ||= []
77
+ @cbor_annotation << v unless @cbor_annotation.include? v
78
+ end
79
+ end
80
+ def cbor_annotation_replace(v)
81
+ @cbor_annotation = [v]
82
+ end
83
+ def cbor_annotations
84
+ @cbor_annotation
85
+ end
86
+ def cbor_annotation_format
87
+ if @cbor_annotation
88
+ "/" << @cbor_annotation.join(", ") << "/ "
89
+ end
90
+ end
91
+ def cbor_add_annotations_from(ann_list)
92
+ _data, anno = ann_list.find{|data, _anno| equal?(data)}
93
+ f = anno.cbor_annotations
94
+ f.each {|a| cbor_annotation_add(a)} if f
95
+ end
96
+ def cbor_clone
97
+ if frozen?
98
+ CBOR::PP::Cloak.new(self)
99
+ else
100
+ self
101
+ end
102
+ end
103
+ def eql?(other)
104
+ if other.respond_to? :__getobj__
105
+ eql? other.__getobj__
106
+ else
107
+ super
108
+ end
109
+ end
110
+ end
111
+
112
+ module EqlMixin
113
+ def eql?(other)
114
+ if other.respond_to? :__getobj__
115
+ eql? other.__getobj__
116
+ else
117
+ super
118
+ end
119
+ end
120
+ # def ==(other)
121
+ # eql?(other) || super
122
+ # end
123
+ end
124
+
125
+ def self.add_annotations(tree, ann_list)
126
+ tree.cbor_add_annotations_from(ann_list)
127
+ end
128
+
129
+ class Cloak < ::SimpleDelegator
130
+ def class
131
+ @delegate_sd_obj.class
132
+ end
133
+ include CBOR::PP::ObjectMixin
134
+ end
135
+ end
136
+
137
+ class Class
138
+ def ===(other)
139
+ if other.respond_to? :__getobj__
140
+ other.__getobj__.kind_of? self
141
+ else
142
+ other.kind_of? self
143
+ end
144
+ end
145
+ end
146
+
147
+ class String
148
+ def cbor_clone
149
+ frozen? ? dup : self
150
+ end
151
+ end
152
+
153
+ class Array # :nodoc:
154
+ def cbor_pp(q) # :nodoc:
155
+ s = "#{cbor_annotation_format}["
156
+ q.group(1, s, ']') {
157
+ q.seplist(self) {|v|
158
+ q.pp v
159
+ }
160
+ }
161
+ end
162
+ def cbor_add_annotations_from(ann_list)
163
+ super
164
+ each {|m| m.cbor_add_annotations_from(ann_list)}
165
+ end
166
+ def cbor_clone
167
+ map(&:cbor_clone)
168
+ end
169
+ end
170
+
171
+ class Hash # :nodoc:
172
+ def cbor_pp(q) # :nodoc:
173
+ q.pp_hash self, cbor_annotation_format
174
+ end
175
+ def cbor_add_annotations_from(ann_list)
176
+ super
177
+ each {|k, v|
178
+ # k.cbor_add_annotations_from(ann_list)
179
+ v.cbor_add_annotations_from(ann_list)
180
+ }
181
+ end
182
+ def cbor_clone
183
+ # to_a.cbor_clone.to_h # this breaks for unknown reasons
184
+ h = {}
185
+ each {|k, v| h[k.cbor_clone] = v.cbor_clone}
186
+ each {|k, v| fail [h, k, k.cbor_clone, h[k], v].inspect unless h[k] == v}
187
+ h
188
+ end
189
+ end
190
+
191
+ class Float # Hmm.
192
+ prepend CBOR::PP::EqlMixin
193
+ end
194
+
195
+ class Numeric
196
+ prepend CBOR::PP::EqlMixin
197
+ end
198
+
199
+ class TrueClass
200
+ prepend CBOR::PP::EqlMixin
201
+ end
202
+
203
+ class FalseClass
204
+ prepend CBOR::PP::EqlMixin
205
+ end
206
+
207
+ class NilClass
208
+ prepend CBOR::PP::EqlMixin
209
+ end
210
+
211
+ class Object < BasicObject # :nodoc:
212
+ include CBOR::PP::ObjectMixin
213
+ end