1use super::*;
2use crate::asn1::Boolean;
3use vstd::prelude::*;
4
5verus! {
6
7broadcast use super::oid::axiom_disjoint_oids;
8
9pub type ExtensionInner = Mapped<
15 LengthWrapped<
16 Depend<
17 ASN1<ObjectIdentifier>,
18 <ExtensionCont as Continuation>::Output,
19 ExtensionCont,
20 >,
21 >,
22 ExtensionMapper>;
23
24pub type ExtensionsInner = SequenceOf<ASN1<Extension>>;
25
26wrap_combinator! {
27 pub struct Extension: ExtensionInner =>
28 spec SpecExtensionValue,
29 exec<'a> ExtensionValue<'a>,
30 owned ExtensionValueOwned,
31 = Mapped {
32 inner: LengthWrapped(Depend {
33 fst: ASN1(ObjectIdentifier),
34 snd: ExtensionCont,
35 spec_snd: Ghost(|i| ExtensionCont::spec_apply(i)),
36 }),
37 mapper: ExtensionMapper,
38 };
39}
40
41asn1_tagged!(Extension, tag_of!(SEQUENCE));
42
43asn1! {
44 seq of Extensions(ASN1(Extension)): ASN1<Extension>;
45}
46
47mapper! {
48 pub struct ExtensionMapper;
49
50 for <Id, Param>
51 from ExtensionFrom where type ExtensionFrom<Id, Param> = (Id, PairValue<OptionDeep<bool>, Param>);
52 to ExtensionPoly where pub struct ExtensionPoly<Id, Param> {
53 pub id: Id,
54 pub critical: OptionDeep<bool>,
55 pub param: Param,
56 }
57
58 spec SpecExtensionValue with <SpecObjectIdentifierValue, SpecExtensionParamValue>;
59 exec ExtensionValue<'a> with <ObjectIdentifierValue, ExtensionParamValue<'a>>;
60 owned ExtensionValueOwned with <ObjectIdentifierValueOwned, ExtensionParamValueOwned>;
61
62 forward(x) {
63 ExtensionPoly {
64 id: x.0,
65 critical: x.1.0,
66 param: x.1.1,
67 }
68 }
69
70 backward(y) {
71 (y.id, PairValue(y.critical, y.param))
72 }
73}
74
75#[derive(Debug, View)]
78pub struct ExtensionCont;
79
80impl ExtensionCont {
81 pub open spec fn spec_apply(i: SpecObjectIdentifierValue) -> <ExtensionCont as Continuation>::Output {
82 Optional(spec_new_wrapped(ASN1(Boolean)), ExtensionParamCont::spec_apply(i))
83 }
84}
85
86impl Continuation for ExtensionCont {
87 type Input<'a> = ObjectIdentifierValue;
88 type Output = Optional<Wrapped<ASN1<Boolean>>, <ExtensionParamCont as Continuation>::Output>;
89
90 fn apply<'a>(&self, i: Self::Input<'a>) -> (o: Self::Output) {
91 Optional(new_wrapped(ASN1(Boolean)), ExtensionParamCont.apply(i))
92 }
93
94 open spec fn requires<'a>(&self, i: Self::Input<'a>) -> bool {
95 true
96 }
97
98 open spec fn ensures<'a>(&self, i: Self::Input<'a>, o: Self::Output) -> bool {
99 o@ == Self::spec_apply(i@)
100 }
101}
102
103}
104
105#[cfg(test)]
106mod test {
107 use super::*;
108
109 verus! {
110 #[test]
112 fn is_combinator() {
113 let _ = ASN1(Extension).parse(&[]);
114 let _ = ASN1(Extensions).parse(&[]);
115 }
116 }
117
118 #[test]
119 fn sanity() {
120 assert!(ASN1(Extension)
121 .parse(&[
122 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xE4, 0xAF, 0x2B,
123 0x26, 0x71, 0x1A, 0x2B, 0x48, 0x27, 0x85, 0x2F, 0x52, 0x66, 0x2C, 0xEF, 0xF0, 0x89,
124 0x13, 0x71, 0x3E,
125 ])
126 .is_ok());
127
128 assert!(ASN1(Extensions)
129 .parse(&[
130 0x30, 0x40, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04,
131 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF,
132 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
133 0x04, 0x16, 0x04, 0x14, 0xE4, 0xAF, 0x2B, 0x26, 0x71, 0x1A, 0x2B, 0x48, 0x27, 0x85,
134 0x2F, 0x52, 0x66, 0x2C, 0xEF, 0xF0, 0x89, 0x13, 0x71, 0x3E,
135 ])
136 .is_ok());
137 }
138}