1use crate::asn1::{ASN1Fmt, BerLength, BerLengthFmt, Class, Tag, TagFmt, BER};
3use crate::combinators::{
4 bytes::ExactLen, mapped::spec::FnSpecMapper, Bind, Const, Mapped, Pair, PrefixTagged, Sum,
5};
6use crate::core::exec::input::InputBuf;
7use crate::core::exec::parser::*;
8use crate::core::exec::{
9 ByteLen, OutputBuf, PResult, Parser, PreSerializeError, Prepare, Serializer,
10};
11use crate::core::{proof::*, spec::*};
12use vstd::prelude::*;
13
14use super::any::{parse_discard_eoc, EocFmt, EocValue, EOC};
15use Sum::Inl as L;
16use Sum::Inr as R;
17
18verus! {
19
20type BerSequenceWireType<T> = (BerLength, Sum<T, (T, EocValue)>);
21
22type BerSequenceFmt__<C> = Mapped<
23 PrefixTagged<
24 TagFmt,
25 Tag,
26 Bind<BerLengthFmt, spec_fn(BerLength) -> Sum<ExactLen<C, usize>, Pair<C, EocFmt>>>,
27 >,
28 FnSpecMapper<BerSequenceWireType<<C as SpecByteLen>::T>, <C as SpecByteLen>::T>,
29>;
30
31pub open spec fn ber_sequence_fmt<C: SpecCombinator>(tag: Tag, content: C) -> BerSequenceFmt__<C> {
37 #[verusfmt::skip]
38 Mapped {
39 inner: PrefixTagged(TagFmt, tag, Bind(BerLengthFmt, |len: BerLength|
40 match len {
41 BerLength::Definite(len) => L(ExactLen(len, content)),
42 BerLength::Indefinite => R(Pair(content, EOC)),
43 },
44 ),
45 ),
46 mapper: (
47 |parsed: BerSequenceWireType<C::T>|
48 match parsed.1 {
49 L(value) => value,
50 R((value, _eoc)) => value,
51 },
52 |value: C::T| {
53 let len = content.byte_len(value) as usize;
54 (BerLength::Definite(len), L(value))
55 },
56 ),
57 }
58}
59
60pub open spec fn ber_sequence_normalized_fmt<C>(tag: Tag, content: C) -> ASN1Fmt<C, BER> {
62 ASN1Fmt(tag, content)
63}
64
65#[derive(Copy)]
70pub struct BerSequenceFmt<C>(pub Tag, pub C);
71
72impl<C: Clone> Clone for BerSequenceFmt<C> {
73 fn clone(&self) -> (cloned: Self)
74 ensures
75 cloned.0 == self.0,
76 call_ensures(C::clone, (&self.1,), cloned.1),
77 {
78 BerSequenceFmt(self.0, self.1.clone())
79 }
80}
81
82impl<C: Copy> BerSequenceFmt<C> {
83 #[verifier::allow_in_spec]
85 pub const fn universal(content: C) -> Self
86 returns
87 Self(TagFmt::SEQUENCE, content),
88 {
89 Self(TagFmt::SEQUENCE, content)
90 }
91
92 #[verifier::allow_in_spec]
94 pub const fn implicit(class: Class, number: u64, content: C) -> Self
95 returns
96 Self(
97 Tag {
98 class,
99 constructed: true,
100 number: crate::asn1::tag::tag_num_from_uint(number),
101 },
102 content,
103 ),
104 {
105 Self(
106 Tag { class, constructed: true, number: crate::asn1::tag::tag_num_from_uint(number) },
107 content,
108 )
109 }
110}
111
112mod derived_specs {
113 use super::*;
114
115 impl<C: SpecCombinator> SpecParser for BerSequenceFmt<C> {
116 type PVal = C::T;
117
118 open spec fn spec_parse(&self, ibuf: Seq<u8>) -> Option<(int, Self::PVal)> {
119 ber_sequence_fmt(self.0, self.1).spec_parse(ibuf)
120 }
121 }
122
123 impl<C: SpecCombinator> Consistency for BerSequenceFmt<C> {
124 type Val = C::T;
125
126 open spec fn consistent(&self, value: Self::Val) -> bool {
127 ber_sequence_fmt(self.0, self.1).consistent(value)
128 }
129 }
130
131 impl<C: SpecCombinator> SpecSerializerDps for BerSequenceFmt<C> {
132 type SValue = C::T;
133
134 open spec fn spec_serialize_dps(&self, value: Self::SValue, obuf: Seq<u8>) -> Seq<u8> {
135 ber_sequence_fmt(self.0, self.1).spec_serialize_dps(value, obuf)
136 }
137 }
138
139 impl<C: SpecCombinator> SpecSerializer for BerSequenceFmt<C> {
140 type SVal = C::T;
141
142 open spec fn spec_serialize(&self, value: Self::SVal) -> Seq<u8> {
143 ber_sequence_fmt(self.0, self.1).spec_serialize(value)
144 }
145 }
146
147 impl<C: SpecCombinator> SpecByteLen for BerSequenceFmt<C> {
148 type T = C::T;
149
150 open spec fn byte_len(&self, value: Self::T) -> nat {
151 ber_sequence_fmt(self.0, self.1).byte_len(value)
152 }
153 }
154
155}
156
157mod derived_proofs {
158 use super::*;
159
160 impl<C: SpecCombinator + SafeParser> SafeParser for BerSequenceFmt<C> {
161 open spec fn safe_inv(&self) -> bool {
162 self.1.safe_inv()
163 }
164
165 proof fn lemma_parse_safe(&self, ibuf: Seq<u8>) {
166 ber_sequence_fmt(self.0, self.1).lemma_parse_safe(ibuf);
167 }
168 }
169
170 impl<C: SpecCombinator + SafeParser + Productive> Productive for BerSequenceFmt<C> {
171 open spec fn productive_inv(&self) -> bool {
172 self.1.safe_inv()
173 }
174
175 proof fn lemma_productive(&self, ibuf: Seq<u8>) {
176 ber_sequence_fmt(self.0, self.1).lemma_productive(ibuf);
177 }
178 }
179
180 impl<C: SpecCombinator + GoodSerializer> GoodSerializer for BerSequenceFmt<C> {
181 open spec fn serialize_inv(&self) -> bool {
182 self.1.serialize_inv()
183 }
184
185 proof fn lemma_serialize_len(&self, value: Self::SVal) {
186 ber_sequence_normalized_fmt(self.0, self.1).lemma_serialize_len(value);
187 }
188 }
189
190 impl<C: SpecCombinator + GoodSerializer + EquivSerializers> NonTailFmt for BerSequenceFmt<C> {
191 open spec fn serialize_dps_inv(&self) -> bool {
192 &&& self.1.serialize_inv()
193 &&& self.1.equiv_inv()
194 }
195
196 proof fn lemma_serialize_dps_prepend(&self, value: Self::SValue, obuf: Seq<u8>) {
197 ber_sequence_normalized_fmt(self.0, self.1).lemma_serialize_dps_prepend(value, obuf);
198 }
199
200 proof fn lemma_serialize_dps_len(&self, value: Self::SValue, obuf: Seq<u8>) {
201 ber_sequence_normalized_fmt(self.0, self.1).lemma_serialize_dps_len(value, obuf);
202 }
203 }
204
205 impl<C: SpecCombinator + EquivSerializers> EquivSerializersGeneral for BerSequenceFmt<C> {
206 open spec fn equiv_general_inv(&self) -> bool {
207 self.1.equiv_inv()
208 }
209
210 proof fn lemma_serialize_equiv(&self, value: Self::SVal, obuf: Seq<u8>) {
211 ber_sequence_normalized_fmt(self.0, self.1).lemma_serialize_equiv(value, obuf);
212 }
213 }
214
215 impl<C: SpecCombinator + EquivSerializers> EquivSerializers for BerSequenceFmt<C> {
216 open spec fn equiv_inv(&self) -> bool {
217 self.1.equiv_inv()
218 }
219
220 proof fn lemma_serialize_equiv_on_empty(&self, value: Self::SVal) {
221 self.lemma_serialize_equiv(value, Seq::empty());
222 }
223 }
224
225 impl<C> SPRoundTripDps for BerSequenceFmt<C> where
226 C: SpecCombinator + GoodSerializer + EquivSerializers + SPRoundTripDps,
227 {
228 open spec fn unambiguous(&self) -> bool {
229 ber_sequence_normalized_fmt(self.0, self.1).unambiguous()
230 }
231
232 proof fn theorem_serialize_dps_parse_roundtrip(&self, value: Self::T, obuf: Seq<u8>) {
233 let normalized = ber_sequence_normalized_fmt(self.0, self.1);
234 normalized.theorem_serialize_dps_parse_roundtrip(value, obuf);
235 let len = self.1.byte_len(value) as usize;
236 let exact = ExactLen(len, self.1);
237 exact.theorem_serialize_dps_parse_roundtrip(value, obuf);
238 let content_suffix = exact.spec_serialize_dps(value, obuf);
239 BerLengthFmt.theorem_serialize_dps_parse_roundtrip(
240 BerLength::Definite(len),
241 content_suffix,
242 );
243 let length_suffix = BerLengthFmt.spec_serialize_dps(
244 BerLength::Definite(len),
245 content_suffix,
246 );
247 BerLengthFmt.lemma_serialize_dps_prepend(BerLength::Definite(len), content_suffix);
248 BerLengthFmt.lemma_serialize_dps_len(BerLength::Definite(len), content_suffix);
249 let length_len = BerLengthFmt.byte_len(BerLength::Definite(len)) as int;
250 TagFmt.theorem_serialize_dps_parse_roundtrip(self.0, length_suffix);
251 TagFmt.lemma_serialize_dps_prepend(self.0, length_suffix);
252 TagFmt.lemma_serialize_dps_len(self.0, length_suffix);
253
254 }
255 }
256
257}
258
259impl<'i, C> Parser<&'i [u8]> for BerSequenceFmt<C> where
260 C: SpecCombinator + Parser<&'i [u8]> + SafeParser + Copy,
261 {
262 type PT = C::PT;
263
264 open spec fn exec_inv(&self) -> bool {
265 &&& self.1.exec_inv()
266 &&& self.1.safe_inv()
267 }
268
269 fn parse(&self, ibuf: &&'i [u8]) -> PResult<Self::PT> {
270 broadcast use crate::core::spec::SafeParser::lemma_parse_safe;
271 broadcast use crate::asn1::tag::lemma_const_tag_fmt_exec_inv;
272
273 let _ = ibuf.len();
274 let (tag_len, _tag) = Const(TagFmt, self.0).parse(ibuf)?;
275 let after_tag = ibuf.skip(tag_len);
276 let (length_len, length) = BerLengthFmt.parse(&after_tag)?;
277 let content = after_tag.skip(length_len);
278
279 let (content_len, value) = match length {
280 BerLength::Definite(len) => ExactLen(len, self.1).parse(&content)?,
281 BerLength::Indefinite => {
282 let framed = Pair(self.1, EOC);
283 proof {
284 crate::core::exec::bridge_lemmas::lemma_pair_parser_exec_inv::<&'i [u8], _, _>(
285 &EOC,
286 );
287 crate::core::exec::bridge_lemmas::lemma_pair_parser_exec_inv::<&'i [u8], _, _>(
288 &framed,
289 );
290 }
291 parse_discard_eoc(&framed, &content)?
292 },
293 };
294 let total = tag_len + length_len + content_len;
295 assert(self.spec_parse(ibuf@) == Some((total as int, value.deep_view())));
296 Ok((total, value))
297 }
298}
299
300impl<Output: OutputBuf, C, T> Serializer<Output, T> for BerSequenceFmt<C> where
301 T: DeepView + ?Sized,
302 C: SpecCombinator + Serializer<Output, T> + ByteLen<T> + Copy,
303 {
304 #[verifier::prophetic]
305 open spec fn exec_inv(&self) -> bool {
306 &&& <C as Serializer<Output, T>>::exec_inv(&self.1)
307 &&& <C as ByteLen<T>>::exec_inv(&self.1)
308 }
309
310 fn serialize_into(&self, value: &T, obuf: &mut Output) {
311 let normalized = ASN1Fmt::<_, BER>(self.0, self.1);
312 normalized.serialize_into(value, obuf);
313 }
314}
315
316impl<C, T> Prepare<T> for BerSequenceFmt<C> where
317 T: DeepView + ?Sized,
318 C: SpecCombinator + Prepare<T> + Copy,
319 {
320 open spec fn exec_inv(&self) -> bool {
321 <C as Prepare<T>>::exec_inv(&self.1)
322 }
323
324 fn prepare(&self, value: &T) -> Result<usize, PreSerializeError> {
325 let normalized = ASN1Fmt::<_, BER>(self.0, self.1);
326 normalized.prepare(value)
327 }
328}
329
330impl<C, T> ByteLen<T> for BerSequenceFmt<C> where
331 T: DeepView + ?Sized,
332 C: SpecCombinator + ByteLen<T> + Copy,
333 {
334 open spec fn exec_inv(&self) -> bool {
335 <C as ByteLen<T>>::exec_inv(&self.1)
336 }
337
338 fn length(&self, value: &T) -> usize {
339 let normalized = ASN1Fmt::<_, BER>(self.0, self.1);
340 normalized.length(value)
341 }
342}
343
344}