cddl 0.8.8 → 0.8.15

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: 6c877883cb125426e061f527ba4375c0f021d70dfef060336fe0bb0f5e2ca3d4
4
- data.tar.gz: 7a3dc4065f3616bf57c229b410782b35140018ecada4418c0ef45056c62aef0b
3
+ metadata.gz: e7b1df5544e11b299155468f15b649f61bf3d281644a0917be5eec9aa099f8bd
4
+ data.tar.gz: c29c65aec8cec554d0ca3e837dafd2cbb18bdec41552666c6f81db52f189e491
5
5
  SHA512:
6
- metadata.gz: b3987fbe82e80dddba2f650b1a12941ed6092708297302cf1a78dfe45b20b79d08e85901cb8739b5fc79eab8cde70ca8efb88698f4340da72c722a7a461565c6
7
- data.tar.gz: 68c35688bac9b30411ee419e171860c463df28c3452bce1741399274e51295b609e0acc8df54e9876037f9d96ba02e369fd9465c2fe7c38bb9682d5ec19018cd
6
+ metadata.gz: 5ba99f5a974fb235e2dfeea4fd55dd8feb2fa15a558e5fe77c1c8a921ccacd83c7f292bb767bda835616cb484d86015cd8c2d6a81a675f889c7f751079d62a54
7
+ data.tar.gz: b5b18dada347123ed8d7b664987a441820ff73c8ead7146b00b310249f54ef8a6f6ed156c90cf32dd92ad682f9c974664e3986066240ecc7ae996520ae37b231
data/bin/cddl CHANGED
@@ -50,11 +50,15 @@ end
50
50
 
51
51
  begin
52
52
  case ARGV[1]
53
- when /\A.p/
53
+ when /\A..*p/
54
54
  $annotate = true
55
55
  require_relative '../lib/cbor-pp'
56
56
  end
57
57
  case ARGV[1]
58
+ when /\A..*s/
59
+ $sequence = true
60
+ end
61
+ case ARGV[1]
58
62
  when /\Ar/ # secret
59
63
  $advanced = true
60
64
  my_pp parser.rules
@@ -83,7 +87,11 @@ begin
83
87
  end
84
88
  when /\Av/
85
89
  instance = read_arg(ARGV[2])
86
- instance = CBOR.decode(instance.b) rescue JSON.load(instance)
90
+ instance = if $sequence
91
+ CBOR.decode("\x9f".b << instance.b << "\xff".b)
92
+ else
93
+ CBOR.decode(instance.b) rescue JSON.load(instance)
94
+ end
87
95
  instance = instance.cbor_clone if $annotate && ENV["EXPERIMENTAL_ANNOTATE"]
88
96
  ann = parser.validate(instance)
89
97
  # my_pp ann
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.8.8'
3
+ s.version = '0.8.15'
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')
@@ -19,3 +19,4 @@ spec = Gem::Specification.new do |s|
19
19
  s.homepage = "http://github.com/cabo/cddl"
20
20
  s.license = 'MIT'
21
21
  end
22
+
data/data/cddl.abnf CHANGED
@@ -16,6 +16,7 @@ type1 = type2 [S (rangeop / annotator) S type2]
16
16
  / "#" "6" ["." uint] "(" S type S ")" ; note no space!
17
17
  / "#" DIGIT ["." uint] ; major/ai
18
18
  / "#" ; any
19
+ / "~" S typename [genericarg]
19
20
  / "{" S group S "}"
20
21
  / "[" S group S "]"
21
22
  / "&" S "(" S group S ")"
data/lib/cddl.rb CHANGED
@@ -329,8 +329,12 @@ module CDDL
329
329
  unless kr
330
330
  case vr[0]
331
331
  when :grpent
332
- fail "grpent in map #{vr.inspect}" unless vr.size == 2
333
- g = Array.new(st) { generate1(vr[1], true) }.flatten(1)
332
+ # fail "grpent in map #{vr.inspect}" unless vr.size == 2
333
+ g = Array.new(st) {
334
+ vr[1..-1].map{ |vrx|
335
+ generate1(vrx, true)
336
+ }.flatten(1)
337
+ }.flatten(1)
334
338
  # warn "GGG #{g.inspect}"
335
339
  return g
336
340
  when :grpchoice
@@ -435,6 +439,31 @@ module CDDL
435
439
  $default_warned = true
436
440
  end
437
441
  generate1(target, inmap)
442
+ when :feature
443
+ generate1(target, inmap)
444
+ when :cat
445
+ lhs = generate1(target, inmap)
446
+ rhs = generate1(control)
447
+ begin
448
+ lhs + rhs
449
+ rescue Exception => e
450
+ fail "Can't #{lhs.inspect} .cat #{rhs.inspect}: #{e.message}"
451
+ end
452
+ when :plus
453
+ lhs = generate1(target, inmap)
454
+ rhs = generate1(control)
455
+ begin
456
+ case lhs
457
+ when Integer
458
+ lhs + Integer(rhs)
459
+ when Numeric
460
+ lhs + rhs
461
+ else
462
+ fail "#{lhs.inspect}: Not a number"
463
+ end
464
+ rescue Exception => e
465
+ fail "Can't #{lhs.inspect} .plus #{rhs.inspect}: #{e.message}"
466
+ end
438
467
  when :eq
439
468
  content = generate1(control)
440
469
  if validate1(content, where)
@@ -523,7 +552,7 @@ module CDDL
523
552
  end
524
553
  end
525
554
 
526
- VALUE_TYPE = {text: String, int: Integer, float: Float}
555
+ VALUE_TYPE = {text: String, bytes: String, int: Integer, float: Float}
527
556
  SIMPLE_VALUE = {
528
557
  [:prim, 7, 20] => [true, false, :bool],
529
558
  [:prim, 7, 21] => [true, true, :bool],
@@ -536,9 +565,34 @@ module CDDL
536
565
  [true, t[1], vt]
537
566
  elsif v = SIMPLE_VALUE[t]
538
567
  v
539
- else
540
- [false]
541
- end
568
+ elsif t[0] == :anno
569
+ _, conop, target, control = t
570
+ # warn ["EXV0", conop, target, control].inspect
571
+ if conop == :cat || conop == :plus
572
+ ok1, v1, vt1 = extract_value(target)
573
+ ok2, v2, vt2 = extract_value(control)
574
+ # warn ["EXV", ok1, v1, vt1, ok2, v2, vt2].inspect
575
+ if ok1 && ok2
576
+ if vt1 == Integer
577
+ [true, v1 + Integer(v2), Integer] if vt2 == Integer || vt2 == Float
578
+ elsif vt1 == Float
579
+ [true, v1 + v2, vt1] if vt2 == Integer || vt2 == Float
580
+ else
581
+ [true, v1 + v2, vt1] if vt1 == vt2
582
+ end
583
+ end rescue nil
584
+ end
585
+ end || [false]
586
+ end
587
+
588
+ def extract_array(t)
589
+ return [false] unless t[0] == :array
590
+ [true, *t[1..-1].map { |el|
591
+ return [false] unless el[0..3] == [:member, 1, 1, nil]
592
+ ok, v, vt = extract_value(el[4])
593
+ return [false] unless ok
594
+ [v, vt]
595
+ }]
542
596
  end
543
597
 
544
598
  def validate_diag
@@ -547,11 +601,17 @@ module CDDL
547
601
 
548
602
  def validate(d, warn=true)
549
603
  @recursion = 0
604
+ $features = Hash.new {|h, k| h[k] = {}}
550
605
  result = validate1a(d, rules)
551
- unless result
552
- if warn
606
+ if warn
607
+ if result
608
+ if $features != {}
609
+ warn "** Features potentially used: #{$features.map {|k, v| "#{k}: #{v.keys}"}.join(", ")}"
610
+ end
611
+ else
553
612
  warn "CDDL validation failure (#{result.inspect} for #{d.inspect}):"
554
613
  PP::pp(validate_diag, STDERR)
614
+ puts(validate_diag.cbor_diagnostic)
555
615
  end
556
616
  end
557
617
  result
@@ -741,16 +801,27 @@ module CDDL
741
801
  idx, ann = validate_forward(d, 0, where)
742
802
  ann if validate_result(idx == d.size) { "#{validate_diag.inspect} -- cannot complete (#{idx}, #{d.size}) array #{d} for #{where}" }
743
803
  end
744
- when :text, :int, :float, :bytes
804
+ when :int, :float
745
805
  _, v = extract_value(where)
746
806
  [] if d == v
807
+ when :text, :bytes
808
+ _, v = extract_value(where)
809
+ [] if d == v && ((d.encoding == Encoding::BINARY) == (v.encoding == Encoding::BINARY))
747
810
  when :range
748
811
  [] if where[2] === d && where[1].include?(d)
749
812
  when :anno
750
- target = where[2]
751
- if ann = validate1a(d, target)
752
- control = where[3]
753
- case where[1]
813
+ _, conop, target, control = where
814
+ if conop == :cat || conop == :plus
815
+ ok1, v1, vt1 = extract_value(target)
816
+ ok2, v2, vt2 = extract_value(control)
817
+ # warn ["ANNO0", ok1, v1, vt1, ok2, v2, vt2, d].inspect
818
+ if ok1 && ok2
819
+ v2 = Integer(v2) if vt1 == Integer
820
+ # warn ["ANNO", ok1, v1, vt1, ok2, v2, vt2, d].inspect
821
+ [] if d == v1 + v2 # XXX Focus ArgumentError
822
+ end
823
+ elsif ann = validate1a(d, target)
824
+ case conop
754
825
  when :size
755
826
  case d
756
827
  when Integer
@@ -789,8 +860,24 @@ module CDDL
789
860
  $default_warned = true
790
861
  end
791
862
  ann
863
+ when :feature
864
+ ok, v, vt = extract_value(control)
865
+ if ok
866
+ nm = v
867
+ det = d
868
+ else
869
+ ok, *v = extract_array(control)
870
+ if ok && v.size == 2
871
+ nm = v[0][0]
872
+ det = v[1][0]
873
+ else
874
+ warn "*** feature controller not implemented: #{control.inspect}"
875
+ end
876
+ end
877
+ $features[nm][det] = true
878
+ ann
792
879
  when :lt, :le, :gt, :ge, :eq, :ne
793
- op = OPERATORS[where[1]]
880
+ op = OPERATORS[conop]
794
881
  ok, v, _vt = extract_value(control)
795
882
  if ok
796
883
  ann if d.send(op, v) rescue nil # XXX Focus ArgumentError
@@ -837,6 +924,14 @@ module CDDL
837
924
  when 3
838
925
  String === d && d.encoding != Encoding::BINARY # cheat
839
926
  when 6
927
+ if Integer === d
928
+ t = 2 # assuming only 2/3 match an Integer
929
+ if d < 0
930
+ d = ~d
931
+ t = 3
932
+ end
933
+ d = CBOR::Tagged.new(t, d == 0 ? "".b : d.digits(256).reverse!.pack("C*"))
934
+ end
840
935
  CBOR::Tagged === d && d.tag == where[2] && validate1a(d.data, where[3])
841
936
  when 7
842
937
  t, v = extract_value(where)
@@ -959,7 +1054,7 @@ module CDDL
959
1054
  when ""
960
1055
  parts[1].b
961
1056
  when "h"
962
- parts[1].gsub(/\s/, "").chars.each_slice(2).map{ |x| Integer(x.join, 16).chr("BINARY") }.join
1057
+ parts[1].gsub(/\s/, "").chars.each_slice(2).map{ |x| Integer(x.join, 16).chr("BINARY") }.join.b
963
1058
  when "b64"
964
1059
  Base64.urlsafe_decode64(parts[1])
965
1060
  else
@@ -1142,7 +1237,7 @@ module CDDL
1142
1237
  end
1143
1238
  when :recurse_grpent # XXX we don't have the entry yet
1144
1239
  when :member
1145
- fail "map entry without member key given: #{member}" unless member[3] || member[4][0] == :grpent || member[4][0] == :grpchoice
1240
+ fail "map entry #{member.inspect} without member key given: #{member}" unless member[3] || member[4][0] == :grpent || member[4][0] == :grpchoice
1146
1241
  else
1147
1242
  fail ["type1 member", member].inspect unless member[0] == :member
1148
1243
  end
@@ -1152,7 +1247,7 @@ module CDDL
1152
1247
  BRACE = {"{" => :map, "[" => :array}
1153
1248
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
1154
1249
  SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp, :cbor, :cborseq, :within, :and,
1155
- :default, :lt, :le, :gt, :ge, :eq, :ne]
1250
+ :default, :lt, :le, :gt, :ge, :eq, :ne, :feature, :cat, :plus]
1156
1251
 
1157
1252
  def type1(n, canbegroup = false)
1158
1253
  # puts "NVALUE #{n.value.inspect}"
@@ -1214,6 +1309,26 @@ module CDDL
1214
1309
  v
1215
1310
  }
1216
1311
  ]
1312
+ when /\A~/
1313
+ if tn = n.typename
1314
+ s = type_recall(tn.to_s, false, n.genericarg).flatten(1)
1315
+ else
1316
+ fail "No typename in unwrap #{n}"
1317
+ end
1318
+ if s[0] != :type1
1319
+ fail [:UNWRAPs0, s].inspect
1320
+ end
1321
+ case s[1]
1322
+ when :map, :array
1323
+ [:grpent, s[2..-1]]
1324
+ when :prim
1325
+ if s[2] != 6
1326
+ fail [:UNWRAPs2, s].inspect
1327
+ end
1328
+ s[4] # check :type1?
1329
+ else
1330
+ fail [:UNWRAPs1, s].inspect
1331
+ end
1217
1332
  else
1218
1333
  "unimplemented #{n}"
1219
1334
  end
data/test/test-cddl.rb CHANGED
@@ -171,6 +171,57 @@ HERE
171
171
  assert parser.validate_for_test(true)
172
172
  end
173
173
 
174
+ def test_validate_bignum
175
+ parser = CDDL::Parser.new <<HERE
176
+ test = bigint
177
+ HERE
178
+ assert parser.validate_for_test(2**4711)
179
+ assert parser.validate_for_test(-2**815)
180
+ assert parser.validate_for_test(1)
181
+ assert parser.validate_for_test(0)
182
+ assert parser.validate_for_test(-11)
183
+ end
184
+
185
+ def test_aaaaaaaa_invalidate_bignum
186
+ parser = CDDL::Parser.new <<HERE
187
+ test = bignint
188
+ HERE
189
+ refute parser.validate_for_test(2**4711, false)
190
+ assert parser.validate_for_test(-2**815)
191
+ refute parser.validate_for_test(1, false)
192
+ refute parser.validate_for_test(0, false)
193
+ assert parser.validate_for_test(-11)
194
+ end
195
+
196
+
197
+ def test_aaaaaaaa_validate_bignum0b
198
+ parser = CDDL::Parser.new <<HERE
199
+ test = #6.2("")
200
+ HERE
201
+ refute parser.validate_for_test(1, false)
202
+ refute parser.validate_for_test(0, false)
203
+ end
204
+
205
+
206
+ def test_aaaaaaaa_validate_bignum0
207
+ parser = CDDL::Parser.new <<HERE
208
+ test = #6.2(h'')
209
+ HERE
210
+ assert parser.validate_for_test(0)
211
+ refute parser.validate_for_test(1, false)
212
+ end
213
+
214
+
215
+ def test_aaaaaaaa_validate_bignum1
216
+ parser = CDDL::Parser.new <<HERE
217
+ test = #6.2(h'01')
218
+ HERE
219
+ assert parser.validate_for_test(1)
220
+ refute parser.validate_for_test(0, false)
221
+ refute parser.validate_for_test(2, false)
222
+ end
223
+
224
+
174
225
  def test_validate_a
175
226
  parser = CDDL::Parser.new <<HERE
176
227
  test = [* one: 1]
@@ -0,0 +1,14 @@
1
+ coap-problem-details = {
2
+ type => uint,
3
+ ? title => text,
4
+ ? response-code => bstr .size 1,
5
+ ? detail => text,
6
+ ? instance => uri,
7
+ * $$coap-problem-details-extension,
8
+ }
9
+
10
+ type = 0
11
+ title = 1
12
+ response-code = 2
13
+ detail = 3
14
+ instance = 4
@@ -0,0 +1 @@
1
+ abignum = unsigned
@@ -0,0 +1,136 @@
1
+ start = bundle
2
+
3
+ dtn-time = uint
4
+
5
+ creation-timestamp = [dtn-time, sequence: uint]
6
+
7
+ eid-generic = [uri-code, SSP: any]
8
+
9
+ uri-code = uint
10
+
11
+ eid = eid-choice .within eid-generic
12
+
13
+ eid-choice /= [dtn-code, SSP: (text / 0)]
14
+
15
+ dtn-code = 1 ; TBD
16
+
17
+ eid-choice /= [ipn-code, SSP: [nodenum: uint, servicenum: uint]]
18
+
19
+ ipn-code = 2 ; TBD
20
+
21
+ bundle-control-flags = uint .bits bundleflagbits
22
+
23
+ bundleflagbits = &(
24
+
25
+ reserved: 15
26
+
27
+ reserved: 14
28
+
29
+ reserved: 13
30
+
31
+ bundle-deletion-status-reports-are-requested: 12
32
+
33
+ bundle-delivery-status-reports-are-requested: 11
34
+
35
+ bundle-forwarding-status-reports-are-requested: 10
36
+
37
+ reserved: 9
38
+
39
+ bundle-reception-status-reports-are-requested: 8
40
+
41
+ bundle-contains-a-Manifest-block: 7
42
+
43
+ status-time-is-requested-in-all-status-reports: 6
44
+
45
+ user-application-acknowledgement-is-requested: 5
46
+
47
+ reserved: 4
48
+
49
+ reserved: 3
50
+
51
+ bundle-must-not-be-fragmented: 2
52
+
53
+ payload-is-an-administrative-record: 1
54
+
55
+ bundle-is-a-fragment: 0
56
+
57
+ )
58
+
59
+ crc = bytes
60
+
61
+ block-control-flags = uint .bits blockflagbits
62
+
63
+ blockflagbits = &(
64
+
65
+ reserved: 7
66
+
67
+ reserved: 6
68
+
69
+ reserved: 5
70
+
71
+ reserved: 4
72
+
73
+ bundle-must-be-deleted-if-block-cannot-be-processed: 3
74
+
75
+ status-report-must-be-transmitted-if-block-cannot-be-processed: 2
76
+
77
+ block-must-be-removed-from-bundle-if-it-cannot-be-processed: 1
78
+
79
+ block-must-be-replicated-in-every-fragment: 0
80
+
81
+ )
82
+
83
+ bundle = [primary-block, *extension-block, payload-block]
84
+
85
+ primary-block = [
86
+
87
+ version: 7,
88
+
89
+ bundle-control-flags,
90
+
91
+ crc-type: uint,
92
+
93
+ destination: eid,
94
+
95
+ source-node: eid,
96
+
97
+ report-to: eid,
98
+
99
+ creation-timestamp,
100
+
101
+ lifetime: uint,
102
+
103
+ ? fragment-offset: uint,
104
+
105
+ ? total-application-data-length: uint,
106
+
107
+ ? crc,
108
+
109
+ ]
110
+
111
+ canonical-block = [
112
+
113
+ block-type-code: uint,
114
+
115
+ canonical-block-common,
116
+
117
+ ? crc
118
+
119
+ ]
120
+
121
+ canonical-block-common = (
122
+
123
+ block-number: uint,
124
+
125
+ block-control-flags,
126
+
127
+ crc-type: uint,
128
+
129
+ block-type-specific-data: bytes
130
+
131
+ )
132
+
133
+
134
+ payload-block = ([block-type-code: 1, canonical-block-common, ?crc]) .within canonical-block
135
+
136
+ extension-block = ([block-type-code: (uint .ne 1), canonical-block-common, ?crc]) .within canonical-block
@@ -0,0 +1,181 @@
1
+ start = bundle / #6.55799(bundle)
2
+
3
+ ; Times before 2000 are invalid
4
+ dtn-time = uint
5
+
6
+ ; CRC enumerated type
7
+ crc-type = 0 / 1 / 2
8
+ ; Either 16-bit or 32-bit
9
+ crc-value = (bstr .size 2) / (bstr .size 4)
10
+
11
+ creation-timestamp = [dtn-time, sequence: uint]
12
+
13
+ eid = $eid-choice .within eid-structure
14
+ eid-structure = [
15
+ uri-code: uint,
16
+ SSP: any
17
+ ]
18
+ $eid-choice /= [
19
+ uri-code: 1,
20
+ SSP: (tstr / 0)
21
+ ]
22
+ $eid-choice /= [
23
+ uri-code: 2,
24
+ SSP: [
25
+ nodenum: uint,
26
+ servicenum: uint
27
+ ]
28
+ ]
29
+
30
+ bundle-control-flags = uint .bits bundleflagbits
31
+ bundleflagbits = &(
32
+ reserved: 15
33
+ reserved: 14
34
+ reserved: 13
35
+ bundle-deletion-status-reports-are-requested: 12
36
+ bundle-delivery-status-reports-are-requested: 11
37
+ bundle-forwarding-status-reports-are-requested: 10
38
+ reserved: 9
39
+ bundle-reception-status-reports-are-requested: 8
40
+ bundle-contains-a-Manifest-block: 7
41
+ status-time-is-requested-in-all-status-reports: 6
42
+ user-application-acknowledgement-is-requested: 5
43
+ reserved: 4
44
+ reserved: 3
45
+ bundle-must-not-be-fragmented: 2
46
+ payload-is-an-administrative-record: 1
47
+ bundle-is-a-fragment: 0
48
+ )
49
+
50
+ block-control-flags = uint .bits blockflagbits
51
+ blockflagbits = &(
52
+ reserved: 7
53
+ reserved: 6
54
+ reserved: 5
55
+ reserved: 4
56
+ bundle-must-be-deleted-if-block-cannot-be-processed: 3
57
+ status-report-must-be-transmitted-if-block-cannot-be-processed: 2
58
+ block-must-be-removed-from-bundle-if-it-cannot-be-processed: 1
59
+ block-must-be-replicated-in-every-fragment: 0
60
+ )
61
+
62
+ bundle = [primary-block, *extension-block, payload-block]
63
+
64
+ primary-block = [
65
+ version: 7,
66
+ bundle-control-flags,
67
+ crc-type,
68
+ destination: eid,
69
+ source-node: eid,
70
+ report-to: eid,
71
+ creation-timestamp,
72
+ lifetime: uint,
73
+ ? (
74
+ fragment-offset: uint,
75
+ ; total-application-data-length: uint,
76
+ )
77
+ ? crc-value,
78
+ ]
79
+
80
+ ; Abstract shared structure of all non-primary blocks
81
+ canonical-block-structure = [
82
+ block-type-code: uint,
83
+ block-number: uint,
84
+ block-control-flags,
85
+ crc-type,
86
+ ; Each block type defines the content within the bytestring
87
+ block-type-specific-data,
88
+ ? crc-value
89
+ ]
90
+ block-type-specific-data = bstr / #6.24(bstr)
91
+ ; Extension block type, which does not specialize any more than the code/number
92
+ extension-block = $extension-block-structure .within canonical-block-structure
93
+ $extension-block-structure = [
94
+ block-type-code: (uint .gt 1),
95
+ extension-block-number,
96
+ block-control-flags,
97
+ crc-type,
98
+ ($extension-block-data .within block-type-specific-data)
99
+ ? crc-value
100
+ ]
101
+ extension-block-number = (uint .ne 0)
102
+ ; Payload block type
103
+ payload-block = payload-block-structure .within canonical-block-structure
104
+ payload-block-structure = [
105
+ block-type-code: 1,
106
+ block-number: 0,
107
+ block-control-flags,
108
+ crc-type,
109
+ ($payload-block-data .within block-type-specific-data)
110
+ ? crc-value
111
+ ]
112
+
113
+ ; Arbitrary payload data
114
+ $payload-block-data /= bstr
115
+
116
+
117
+ ; Administrative record as a payload data specialization
118
+ $payload-block-data /= block-type-specific-data .cbor admin-record
119
+ admin-record = $admin-record .within admin-record-structure
120
+ admin-record-structure = [
121
+ record-type-code: uint,
122
+ record-content: any
123
+ ]
124
+ ; Only one defined record type
125
+ $admin-record /= [1, status-record-content]
126
+ status-record-content = [
127
+ bundle-status-information,
128
+ status-report-reason-code: uint,
129
+ source-node-eid: eid,
130
+ subject-creation-timestamp: creation-timestamp,
131
+ ? (
132
+ subject-payload-offset: uint,
133
+ subject-payload-length: uint
134
+ )
135
+ ]
136
+ bundle-status-information = [
137
+ reporting-node-received-bundle: status-info-content,
138
+ reporting-node-forwarded-bundle: status-info-content,
139
+ reporting-node-delivered-bundle: status-info-content,
140
+ reporting-node-deleted-bundle: status-info-content
141
+ ]
142
+ status-info-content = [
143
+ status-indicator: bool,
144
+ ? timestamp: dtn-time
145
+ ]
146
+
147
+ ; Previous Node extension block
148
+ $extension-block-structure /= [
149
+ block-type-code: 7,
150
+ extension-block-number,
151
+ block-control-flags,
152
+ crc-type,
153
+ (block-type-specific-data .cbor ext-data-previous-node)
154
+ ? crc-value
155
+ ]
156
+ ext-data-previous-node = eid
157
+
158
+ ; Bundle Age extension block
159
+ $extension-block-structure /= [
160
+ block-type-code: 8,
161
+ extension-block-number,
162
+ block-control-flags,
163
+ crc-type,
164
+ (block-type-specific-data .cbor ext-data-bundle-age)
165
+ ? crc-value
166
+ ]
167
+ ext-data-bundle-age = uint
168
+
169
+ ; Hop Count extension block
170
+ $extension-block-structure /= [
171
+ block-type-code: 9,
172
+ extension-block-number,
173
+ block-control-flags,
174
+ crc-type,
175
+ (block-type-specific-data .cbor ext-data-hop-count)
176
+ ? crc-value
177
+ ]
178
+ ext-data-hop-count = [
179
+ hop-limit: uint,
180
+ hop-count: uint
181
+ ]