1use alloc::{boxed::Box, string::String, vec::Vec};
7
8use crate::asn1::Utf8StringFmt;
9use crate::combinators::{
10 bytes::ExactLen,
11 mapped::spec::{FnSpecMapper, LosslessMapper, LossyMapper, SpecMapper},
12 recursive::{
13 BundledSpecs, EquivSerializersGeneralRecBody, GoodSerializerRecBody, NonMalleableRecBody,
14 NonTailFmtRecBody, ParamRecSpecs, ParserRecBody, PrepareRecBody, ProductiveRecBody,
15 SPRoundTripDpsRecBody, SafeParserRecBody, SerializerRecBody, SoundParserRecBody,
16 SpecRecBody,
17 },
18 Bind, Empty, FixWith, Mapped, Pair, Repeat, RepeatN, Sum, Tail, Void,
19};
20use crate::core::exec::{
21 fns::{FnByteLen, FnParser, FnPrepare, FnSerializer},
22 input::{InputBuf, InputSlice},
23 output::OutputBuf,
24 parser::*,
25 serializer::{ByteLen, PreSerializeError, Prepare, Serializer},
26 ParseError,
27};
28use crate::core::{proof::*, spec::*};
29use crate::Never;
30use vstd::assert_seqs_equal;
31use vstd::prelude::*;
32use vstd::string::StringSliceAdditionalSpecFns;
33
34use super::{
35 CborBytes, CborFloat, CborHead, CborHeadFmt, CborHeadValue, CborText, CborValue, CborValueSpec,
36 MajorType, BREAK, MAX_RECURSION_DEPTH,
37};
38use Sum::Inl as L;
39use Sum::Inr as R;
40
41use super::chunk::{flatten_byte_chunks, flatten_text_chunks, ByteChunkFmt, TextChunkFmt};
42
43verus! {
44
45type CborWire = (
46 CborHead,
47 Sum<
48 (),
49 Sum<
50 (),
51 Sum<
52 Seq<u8>,
53 Sum<
54 (Seq<Seq<u8>>, u8),
55 Sum<
56 Seq<char>,
57 Sum<
58 (Seq<Seq<char>>, u8),
59 Sum<
60 Seq<CborValueSpec>,
61 Sum<
62 (Seq<CborValueSpec>, u8),
63 Sum<
64 Seq<(CborValueSpec, CborValueSpec)>,
65 Sum<
66 (Seq<(CborValueSpec, CborValueSpec)>, u8),
67 Sum<CborValueSpec, Sum<(), Never>>,
68 >,
69 >,
70 >,
71 >,
72 >,
73 >,
74 >,
75 >,
76 >,
77 >,
78);
79
80type CborBranches<Rec, const DET: bool> = Sum<
81 Empty,
82 Sum<
83 Empty,
84 Sum<
85 ExactLen<Tail, u64>,
86 Sum<
87 Repeat<ByteChunkFmt<DET>, super::BreakFmt>,
88 Sum<
89 ExactLen<Utf8StringFmt, u64>,
90 Sum<
91 Repeat<TextChunkFmt<DET>, super::BreakFmt>,
92 Sum<
93 RepeatN<Rec, u64>,
94 Sum<
95 Repeat<Rec, super::BreakFmt>,
96 Sum<
97 RepeatN<Pair<Rec, Rec>, u64>,
98 Sum<
99 Repeat<Pair<Rec, Rec>, super::BreakFmt>,
100 Sum<Rec, Sum<Empty, Void>>,
101 >,
102 >,
103 >,
104 >,
105 >,
106 >,
107 >,
108 >,
109 >,
110>;
111
112type CborParseBodyInnerFmt<Rec, const DET: bool> = Mapped<
113 Bind<CborHeadFmt<DET>, spec_fn(CborHead) -> CborBranches<Rec, DET>>,
114 CborMapper<DET>,
115>;
116
117type NormalizedOnly<T> = Mapped<Void, FnSpecMapper<Never, T>>;
118
119pub open spec fn normalized_only<T>() -> NormalizedOnly<T> {
120 Mapped {
121 inner: Void("indefinite-length form is not emitted"),
122 mapper: (|_never: Never| arbitrary(), |_value: T| arbitrary()),
123 }
124}
125
126type CborNormalizedBranches<Rec, const DET: bool> = Sum<
127 Empty,
128 Sum<
129 Empty,
130 Sum<
131 ExactLen<Tail, u64>,
132 Sum<
133 NormalizedOnly<(Seq<Seq<u8>>, u8)>,
134 Sum<
135 ExactLen<Utf8StringFmt, u64>,
136 Sum<
137 NormalizedOnly<(Seq<Seq<char>>, u8)>,
138 Sum<
139 RepeatN<Rec, u64>,
140 Sum<
141 NormalizedOnly<(Seq<CborValueSpec>, u8)>,
142 Sum<
143 RepeatN<Pair<Rec, Rec>, u64>,
144 Sum<
145 NormalizedOnly<(Seq<(CborValueSpec, CborValueSpec)>, u8)>,
146 Sum<Rec, Sum<Empty, Void>>,
147 >,
148 >,
149 >,
150 >,
151 >,
152 >,
153 >,
154 >,
155 >,
156>;
157
158type CborNormalizedBodyInnerFmt<Rec, const DET: bool> = Mapped<
159 Bind<CborHeadFmt<DET>, spec_fn(CborHead) -> CborNormalizedBranches<Rec, DET>>,
160 CborMapper<DET>,
161>;
162
163pub open spec fn cbor_value_valid(value: CborValueSpec) -> bool {
164 match value {
165 CborValueSpec::Integer(value) => {
166 &&& value as int >= -1 - u64::MAX as int
167 &&& value as int <= u64::MAX as int
168 },
169 CborValueSpec::Bytes(bytes) => bytes.len() <= u64::MAX,
170 CborValueSpec::Text(text) => vstd::utf8::encode_utf8(text).len() <= u64::MAX,
171 CborValueSpec::Array(values) => values.len() <= u64::MAX,
172 CborValueSpec::Map(entries) => entries.len() <= u64::MAX,
173 CborValueSpec::Simple(value) => value <= 19u8 || value >= 32u8,
174 _ => true,
175 }
176}
177
178pub open spec fn cbor_wire_valid<const DET: bool>(wire: CborWire) -> bool {
179 #[verusfmt::skip]
180 match wire {
181 (CborHead { major: MajorType::Unsigned, value: CborHeadValue::Argument(_) }, L(())) => true,
182 (CborHead { major: MajorType::Negative, value: CborHeadValue::Argument(_) }, R(L(()))) => true,
183 (CborHead { major: MajorType::Bytes, value: CborHeadValue::Argument(len) }, R(R(L(bytes)))) => len == bytes.len(),
184 (CborHead { major: MajorType::Bytes, value: CborHeadValue::Indefinite }, R(R(R(L(_))))) => !DET,
185 (CborHead { major: MajorType::Text, value: CborHeadValue::Argument(len) }, R(R(R(R(L(text)))))) => len == vstd::utf8::encode_utf8(text).len(),
186 (CborHead { major: MajorType::Text, value: CborHeadValue::Indefinite }, R(R(R(R(R(L(_))))))) => !DET,
187 (CborHead { major: MajorType::Array, value: CborHeadValue::Argument(len) }, R(R(R(R(R(R(L(values)))))))) => len == values.len(),
188 (CborHead { major: MajorType::Array, value: CborHeadValue::Indefinite }, R(R(R(R(R(R(R(L(_))))))))) => !DET,
189 (CborHead { major: MajorType::Map, value: CborHeadValue::Argument(len) }, R(R(R(R(R(R(R(R(L(entries)))))))))) => len == entries.len(),
190 (CborHead { major: MajorType::Map, value: CborHeadValue::Indefinite }, R(R(R(R(R(R(R(R(R(L(_))))))))))) => !DET,
191 (CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(_) }, R(R(R(R(R(R(R(R(R(R(L(_)))))))))))) => true,
192 (CborHead { major: MajorType::Simple, value }, R(R(R(R(R(R(R(R(R(R(R(L(()))))))))))))) => match value {
193 CborHeadValue::Float(_) => true,
194 CborHeadValue::Simple(value) => value <= 23u8 || value >= 32u8,
195 _ => false,
196 },
197 _ => false,
198 }
199}
200
201pub open spec fn decode_cbor_wire(wire: CborWire) -> CborValueSpec {
202 let head = wire.0;
203 #[verusfmt::skip]
204 match wire.1 {
205 L(()) => match head.value {
206 CborHeadValue::Argument(value) => CborValueSpec::Integer(value as i128),
207 _ => arbitrary(),
208 },
209 R(L(())) => match head.value {
210 CborHeadValue::Argument(value) => CborValueSpec::Integer((-1 - value as int) as i128),
211 _ => arbitrary(),
212 },
213 R(R(L(bytes))) => CborValueSpec::Bytes(bytes),
214 R(R(R(L((chunks, _break))))) => CborValueSpec::Bytes(chunks.flatten()),
215 R(R(R(R(L(text))))) => CborValueSpec::Text(text),
216 R(R(R(R(R(L((chunks, _break))))))) => CborValueSpec::Text(chunks.flatten()),
217 R(R(R(R(R(R(L(values))))))) => CborValueSpec::Array(values),
218 R(R(R(R(R(R(R(L((values, _break))))))))) => CborValueSpec::Array(values),
219 R(R(R(R(R(R(R(R(L(entries))))))))) => CborValueSpec::Map(entries),
220 R(R(R(R(R(R(R(R(R(L((entries, _break))))))))))) => CborValueSpec::Map(entries),
221 R(R(R(R(R(R(R(R(R(R(L(value))))))))))) => match head.value {
222 CborHeadValue::Argument(tag) => CborValueSpec::Tag(tag, Box::new(value)),
223 _ => arbitrary(),
224 },
225 R(R(R(R(R(R(R(R(R(R(R(L(())))))))))))) => match head.value {
226 CborHeadValue::Float(value) => CborValueSpec::Float(value),
227 CborHeadValue::Simple(20) => CborValueSpec::Bool(false),
228 CborHeadValue::Simple(21) => CborValueSpec::Bool(true),
229 CborHeadValue::Simple(22) => CborValueSpec::Null,
230 CborHeadValue::Simple(23) => CborValueSpec::Undefined,
231 CborHeadValue::Simple(value) => CborValueSpec::Simple(value),
232 _ => arbitrary(),
233 },
234 _ => arbitrary(),
235 }
236}
237
238pub open spec fn encode_cbor_value(value: CborValueSpec) -> CborWire {
239 #[verusfmt::skip]
240 match value {
241 CborValueSpec::Integer(value) if value >= 0 => (
242 CborHead { major: MajorType::Unsigned, value: CborHeadValue::Argument(value as u64) },
243 L(()),
244 ),
245 CborValueSpec::Integer(value) => (
246 CborHead {
247 major: MajorType::Negative,
248 value: CborHeadValue::Argument((-1 - value as int) as u64),
249 },
250 R(L(())),
251 ),
252 CborValueSpec::Bytes(bytes) => (
253 CborHead {
254 major: MajorType::Bytes,
255 value: CborHeadValue::Argument(bytes.len() as u64),
256 },
257 R(R(L(bytes))),
258 ),
259 CborValueSpec::Text(text) => (
260 CborHead {
261 major: MajorType::Text,
262 value: CborHeadValue::Argument(vstd::utf8::encode_utf8(text).len() as u64),
263 },
264 R(R(R(R(L(text))))),
265 ),
266 CborValueSpec::Array(values) => (
267 CborHead {
268 major: MajorType::Array,
269 value: CborHeadValue::Argument(values.len() as u64),
270 },
271 R(R(R(R(R(R(L(values))))))),
272 ),
273 CborValueSpec::Map(entries) => (
274 CborHead {
275 major: MajorType::Map,
276 value: CborHeadValue::Argument(entries.len() as u64),
277 },
278 R(R(R(R(R(R(R(R(L(entries))))))))),
279 ),
280 CborValueSpec::Tag(tag, value) => (
281 CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(tag) },
282 R(R(R(R(R(R(R(R(R(R(L(*value))))))))))),
283 ),
284 CborValueSpec::Float(value) => (
285 CborHead { major: MajorType::Simple, value: CborHeadValue::Float(value) },
286 R(R(R(R(R(R(R(R(R(R(R(L(())))))))))))),
287 ),
288 CborValueSpec::Bool(value) => (
289 CborHead {
290 major: MajorType::Simple,
291 value: CborHeadValue::Simple(if value { 21 } else { 20 }),
292 },
293 R(R(R(R(R(R(R(R(R(R(R(L(())))))))))))),
294 ),
295 CborValueSpec::Null => (
296 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(22) },
297 R(R(R(R(R(R(R(R(R(R(R(L(())))))))))))),
298 ),
299 CborValueSpec::Undefined => (
300 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(23) },
301 R(R(R(R(R(R(R(R(R(R(R(L(())))))))))))),
302 ),
303 CborValueSpec::Simple(value) => (
304 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(value) },
305 R(R(R(R(R(R(R(R(R(R(R(L(())))))))))))),
306 ),
307 }
308}
309
310#[derive(Clone, Copy)]
311pub struct CborMapper<const DET: bool>;
312
313impl<const DET: bool> SpecMapper for CborMapper<DET> {
314 type In = CborWire;
315
316 type Out = CborValueSpec;
317
318 open spec fn spec_map(&self, wire: Self::In) -> Self::Out {
319 decode_cbor_wire(wire)
320 }
321
322 open spec fn spec_map_rev(&self, value: Self::Out) -> Self::In {
323 encode_cbor_value(value)
324 }
325
326 open spec fn wf_in(&self, wire: Self::In) -> bool {
327 cbor_wire_valid::<DET>(wire)
328 }
329
330 open spec fn wf_out(&self, value: Self::Out) -> bool {
331 cbor_value_valid(value)
332 }
333}
334
335impl<const DET: bool> LossyMapper for CborMapper<DET> {
336 proof fn lemma_sound_mapper(&self, value: Self::Out) {
337 }
338
339 proof fn lemma_mapper_wf_out_in(&self, value: Self::Out) {
340 }
341}
342
343impl LosslessMapper for CborMapper<true> {
344 proof fn lemma_lossless_mapper(&self, wire: Self::In) {
345 assert(cbor_wire_valid::<true>(wire));
346 assert(encode_cbor_value(decode_cbor_wire(wire)) == wire);
347 }
348
349 proof fn lemma_mapper_wf_in_out(&self, wire: Self::In) {
350 }
351}
352
353#[doc(hidden)]
354pub open spec fn cbor_parse_body<const DET: bool>(
355 rec: ParamRecSpecs<(), CborValueSpec>,
356) -> CborParseBodyInnerFmt<BundledSpecs<CborValueSpec>, DET> {
357 let child = rec(());
358 #[verusfmt::skip]
359 Mapped {
360 inner: Bind(
361 CborHeadFmt::<DET>,
362 |head: CborHead|
363 match head {
364 CborHead { major: MajorType::Unsigned, value: CborHeadValue::Argument(_) } => L(Empty),
365 CborHead { major: MajorType::Negative, value: CborHeadValue::Argument(_) } => R(L(Empty)),
366 CborHead { major: MajorType::Bytes, value: CborHeadValue::Argument(len) } => R(R(L(ExactLen(len, Tail)))),
367 CborHead { major: MajorType::Bytes, value: CborHeadValue::Indefinite } => R(R(R(L(Repeat(ByteChunkFmt::<DET>, BREAK))))),
368 CborHead { major: MajorType::Text, value: CborHeadValue::Argument(len) } => R(R(R(R(L(ExactLen(len, Utf8StringFmt)))))),
369 CborHead { major: MajorType::Text, value: CborHeadValue::Indefinite } => R(R(R(R(R(L(Repeat(TextChunkFmt::<DET>, BREAK))))))),
370 CborHead { major: MajorType::Array, value: CborHeadValue::Argument(len) } => R(R(R(R(R(R(L(RepeatN(len, child)))))))),
371 CborHead { major: MajorType::Array, value: CborHeadValue::Indefinite } => R(R(R(R(R(R(R(L(Repeat(child, BREAK))))))))),
372 CborHead { major: MajorType::Map, value: CborHeadValue::Argument(len) } => R(R(R(R(R(R(R(R(L(RepeatN(len, Pair(child, child))))))))))),
373 CborHead { major: MajorType::Map, value: CborHeadValue::Indefinite } => R(R(R(R(R(R(R(R(R(L(Repeat(Pair(child, child), BREAK))))))))))),
374 CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(_) } => R(R(R(R(R(R(R(R(R(R(L(child))))))))))),
375 CborHead { major: MajorType::Simple, value } if value != CborHeadValue::Break => R(R(R(R(R(R(R(R(R(R(R(L(Empty)))))))))))),
376 _ => R(R(R(R(R(R(R(R(R(R(R(R(Void("invalid CBOR head/value combination"))))))))))))),
377 },
378 ),
379 mapper: CborMapper::<DET>,
380 }
381}
382
383#[doc(hidden)]
384pub open spec fn cbor_normalized_body<const DET: bool>(
385 rec: ParamRecSpecs<(), CborValueSpec>,
386) -> CborNormalizedBodyInnerFmt<BundledSpecs<CborValueSpec>, DET> {
387 let child = rec(());
388 #[verusfmt::skip]
389 Mapped {
390 inner: Bind(
391 CborHeadFmt::<DET>,
392 |head: CborHead|
393 match head {
394 CborHead { major: MajorType::Unsigned, value: CborHeadValue::Argument(_) } => L(Empty),
395 CborHead { major: MajorType::Negative, value: CborHeadValue::Argument(_) } => R(L(Empty)),
396 CborHead { major: MajorType::Bytes, value: CborHeadValue::Argument(len) } => R(R(L(ExactLen(len, Tail)))),
397 CborHead { major: MajorType::Bytes, value: CborHeadValue::Indefinite } => R(R(R(L(normalized_only())))),
398 CborHead { major: MajorType::Text, value: CborHeadValue::Argument(len) } => R(R(R(R(L(ExactLen(len, Utf8StringFmt)))))),
399 CborHead { major: MajorType::Text, value: CborHeadValue::Indefinite } => R(R(R(R(R(L(normalized_only())))))),
400 CborHead { major: MajorType::Array, value: CborHeadValue::Argument(len) } => R(R(R(R(R(R(L(RepeatN(len, child)))))))),
401 CborHead { major: MajorType::Array, value: CborHeadValue::Indefinite } => R(R(R(R(R(R(R(L(normalized_only())))))))),
402 CborHead { major: MajorType::Map, value: CborHeadValue::Argument(len) } => R(R(R(R(R(R(R(R(L(RepeatN(len, Pair(child, child))))))))))),
403 CborHead { major: MajorType::Map, value: CborHeadValue::Indefinite } => R(R(R(R(R(R(R(R(R(L(normalized_only())))))))))),
404 CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(_) } => R(R(R(R(R(R(R(R(R(R(L(child))))))))))),
405 CborHead { major: MajorType::Simple, value } if value != CborHeadValue::Break => R(R(R(R(R(R(R(R(R(R(R(L(Empty)))))))))))),
406 _ => R(R(R(R(R(R(R(R(R(R(R(R(Void("invalid CBOR head/value combination"))))))))))))),
407 },
408 ),
409 mapper: CborMapper::<DET>,
410 }
411}
412
413proof fn lemma_normalized_parse_implies_parse<const DET: bool>(
414 rec: ParamRecSpecs<(), CborValueSpec>,
415 input: Seq<u8>,
416)
417 ensures
418 cbor_normalized_body::<DET>(rec).spec_parse(input) matches Some((n, value))
419 ==> cbor_parse_body::<DET>(rec).spec_parse(input) == Some((n, value)),
420{
421}
422
423proof fn lemma_parse_normalized_consistency<const DET: bool>(
424 rec: ParamRecSpecs<(), CborValueSpec>,
425 value: CborValueSpec,
426)
427 ensures
428 cbor_parse_body::<DET>(rec).consistent(value) == cbor_normalized_body::<DET>(
429 rec,
430 ).consistent(value),
431{
432}
433
434proof fn lemma_parse_normalized_byte_len<const DET: bool>(
435 rec: ParamRecSpecs<(), CborValueSpec>,
436 value: CborValueSpec,
437)
438 ensures
439 cbor_parse_body::<DET>(rec).byte_len(value) == cbor_normalized_body::<DET>(rec).byte_len(
440 value,
441 ),
442{
443}
444
445#[doc(hidden)]
447pub struct CborBodyFmt<const DET: bool> {
448 pub rec: Ghost<ParamRecSpecs<(), CborValueSpec>>,
449}
450
451pub open spec fn cbor_body<const DET: bool>(rec: ParamRecSpecs<(), CborValueSpec>) -> CborBodyFmt<
452 DET,
453> {
454 CborBodyFmt { rec: Ghost(rec) }
455}
456
457pub struct CborRecBody<const DET: bool>;
458
459impl<const DET: bool> SpecRecBody for CborRecBody<DET> {
460 type Param = ();
461
462 type T = CborValueSpec;
463
464 type Body = CborBodyFmt<DET>;
465
466 open spec fn spec_body(&self, _param: (), rec: ParamRecSpecs<(), CborValueSpec>) -> Self::Body {
467 cbor_body::<DET>(rec)
468 }
469}
470
471fn parse_cbor_with_child<'i, const DET: bool, P>(
472 Ghost(spec_rec): Ghost<ParamRecSpecs<(), CborValueSpec>>,
473 child: &P,
474 input: &&'i [u8],
475) -> (result: PResult<CborValue<'i>>) where
476 P: Parser<&'i [u8], PT = CborValue<'i>, PVal = CborValueSpec> + Productive,
477
478 requires
479 child.exec_inv(),
480 child.safe_inv(),
481 child.productive_inv(),
482 parser_congruent(child, spec_rec(())),
483 ensures
484 parse_matches_spec(result, cbor_body::<DET>(spec_rec).spec_parse(input@)),
485{
486 use crate::combinators::congruence::*;
487 use crate::core::exec::bridge_lemmas::*;
488
489 broadcast use crate::core::spec::SafeParser::lemma_parse_safe;
490 broadcast use lemma_parser_congruent_reflexive;
491
492 let _ = input.len();
493 let (head_len, head) = CborHeadFmt::<DET>.parse(input)?;
494 proof {
495 CborHeadFmt::<DET>.lemma_parse_safe(input@);
496 }
497 let rest = input.skip(head_len);
498
499 let ghost child_spec = spec_rec(());
500 proof {
501 lemma_ref_parser_exec_inv::<&'i [u8], _>(child);
502 lemma_ref_safe_productive_inv(child);
503 }
504
505 match head {
506 CborHead { major: MajorType::Unsigned, value: CborHeadValue::Argument(value) } => {
507 Ok((head_len, CborValue::Integer(value as i128)))
508 },
509 CborHead { major: MajorType::Negative, value: CborHeadValue::Argument(value) } => {
510 Ok((head_len, CborValue::Integer(-1i128 - value as i128)))
511 },
512 CborHead { major: MajorType::Bytes, value: CborHeadValue::Argument(len) } => {
513 let (content_len, bytes) = ExactLen(len, Tail).parse(&rest)?;
514 Ok((head_len + content_len, CborValue::Bytes(CborBytes::Definite(bytes))))
515 },
516 CborHead { major: MajorType::Bytes, value: CborHeadValue::Indefinite } => {
517 let repeated = Repeat(ByteChunkFmt::<DET>, BREAK);
518 let (content_len, (chunks, _break)) = repeated.parse(&rest)?;
519 let bytes = flatten_byte_chunks(chunks);
520 Ok((head_len + content_len, CborValue::Bytes(CborBytes::Indefinite(bytes))))
521 },
522 CborHead { major: MajorType::Text, value: CborHeadValue::Argument(len) } => {
523 let (content_len, text) = ExactLen(len, Utf8StringFmt).parse(&rest)?;
524 Ok((head_len + content_len, CborValue::Text(CborText::Definite(text))))
525 },
526 CborHead { major: MajorType::Text, value: CborHeadValue::Indefinite } => {
527 let repeated = Repeat(TextChunkFmt::<DET>, BREAK);
528 let (content_len, (chunks, _break)) = repeated.parse(&rest)?;
529 let text = flatten_text_chunks(chunks);
530 Ok((head_len + content_len, CborValue::Text(CborText::Indefinite(text))))
531 },
532 CborHead { major: MajorType::Array, value: CborHeadValue::Argument(len) } => {
533 let repeated = RepeatN(len, child);
534 proof {
535 lemma_repeat_n_parser_exec_inv::<&'i [u8], _, _>(&repeated);
536 lemma_repeat_n_parser_congruence(repeated, RepeatN(len, child_spec));
537 lemma_parser_congruent_apply(repeated, RepeatN(len, child_spec), rest@);
538 }
539 let (content_len, values) = repeated.parse(&rest)?;
540 let value = CborValue::Array(values);
541 proof {
542 super::value::lemma_collection_value_view(&value);
543 }
544 Ok((head_len + content_len, value))
545 },
546 CborHead { major: MajorType::Array, value: CborHeadValue::Indefinite } => {
547 let repeated = Repeat(child, BREAK);
548 proof {
549 lemma_repeat_parser_exec_inv::<&'i [u8], _, _>(&repeated);
550 lemma_repeat_parser_congruence(child, child_spec, BREAK, BREAK);
551 lemma_parser_congruent_apply(repeated, Repeat(child_spec, BREAK), rest@);
552 }
553 let (content_len, (values, _break)) = repeated.parse(&rest)?;
554 let value = CborValue::Array(values);
555 proof {
556 super::value::lemma_collection_value_view(&value);
557 }
558 Ok((head_len + content_len, value))
559 },
560 CborHead { major: MajorType::Map, value: CborHeadValue::Argument(len) } => {
561 let entry = Pair(child, child);
562 let repeated = RepeatN(len, entry);
563 proof {
564 lemma_pair_parser_exec_inv::<&'i [u8], _, _>(&entry);
565 lemma_pair_parser_congruence(child, child_spec, child, child_spec);
566 lemma_repeat_n_parser_exec_inv::<&'i [u8], _, _>(&repeated);
567 lemma_repeat_n_parser_congruence(
568 repeated,
569 RepeatN(len, Pair(child_spec, child_spec)),
570 );
571 lemma_parser_congruent_apply(
572 repeated,
573 RepeatN(len, Pair(child_spec, child_spec)),
574 rest@,
575 );
576 }
577 let (content_len, entries) = repeated.parse(&rest)?;
578 let value = CborValue::Map(entries);
579 proof {
580 super::value::lemma_collection_value_view(&value);
581 }
582 Ok((head_len + content_len, value))
583 },
584 CborHead { major: MajorType::Map, value: CborHeadValue::Indefinite } => {
585 let entry = Pair(child, child);
586 let repeated = Repeat(entry, BREAK);
587 proof {
588 lemma_pair_parser_exec_inv::<&'i [u8], _, _>(&entry);
589 lemma_pair_parser_congruence(child, child_spec, child, child_spec);
590 lemma_repeat_parser_exec_inv::<&'i [u8], _, _>(&repeated);
591 lemma_repeat_parser_congruence(entry, Pair(child_spec, child_spec), BREAK, BREAK);
592 lemma_parser_congruent_apply(
593 repeated,
594 Repeat(Pair(child_spec, child_spec), BREAK),
595 rest@,
596 );
597 }
598 let (content_len, (entries, _break)) = repeated.parse(&rest)?;
599 let value = CborValue::Map(entries);
600 proof {
601 super::value::lemma_collection_value_view(&value);
602 }
603 Ok((head_len + content_len, value))
604 },
605 CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(tag) } => {
606 proof {
607 lemma_parser_congruent_apply(child, child_spec, rest@);
608 }
609 let (content_len, value) = child.parse(&rest)?;
610 Ok((head_len + content_len, CborValue::Tag(tag, Box::new(value))))
611 },
612 CborHead { major: MajorType::Simple, value: CborHeadValue::Float(value) } => {
613 Ok((head_len, CborValue::Float(value)))
614 },
615 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(20) } => {
616 Ok((head_len, CborValue::Bool(false)))
617 },
618 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(21) } => {
619 Ok((head_len, CborValue::Bool(true)))
620 },
621 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(22) } => {
622 Ok((head_len, CborValue::Null))
623 },
624 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(23) } => {
625 Ok((head_len, CborValue::Undefined))
626 },
627 CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(value) } => {
628 Ok((head_len, CborValue::Simple(value)))
629 },
630 _ => Err(ParseError::custom("invalid CBOR head/value combination")),
631 }
632}
633
634#[verifier::rlimit(50)]
635fn serialize_cbor_with_child<'i, Output, const DET: bool, Exec>(
636 Ghost(spec_rec): Ghost<ParamRecSpecs<(), CborValueSpec>>,
637 exec_rec: Exec,
638 value: &CborValue<'i>,
639 out: &mut Output,
640) where Output: OutputBuf, Exec: Fn(&(), &CborValue<'i>, &mut Output)
641 requires
642 cbor_body::<DET>(spec_rec).consistent(value.deep_view()),
643 old(out).fits(cbor_body::<DET>(spec_rec).byte_len(value.deep_view())),
644 forall|pp: &(), vv: &CborValue<'i>, output: &mut Output|
645 {
646 &&& spec_rec(pp.deep_view()).0(vv.deep_view())
647 &&& output.fits(spec_rec(pp.deep_view()).1(vv.deep_view()))
648 } ==> call_requires(exec_rec, (pp, vv, output)),
649 forall|pp: &(), vv: &CborValue<'i>, output: &mut Output|
650 call_ensures(exec_rec, (pp, vv, output), ()) ==> {
651 &&& final(output)@ == output@ + spec_rec(pp.deep_view()).3(vv.deep_view())
652 &&& forall|n|
653 output.fits(spec_rec(pp.deep_view()).1(vv.deep_view()) + n)
654 <==> #[trigger] final(output).fits(n)
655 &&& output.same_destination(final(output))
656 },
657 ensures
658 final(out)@ == old(out)@ + cbor_body::<DET>(spec_rec).spec_serialize(value.deep_view()),
659 forall|n|
660 old(out).fits(cbor_body::<DET>(spec_rec).byte_len(value.deep_view()) + n)
661 <==> #[trigger] final(out).fits(n),
662 old(out).same_destination(final(out)),
663{
664 use crate::combinators::congruence::*;
665 use crate::core::exec::bridge_lemmas::*;
666 broadcast use crate::core::exec::output::outbuf_lemmas;
667
668 reveal(<crate::combinators::Star<_> as Consistency>::consistent);
669 reveal(<crate::combinators::Star<_> as SpecByteLen>::byte_len);
670 reveal(<crate::combinators::Star<_> as SpecSerializer>::spec_serialize);
671
672 let ghost child_spec = spec_rec(());
673 let child_exec = |child_value: &CborValue<'i>, output: &mut Output| -> ()
674 requires
675 child_spec.consistent(child_value.deep_view()),
676 old(output).fits(child_spec.byte_len(child_value.deep_view())),
677 ensures
678 final(output)@ == old(output)@ + child_spec.spec_serialize(child_value.deep_view()),
679 forall|n|
680 old(output).fits(child_spec.byte_len(child_value.deep_view()) + n)
681 <==> #[trigger] final(output).fits(n),
682 old(output).same_destination(final(output)),
683 { exec_rec(&(), child_value, output) };
684 let child: FnSerializer<Output, CborValue<'i>, BundledSpecs<CborValueSpec>, _> =
685 FnSerializer::new(child_exec, Ghost(child_spec));
686 proof {
687 lemma_ref_serializer_exec_inv::<Output, _, CborValue<'i>>(&child);
688 lemma_ref_fn_serializer_congruence(&child);
689 }
690
691 match value {
692 CborValue::Integer(integer) => {
693 let head = if *integer >= 0 {
694 CborHead {
695 major: MajorType::Unsigned,
696 value: CborHeadValue::Argument(*integer as u64),
697 }
698 } else {
699 CborHead {
700 major: MajorType::Negative,
701 value: CborHeadValue::Argument((-1i128 - *integer) as u64),
702 }
703 };
704 CborHeadFmt::<DET>.serialize_into(&head, out);
705 },
706 CborValue::Bytes(CborBytes::Definite(bytes)) => {
707 let head = CborHead {
708 major: MajorType::Bytes,
709 value: CborHeadValue::Argument(bytes.len() as u64),
710 };
711 CborHeadFmt::<DET>.serialize_into(&head, out);
712 Tail.serialize_into(bytes, out);
713 },
714 CborValue::Bytes(CborBytes::Indefinite(bytes)) => {
715 let head = CborHead {
716 major: MajorType::Bytes,
717 value: CborHeadValue::Argument(bytes.len() as u64),
718 };
719 CborHeadFmt::<DET>.serialize_into(&head, out);
720 Tail.serialize_into(bytes.as_slice(), out);
721 },
722 CborValue::Text(CborText::Definite(text)) => {
723 let head = CborHead {
724 major: MajorType::Text,
725 value: CborHeadValue::Argument(text.as_bytes().len() as u64),
726 };
727 CborHeadFmt::<DET>.serialize_into(&head, out);
728 Utf8StringFmt.serialize_into(text, out);
729 },
730 CborValue::Text(CborText::Indefinite(text)) => {
731 let head = CborHead {
732 major: MajorType::Text,
733 value: CborHeadValue::Argument(text.as_str().as_bytes().len() as u64),
734 };
735 CborHeadFmt::<DET>.serialize_into(&head, out);
736 Utf8StringFmt.serialize_into(text, out);
737 },
738 CborValue::Array(values) => {
739 proof {
740 super::value::lemma_collection_value_view(value);
741 }
742 let count = values.len();
743 let head = CborHead {
744 major: MajorType::Array,
745 value: CborHeadValue::Argument(count as u64),
746 };
747 CborHeadFmt::<DET>.serialize_into(&head, out);
748 let repeated = RepeatN(count as u64, &child);
749 let ghost repeated_spec = RepeatN(count as u64, child_spec);
750 proof {
751 lemma_repeat_n_serializer_exec_inv::<Output, _, _, CborValue<'i>>(&repeated);
752 lemma_repeat_n_serializer_congruence(repeated, repeated_spec);
753 lemma_serializer_congruent_prepare(repeated, repeated_spec);
754 lemma_prepare_congruent_consistent(repeated, repeated_spec, values.deep_view());
755 lemma_prepare_congruent_byte_len(repeated, repeated_spec, values.deep_view());
756 lemma_serializer_congruent_serialize(repeated, repeated_spec, values.deep_view());
757 }
758 repeated.serialize_into(values.as_slice(), out);
759 },
760 CborValue::Map(entries) => {
761 proof {
762 super::value::lemma_collection_value_view(value);
763 }
764 let count = entries.len();
765 let head = CborHead {
766 major: MajorType::Map,
767 value: CborHeadValue::Argument(count as u64),
768 };
769 CborHeadFmt::<DET>.serialize_into(&head, out);
770 let entry = Pair(&child, &child);
771 let ghost entry_spec = Pair(child_spec, child_spec);
772 let repeated = RepeatN(count as u64, entry);
773 let ghost repeated_spec = RepeatN(count as u64, entry_spec);
774 proof {
775 lemma_pair_serializer_congruence(entry, entry_spec);
776 lemma_pair_serializer_exec_inv::<Output, _, _, CborValue<'i>, CborValue<'i>>(
777 &entry,
778 );
779 lemma_repeat_n_serializer_exec_inv::<Output, _, _, (CborValue<'i>, CborValue<'i>)>(
780 &repeated,
781 );
782 lemma_repeat_n_serializer_congruence(repeated, repeated_spec);
783 lemma_serializer_congruent_prepare(repeated, repeated_spec);
784 lemma_prepare_congruent_consistent(repeated, repeated_spec, entries.deep_view());
785 lemma_prepare_congruent_byte_len(repeated, repeated_spec, entries.deep_view());
786 lemma_serializer_congruent_serialize(repeated, repeated_spec, entries.deep_view());
787 }
788 repeated.serialize_into(entries.as_slice(), out);
789 },
790 CborValue::Tag(tag, inner) => {
791 let head = CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(*tag) };
792 proof {
793 assert(child_spec.consistent((**inner).deep_view()));
794 lemma_serializer_congruent_prepare(&child, child_spec);
795 lemma_prepare_congruent_consistent(&child, child_spec, (**inner).deep_view());
796 lemma_prepare_congruent_byte_len(&child, child_spec, (**inner).deep_view());
797 lemma_serializer_congruent_serialize(&child, child_spec, (**inner).deep_view());
798 lemma_fn_serializer_specs(&child, (**inner).deep_view());
799 }
800 CborHeadFmt::<DET>.serialize_into(&head, out);
801 child.serialize_into(&**inner, out);
802 },
803 CborValue::Float(float) => {
804 let head = CborHead { major: MajorType::Simple, value: CborHeadValue::Float(*float) };
805 CborHeadFmt::<DET>.serialize_into(&head, out);
806 },
807 CborValue::Bool(boolean) => {
808 let head = CborHead {
809 major: MajorType::Simple,
810 value: CborHeadValue::Simple(
811 if *boolean {
812 21
813 } else {
814 20
815 },
816 ),
817 };
818 CborHeadFmt::<DET>.serialize_into(&head, out);
819 },
820 CborValue::Null => {
821 let head = CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(22) };
822 CborHeadFmt::<DET>.serialize_into(&head, out);
823 },
824 CborValue::Undefined => {
825 let head = CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(23) };
826 CborHeadFmt::<DET>.serialize_into(&head, out);
827 },
828 CborValue::Simple(simple) => {
829 let head = CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(*simple) };
830 CborHeadFmt::<DET>.serialize_into(&head, out);
831 },
832 }
833}
834
835fn checked_add_lengths(left: usize, right: usize) -> (result: Result<usize, PreSerializeError>)
836 ensures
837 result matches Ok(total) ==> total as nat == left as nat + right as nat,
838{
839 match left.checked_add(right) {
840 Some(total) => Ok(total),
841 None => Err(PreSerializeError::length_too_large()),
842 }
843}
844
845fn prepare_cbor_with_child<'i, const DET: bool, Exec>(
846 Ghost(spec_rec): Ghost<ParamRecSpecs<(), CborValueSpec>>,
847 exec_rec: Exec,
848 value: &CborValue<'i>,
849) -> (result: Result<usize, PreSerializeError>) where
850 Exec: Fn(&(), &CborValue<'i>) -> Result<usize, PreSerializeError>,
851
852 requires
853 forall|pp: &(), vv: &CborValue<'i>| call_requires(exec_rec, (pp, vv)),
854 forall|pp: &(), vv: &CborValue<'i>, rr: Result<usize, PreSerializeError>|
855 call_ensures(exec_rec, (pp, vv), rr) ==> (rr matches Ok(len) ==> {
856 &&& spec_rec(pp.deep_view()).0(vv.deep_view())
857 &&& len == spec_rec(pp.deep_view()).1(vv.deep_view())
858 }),
859 ensures
860 result matches Ok(len) ==> {
861 &&& cbor_body::<DET>(spec_rec).consistent(value.deep_view())
862 &&& len == cbor_body::<DET>(spec_rec).byte_len(value.deep_view())
863 },
864{
865 use crate::combinators::congruence::*;
866 use crate::core::exec::bridge_lemmas::*;
867
868 let ghost child_spec = spec_rec(());
869 let child_exec = |child_value: &CborValue<'i>| -> (child_result: Result<
870 usize,
871 PreSerializeError,
872 >)
873 ensures
874 child_result matches Ok(len) ==> {
875 &&& child_spec.consistent(child_value.deep_view())
876 &&& len == child_spec.byte_len(child_value.deep_view())
877 },
878 { exec_rec(&(), child_value) };
879 let child: FnPrepare<CborValue<'i>, BundledSpecs<CborValueSpec>, _> = FnPrepare::new(
880 child_exec,
881 Ghost(child_spec),
882 );
883 proof {
884 lemma_ref_prepare_exec_inv(&child);
885 lemma_ref_fn_prepare_congruence(&child);
886 }
887
888 match value {
889 CborValue::Integer(integer) => {
890 if *integer < -1i128 - u64::MAX as i128 || *integer > u64::MAX as i128 {
891 return Err(PreSerializeError::custom("CBOR integer is out of range"));
892 }
893 let head = if *integer >= 0 {
894 CborHead {
895 major: MajorType::Unsigned,
896 value: CborHeadValue::Argument(*integer as u64),
897 }
898 } else {
899 CborHead {
900 major: MajorType::Negative,
901 value: CborHeadValue::Argument((-1i128 - *integer) as u64),
902 }
903 };
904 CborHeadFmt::<DET>.prepare(&head)
905 },
906 CborValue::Bytes(CborBytes::Definite(bytes)) => {
907 let head = CborHead {
908 major: MajorType::Bytes,
909 value: CborHeadValue::Argument(bytes.len() as u64),
910 };
911 let head_len = CborHeadFmt::<DET>.prepare(&head)?;
912 let content_len = Tail.prepare(bytes)?;
913 checked_add_lengths(head_len, content_len)
914 },
915 CborValue::Bytes(CborBytes::Indefinite(bytes)) => {
916 let head = CborHead {
917 major: MajorType::Bytes,
918 value: CborHeadValue::Argument(bytes.len() as u64),
919 };
920 let head_len = CborHeadFmt::<DET>.prepare(&head)?;
921 let content_len = Tail.prepare(bytes.as_slice())?;
922 checked_add_lengths(head_len, content_len)
923 },
924 CborValue::Text(CborText::Definite(text)) => {
925 let head = CborHead {
926 major: MajorType::Text,
927 value: CborHeadValue::Argument(text.as_bytes().len() as u64),
928 };
929 let head_len = CborHeadFmt::<DET>.prepare(&head)?;
930 let content_len = Utf8StringFmt.prepare(text)?;
931 checked_add_lengths(head_len, content_len)
932 },
933 CborValue::Text(CborText::Indefinite(text)) => {
934 let head = CborHead {
935 major: MajorType::Text,
936 value: CborHeadValue::Argument(text.as_str().as_bytes().len() as u64),
937 };
938 let head_len = CborHeadFmt::<DET>.prepare(&head)?;
939 let content_len = Utf8StringFmt.prepare(text)?;
940 checked_add_lengths(head_len, content_len)
941 },
942 CborValue::Array(values) => {
943 proof {
944 super::value::lemma_collection_value_view(value);
945 }
946 let count = values.len();
947 let head = CborHead {
948 major: MajorType::Array,
949 value: CborHeadValue::Argument(count as u64),
950 };
951 let repeated = RepeatN(count as u64, &child);
952 let ghost repeated_spec = RepeatN(count as u64, child_spec);
953 proof {
954 lemma_repeat_n_prepare_exec_inv::<_, _, CborValue<'i>>(&repeated);
955 lemma_repeat_n_prepare_congruence(repeated, repeated_spec);
956 }
957 let head_len = CborHeadFmt::<DET>.prepare(&head)?;
958 let content_len = repeated.prepare(values.as_slice())?;
959 proof {
960 lemma_prepare_congruent_consistent(repeated, repeated_spec, values.deep_view());
961 lemma_prepare_congruent_byte_len(repeated, repeated_spec, values.deep_view());
962 }
963 checked_add_lengths(head_len, content_len)
964 },
965 CborValue::Map(entries) => {
966 proof {
967 super::value::lemma_collection_value_view(value);
968 }
969 let count = entries.len();
970 let head = CborHead {
971 major: MajorType::Map,
972 value: CborHeadValue::Argument(count as u64),
973 };
974 let entry = Pair(&child, &child);
975 let ghost entry_spec = Pair(child_spec, child_spec);
976 let repeated = RepeatN(count as u64, entry);
977 let ghost repeated_spec = RepeatN(count as u64, entry_spec);
978 proof {
979 lemma_pair_prepare_exec_inv::<_, _, CborValue<'i>, CborValue<'i>>(&entry);
980 lemma_pair_prepare_congruence(entry, entry_spec);
981 lemma_repeat_n_prepare_exec_inv::<_, _, (CborValue<'i>, CborValue<'i>)>(&repeated);
982 lemma_repeat_n_prepare_congruence(repeated, repeated_spec);
983 }
984 let head_len = CborHeadFmt::<DET>.prepare(&head)?;
985 let content_len = repeated.prepare(entries.as_slice())?;
986 proof {
987 lemma_prepare_congruent_consistent(repeated, repeated_spec, entries.deep_view());
988 lemma_prepare_congruent_byte_len(repeated, repeated_spec, entries.deep_view());
989 }
990 checked_add_lengths(head_len, content_len)
991 },
992 CborValue::Tag(tag, inner) => {
993 let head = CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(*tag) };
994 let head_len = CborHeadFmt::<DET>.prepare(&head)?;
995 let content_len = child.prepare(&**inner)?;
996 proof {
997 lemma_prepare_congruent_consistent(&child, child_spec, (**inner).deep_view());
998 lemma_prepare_congruent_byte_len(&child, child_spec, (**inner).deep_view());
999 lemma_fn_prepare_specs(&child, (**inner).deep_view());
1000 }
1001 checked_add_lengths(head_len, content_len)
1002 },
1003 CborValue::Float(float) => CborHeadFmt::<DET>.prepare(
1004 &CborHead { major: MajorType::Simple, value: CborHeadValue::Float(*float) },
1005 ),
1006 CborValue::Bool(boolean) => CborHeadFmt::<DET>.prepare(
1007 &CborHead {
1008 major: MajorType::Simple,
1009 value: CborHeadValue::Simple(
1010 if *boolean {
1011 21
1012 } else {
1013 20
1014 },
1015 ),
1016 },
1017 ),
1018 CborValue::Null => CborHeadFmt::<DET>.prepare(
1019 &CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(22) },
1020 ),
1021 CborValue::Undefined => CborHeadFmt::<DET>.prepare(
1022 &CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(23) },
1023 ),
1024 CborValue::Simple(simple) => {
1025 if *simple > 19 && *simple < 32 {
1026 Err(PreSerializeError::custom("reserved CBOR simple value"))
1027 } else {
1028 CborHeadFmt::<DET>.prepare(
1029 &CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(*simple) },
1030 )
1031 }
1032 },
1033 }
1034}
1035
1036fn length_cbor_with_child<'i, const DET: bool, Exec>(
1037 Ghost(spec_rec): Ghost<ParamRecSpecs<(), CborValueSpec>>,
1038 exec_rec: Exec,
1039 value: &CborValue<'i>,
1040) -> (len: usize) where Exec: Fn(&(), &CborValue<'i>) -> usize
1041 requires
1042 cbor_body::<DET>(spec_rec).byte_len(value.deep_view()) <= usize::MAX,
1043 forall|pp: &(), vv: &CborValue<'i>|
1044 spec_rec(pp.deep_view()).1(vv.deep_view()) <= usize::MAX ==> call_requires(
1045 exec_rec,
1046 (pp, vv),
1047 ),
1048 forall|pp: &(), vv: &CborValue<'i>, child_len: usize|
1049 call_ensures(exec_rec, (pp, vv), child_len) ==> child_len == spec_rec(pp.deep_view()).1(
1050 vv.deep_view(),
1051 ),
1052 ensures
1053 len == cbor_body::<DET>(spec_rec).byte_len(value.deep_view()),
1054{
1055 use crate::combinators::congruence::*;
1056 use crate::core::exec::bridge_lemmas::*;
1057
1058 let ghost child_spec = spec_rec(());
1059 let child_exec = |child_value: &CborValue<'i>| -> (child_len: usize)
1060 requires
1061 child_spec.byte_len(child_value.deep_view()) <= usize::MAX,
1062 ensures
1063 child_len == child_spec.byte_len(child_value.deep_view()),
1064 { exec_rec(&(), child_value) };
1065 let child: FnByteLen<CborValue<'i>, BundledSpecs<CborValueSpec>, _> = FnByteLen::new(
1066 child_exec,
1067 Ghost(child_spec),
1068 );
1069 proof {
1070 lemma_ref_fn_byte_len_congruence(&child);
1071 lemma_ref_byte_len_exec_inv::<_, CborValue<'i>>(&child);
1072 }
1073
1074 match value {
1075 CborValue::Integer(integer) => {
1076 let head = if *integer >= 0 {
1077 CborHead {
1078 major: MajorType::Unsigned,
1079 value: CborHeadValue::Argument(*integer as u64),
1080 }
1081 } else {
1082 CborHead {
1083 major: MajorType::Negative,
1084 value: CborHeadValue::Argument((-1i128 - *integer) as u64),
1085 }
1086 };
1087 CborHeadFmt::<DET>.length(&head)
1088 },
1089 CborValue::Bytes(CborBytes::Definite(bytes)) => {
1090 let head = CborHead {
1091 major: MajorType::Bytes,
1092 value: CborHeadValue::Argument(bytes.len() as u64),
1093 };
1094 CborHeadFmt::<DET>.length(&head) + Tail.length(bytes)
1095 },
1096 CborValue::Bytes(CborBytes::Indefinite(bytes)) => {
1097 let head = CborHead {
1098 major: MajorType::Bytes,
1099 value: CborHeadValue::Argument(bytes.len() as u64),
1100 };
1101 CborHeadFmt::<DET>.length(&head) + Tail.length(bytes.as_slice())
1102 },
1103 CborValue::Text(CborText::Definite(text)) => {
1104 let head = CborHead {
1105 major: MajorType::Text,
1106 value: CborHeadValue::Argument(text.as_bytes().len() as u64),
1107 };
1108 CborHeadFmt::<DET>.length(&head) + Utf8StringFmt.length(text)
1109 },
1110 CborValue::Text(CborText::Indefinite(text)) => {
1111 let head = CborHead {
1112 major: MajorType::Text,
1113 value: CborHeadValue::Argument(text.as_str().as_bytes().len() as u64),
1114 };
1115 CborHeadFmt::<DET>.length(&head) + Utf8StringFmt.length(text)
1116 },
1117 CborValue::Array(values) => {
1118 proof {
1119 super::value::lemma_collection_value_view(value);
1120 }
1121 let count = values.len();
1122 let head = CborHead {
1123 major: MajorType::Array,
1124 value: CborHeadValue::Argument(count as u64),
1125 };
1126 let repeated = RepeatN(count as u64, &child);
1127 let ghost repeated_spec = RepeatN(count as u64, child_spec);
1128 proof {
1129 lemma_repeat_n_prepare_congruence(repeated, repeated_spec);
1130 lemma_prepare_congruent_byte_len(repeated, repeated_spec, values.deep_view());
1131 lemma_repeat_n_byte_len_exec_inv::<_, _, CborValue<'i>>(&repeated);
1132 }
1133 CborHeadFmt::<DET>.length(&head) + repeated.length(values.as_slice())
1134 },
1135 CborValue::Map(entries) => {
1136 proof {
1137 super::value::lemma_collection_value_view(value);
1138 }
1139 let count = entries.len();
1140 let head = CborHead {
1141 major: MajorType::Map,
1142 value: CborHeadValue::Argument(count as u64),
1143 };
1144 let entry = Pair(&child, &child);
1145 let ghost entry_spec = Pair(child_spec, child_spec);
1146 let repeated = RepeatN(count as u64, entry);
1147 let ghost repeated_spec = RepeatN(count as u64, entry_spec);
1148 proof {
1149 lemma_pair_prepare_congruence(entry, entry_spec);
1150 lemma_repeat_n_prepare_congruence(repeated, repeated_spec);
1151 lemma_prepare_congruent_byte_len(repeated, repeated_spec, entries.deep_view());
1152 lemma_pair_byte_len_exec_inv::<_, _, CborValue<'i>, CborValue<'i>>(&entry);
1153 lemma_repeat_n_byte_len_exec_inv::<_, _, (CborValue<'i>, CborValue<'i>)>(&repeated);
1154 }
1155 CborHeadFmt::<DET>.length(&head) + repeated.length(entries.as_slice())
1156 },
1157 CborValue::Tag(tag, inner) => {
1158 proof {
1159 lemma_prepare_congruent_byte_len(&child, child_spec, (**inner).deep_view());
1160 lemma_fn_byte_len_specs(&child, (**inner).deep_view());
1161 }
1162 let head = CborHead { major: MajorType::Tag, value: CborHeadValue::Argument(*tag) };
1163 CborHeadFmt::<DET>.length(&head) + child.length(&**inner)
1164 },
1165 CborValue::Float(float) => CborHeadFmt::<DET>.length(
1166 &CborHead { major: MajorType::Simple, value: CborHeadValue::Float(*float) },
1167 ),
1168 CborValue::Bool(boolean) => CborHeadFmt::<DET>.length(
1169 &CborHead {
1170 major: MajorType::Simple,
1171 value: CborHeadValue::Simple(
1172 if *boolean {
1173 21
1174 } else {
1175 20
1176 },
1177 ),
1178 },
1179 ),
1180 CborValue::Null => CborHeadFmt::<DET>.length(
1181 &CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(22) },
1182 ),
1183 CborValue::Undefined => CborHeadFmt::<DET>.length(
1184 &CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(23) },
1185 ),
1186 CborValue::Simple(simple) => CborHeadFmt::<DET>.length(
1187 &CborHead { major: MajorType::Simple, value: CborHeadValue::Simple(*simple) },
1188 ),
1189 }
1190}
1191
1192fn cbor_length_gas<'i, const DET: bool, const LIMIT: usize>(
1193 gas: usize,
1194 value: &CborValue<'i>,
1195) -> (len: usize)
1196 requires
1197 FixWith::<LIMIT, CborRecBody<DET>, ()>::byte_len_gas(
1198 &CborRecBody::<DET>,
1199 gas as nat,
1200 (),
1201 value.deep_view(),
1202 ) <= usize::MAX,
1203 ensures
1204 len == FixWith::<LIMIT, CborRecBody<DET>, ()>::byte_len_gas(
1205 &CborRecBody::<DET>,
1206 gas as nat,
1207 (),
1208 value.deep_view(),
1209 ),
1210 decreases gas,
1211{
1212 let ghost body = CborRecBody::<DET>;
1213 let ghost spec_rec = FixWith::<LIMIT, CborRecBody<DET>, ()>::specs_callback(&body, gas as nat);
1214 let exec_rec = |_param: &(), child: &CborValue<'i>| -> (child_len: usize)
1215 requires
1216 spec_rec(()).byte_len(child.deep_view()) <= usize::MAX,
1217 ensures
1218 child_len == spec_rec(()).byte_len(child.deep_view()),
1219 {
1220 if gas > 0 {
1221 cbor_length_gas::<DET, LIMIT>((gas - 1) as usize, child)
1222 } else {
1223 0
1224 }
1225 };
1226 length_cbor_with_child::<DET, _>(Ghost(spec_rec), exec_rec, value)
1227}
1228
1229fn parse_cbor_rec_body<'i, const DET: bool, Exec>(
1230 param: &(),
1231 Ghost(spec_rec): Ghost<ParamRecSpecs<(), CborValueSpec>>,
1232 exec_rec: Exec,
1233 input: &&'i [u8],
1234) -> (result: PResult<CborValue<'i>>) where Exec: Fn(&(), &&'i [u8]) -> PResult<CborValue<'i>>
1235 requires
1236 forall|p: ()| #[trigger] spec_rec(p).safe_inv(),
1237 forall|p: ()| #[trigger] spec_rec(p).productive_inv(),
1238 forall|pp: &(), i: &&'i [u8]| call_requires(exec_rec, (pp, i)),
1239 forall|pp: &(), i: &&'i [u8], rr: PResult<CborValue<'i>>|
1240 call_ensures(exec_rec, (pp, i), rr) ==> parse_matches_spec(
1241 rr,
1242 spec_rec(pp.deep_view()).2(i@),
1243 ),
1244 ensures
1245 parse_matches_spec(result, cbor_body::<DET>(spec_rec).spec_parse(input@)),
1246{
1247 let ghost child_spec = spec_rec(());
1248 let child_exec = |child_input: &&'i [u8]| -> (result: PResult<CborValue<'i>>)
1249 ensures
1250 parse_matches_spec(result, child_spec.2(child_input@)),
1251 { exec_rec(param, child_input) };
1252 let child: FnParser<&'i [u8], CborValue<'i>, BundledSpecs<CborValueSpec>, _> = FnParser::new(
1253 child_exec,
1254 Ghost(child_spec),
1255 );
1256 proof {
1257 crate::combinators::congruence::lemma_ref_fn_parser_congruence(&child);
1258 }
1259 parse_cbor_with_child::<DET, _>(Ghost(spec_rec), &child, input)
1260}
1261
1262impl<'i> ParserRecBody<&'i [u8]> for CborRecBody<false> where
1266 CborRecBody<false>: SpecRecBody<Param = (), T = CborValueSpec, Body = CborBodyFmt<false>>,
1267 {
1268 type EP = ();
1269
1270 type O = CborValue<'i>;
1271
1272 fn parse_body<Exec>(
1273 &self,
1274 param: &(),
1275 spec_rec: Ghost<ParamRecSpecs<(), CborValueSpec>>,
1276 exec_rec: Exec,
1277 input: &&'i [u8],
1278 ) -> PResult<Self::O> where Exec: Fn(&(), &&'i [u8]) -> PResult<Self::O> {
1279 parse_cbor_rec_body::<false, _>(param, spec_rec, exec_rec, input)
1280 }
1281}
1282
1283impl<'i> ParserRecBody<&'i [u8]> for CborRecBody<true> where
1284 CborRecBody<true>: SpecRecBody<Param = (), T = CborValueSpec, Body = CborBodyFmt<true>>,
1285 {
1286 type EP = ();
1287
1288 type O = CborValue<'i>;
1289
1290 fn parse_body<Exec>(
1291 &self,
1292 param: &(),
1293 spec_rec: Ghost<ParamRecSpecs<(), CborValueSpec>>,
1294 exec_rec: Exec,
1295 input: &&'i [u8],
1296 ) -> PResult<Self::O> where Exec: Fn(&(), &&'i [u8]) -> PResult<Self::O> {
1297 parse_cbor_rec_body::<true, _>(param, spec_rec, exec_rec, input)
1298 }
1299}
1300
1301impl<'i, Output: OutputBuf, const DET: bool> SerializerRecBody<
1302 Output,
1303 CborValue<'i>,
1304> for CborRecBody<DET> {
1305 type EP = ();
1306
1307 fn serialize_body<Exec>(
1308 &self,
1309 _param: &(),
1310 Ghost(spec_rec): Ghost<ParamRecSpecs<(), CborValueSpec>>,
1311 exec_rec: Exec,
1312 value: &CborValue<'i>,
1313 out: &mut Output,
1314 ) where Exec: Fn(&(), &CborValue<'i>, &mut Output) {
1315 serialize_cbor_with_child::<Output, DET, _>(Ghost(spec_rec), exec_rec, value, out)
1316 }
1317}
1318
1319impl<'i> PrepareRecBody<CborValue<'i>> for CborRecBody<false> where
1322 CborRecBody<false>: SpecRecBody<Param = (), T = CborValueSpec, Body = CborBodyFmt<false>>,
1323 {
1324 type EP = ();
1325
1326 fn prepare_body<Exec>(
1327 &self,
1328 _param: &(),
1329 spec_rec: Ghost<ParamRecSpecs<(), CborValueSpec>>,
1330 exec_rec: Exec,
1331 value: &CborValue<'i>,
1332 ) -> Result<usize, PreSerializeError> where
1333 Exec: Fn(&(), &CborValue<'i>) -> Result<usize, PreSerializeError>,
1334 {
1335 prepare_cbor_with_child::<false, _>(spec_rec, exec_rec, value)
1336 }
1337}
1338
1339impl<'i> PrepareRecBody<CborValue<'i>> for CborRecBody<true> where
1340 CborRecBody<true>: SpecRecBody<Param = (), T = CborValueSpec, Body = CborBodyFmt<true>>,
1341 {
1342 type EP = ();
1343
1344 fn prepare_body<Exec>(
1345 &self,
1346 _param: &(),
1347 spec_rec: Ghost<ParamRecSpecs<(), CborValueSpec>>,
1348 exec_rec: Exec,
1349 value: &CborValue<'i>,
1350 ) -> Result<usize, PreSerializeError> where
1351 Exec: Fn(&(), &CborValue<'i>) -> Result<usize, PreSerializeError>,
1352 {
1353 prepare_cbor_with_child::<true, _>(spec_rec, exec_rec, value)
1354 }
1355}
1356
1357#[derive(Clone, Copy)]
1359pub struct CborFmt<const DET: bool, const LIMIT: usize = MAX_RECURSION_DEPTH>;
1360
1361pub open spec fn cbor_fmt<const DET: bool, const LIMIT: usize>() -> FixWith<
1362 LIMIT,
1363 CborRecBody<DET>,
1364 (),
1365> {
1366 FixWith(CborRecBody::<DET>, ())
1367}
1368
1369impl<'i, const DET: bool, const LIMIT: usize> Parser<&'i [u8]> for CborFmt<DET, LIMIT> where
1370 CborRecBody<DET>: SpecRecBody<
1371 Param = (),
1372 T = CborValueSpec,
1373 Body = CborBodyFmt<DET>,
1374 > + ParserRecBody<&'i [u8], EP = (), O = CborValue<'i>>,
1375 <CborRecBody<DET> as SpecRecBody>::Body: Productive,
1376 {
1377 type PT = CborValue<'i>;
1378
1379 fn parse(&self, input: &&'i [u8]) -> PResult<Self::PT> {
1380 FixWith::<LIMIT, _, _>(CborRecBody::<DET>, ()).parse(input)
1381 }
1382}
1383
1384impl<'i, Output: OutputBuf, const DET: bool, const LIMIT: usize> Serializer<
1385 Output,
1386 CborValue<'i>,
1387> for CborFmt<DET, LIMIT> {
1388 fn serialize_into(&self, value: &CborValue<'i>, out: &mut Output) {
1389 FixWith::<LIMIT, _, _>(CborRecBody::<DET>, ()).serialize_into(value, out)
1390 }
1391}
1392
1393impl<'i, const DET: bool, const LIMIT: usize> Prepare<CborValue<'i>> for CborFmt<DET, LIMIT> where
1394 CborRecBody<DET>: SpecRecBody<
1395 Param = (),
1396 T = CborValueSpec,
1397 Body = CborBodyFmt<DET>,
1398 > + PrepareRecBody<CborValue<'i>, EP = ()>,
1399 {
1400 fn prepare(&self, value: &CborValue<'i>) -> Result<usize, PreSerializeError> {
1401 FixWith::<LIMIT, _, _>(CborRecBody::<DET>, ()).prepare(value)
1402 }
1403}
1404
1405impl<'i, const DET: bool, const LIMIT: usize> ByteLen<CborValue<'i>> for CborFmt<DET, LIMIT> {
1406 fn length(&self, value: &CborValue<'i>) -> usize {
1407 cbor_length_gas::<DET, LIMIT>(LIMIT, value)
1408 }
1409}
1410
1411mod derived_specs {
1412 use super::*;
1413
1414 impl<const DET: bool> SpecParser for CborBodyFmt<DET> {
1415 type PVal = CborValueSpec;
1416
1417 open spec fn spec_parse(&self, input: Seq<u8>) -> Option<(int, Self::PVal)> {
1418 cbor_parse_body::<DET>(self.rec@).spec_parse(input)
1419 }
1420 }
1421
1422 impl<const DET: bool> Consistency for CborBodyFmt<DET> {
1423 type Val = CborValueSpec;
1424
1425 open spec fn consistent(&self, value: Self::Val) -> bool {
1426 cbor_normalized_body::<DET>(self.rec@).consistent(value)
1427 }
1428 }
1429
1430 impl<const DET: bool> SpecSerializerDps for CborBodyFmt<DET> {
1431 type SValue = CborValueSpec;
1432
1433 open spec fn spec_serialize_dps(&self, value: Self::SValue, out: Seq<u8>) -> Seq<u8> {
1434 cbor_normalized_body::<DET>(self.rec@).spec_serialize_dps(value, out)
1435 }
1436 }
1437
1438 impl<const DET: bool> SpecSerializer for CborBodyFmt<DET> {
1439 type SVal = CborValueSpec;
1440
1441 open spec fn spec_serialize(&self, value: Self::SVal) -> Seq<u8> {
1442 cbor_normalized_body::<DET>(self.rec@).spec_serialize(value)
1443 }
1444 }
1445
1446 impl<const DET: bool> SpecByteLen for CborBodyFmt<DET> {
1447 type T = CborValueSpec;
1448
1449 open spec fn byte_len(&self, value: Self::T) -> nat {
1450 cbor_normalized_body::<DET>(self.rec@).byte_len(value)
1451 }
1452 }
1453
1454 impl<const DET: bool, const LIMIT: usize> SpecParser for CborFmt<DET, LIMIT> {
1455 type PVal = CborValueSpec;
1456
1457 open spec fn spec_parse(&self, input: Seq<u8>) -> Option<(int, Self::PVal)> {
1458 cbor_fmt::<DET, LIMIT>().spec_parse(input)
1459 }
1460 }
1461
1462 impl<const DET: bool, const LIMIT: usize> Consistency for CborFmt<DET, LIMIT> {
1463 type Val = CborValueSpec;
1464
1465 open spec fn consistent(&self, value: Self::Val) -> bool {
1466 cbor_fmt::<DET, LIMIT>().consistent(value)
1467 }
1468 }
1469
1470 impl<const DET: bool, const LIMIT: usize> SpecSerializerDps for CborFmt<DET, LIMIT> {
1471 type SValue = CborValueSpec;
1472
1473 open spec fn spec_serialize_dps(&self, value: Self::SValue, out: Seq<u8>) -> Seq<u8> {
1474 cbor_fmt::<DET, LIMIT>().spec_serialize_dps(value, out)
1475 }
1476 }
1477
1478 impl<const DET: bool, const LIMIT: usize> SpecSerializer for CborFmt<DET, LIMIT> {
1479 type SVal = CborValueSpec;
1480
1481 open spec fn spec_serialize(&self, value: Self::SVal) -> Seq<u8> {
1482 cbor_fmt::<DET, LIMIT>().spec_serialize(value)
1483 }
1484 }
1485
1486 impl<const DET: bool, const LIMIT: usize> SpecByteLen for CborFmt<DET, LIMIT> {
1487 type T = CborValueSpec;
1488
1489 open spec fn byte_len(&self, value: Self::T) -> nat {
1490 cbor_fmt::<DET, LIMIT>().byte_len(value)
1491 }
1492 }
1493
1494}
1495
1496mod recursive_proofs {
1497 use super::*;
1498
1499 impl<const DET: bool> SafeParserRecBody for CborRecBody<DET> {
1500 proof fn lemma_body_safe_inv_preservation(
1501 &self,
1502 _param: (),
1503 _rec: ParamRecSpecs<(), CborValueSpec>,
1504 ) {
1505 }
1506 }
1507
1508 impl<const DET: bool> ProductiveRecBody for CborRecBody<DET> {
1509 proof fn lemma_body_productive_inv_preservation(
1510 &self,
1511 _param: (),
1512 _rec: ParamRecSpecs<(), CborValueSpec>,
1513 ) {
1514 }
1515 }
1516
1517 impl SoundParserRecBody for CborRecBody<true> {
1518 proof fn lemma_body_sound_inv_preservation(
1519 &self,
1520 _param: (),
1521 _rec: ParamRecSpecs<(), CborValueSpec>,
1522 ) {
1523 }
1524 }
1525
1526 impl NonMalleableRecBody for CborRecBody<true> {
1527 proof fn lemma_body_nonmal_inv_preservation(
1528 &self,
1529 _param: (),
1530 _rec: ParamRecSpecs<(), CborValueSpec>,
1531 ) {
1532 }
1533 }
1534
1535 impl<const DET: bool> GoodSerializerRecBody for CborRecBody<DET> {
1536 proof fn lemma_s_body_serialize_inv_preservation(
1537 &self,
1538 _param: (),
1539 _rec: ParamRecSpecs<(), CborValueSpec>,
1540 ) {
1541 }
1542 }
1543
1544 impl<const DET: bool> NonTailFmtRecBody for CborRecBody<DET> {
1545 proof fn lemma_s_body_dps_serialize_dps_inv_preservation(
1546 &self,
1547 _param: (),
1548 _rec: ParamRecSpecs<(), CborValueSpec>,
1549 ) {
1550 }
1551 }
1552
1553 impl<const DET: bool> SPRoundTripDpsRecBody for CborRecBody<DET> {
1554 proof fn lemma_body_sp_roundtrip_dps_inv_preservation(
1555 &self,
1556 _param: (),
1557 _rec: ParamRecSpecs<(), CborValueSpec>,
1558 ) {
1559 }
1560 }
1561
1562 impl<const DET: bool> EquivSerializersGeneralRecBody for CborRecBody<DET> {
1563 proof fn lemma_s_body_equiv_general_inv_preservation(
1564 &self,
1565 _param: (),
1566 _rec: ParamRecSpecs<(), CborValueSpec>,
1567 ) {
1568 }
1569 }
1570
1571}
1572
1573mod derived_proofs {
1574 use super::*;
1575
1576 impl<const DET: bool> SafeParser for CborBodyFmt<DET> {
1577 open spec fn safe_inv(&self) -> bool {
1578 cbor_parse_body::<DET>(self.rec@).safe_inv()
1579 }
1580
1581 proof fn lemma_parse_safe(&self, input: Seq<u8>) {
1582 cbor_parse_body::<DET>(self.rec@).lemma_parse_safe(input);
1583 }
1584 }
1585
1586 impl<const DET: bool> Productive for CborBodyFmt<DET> {
1587 open spec fn productive_inv(&self) -> bool {
1588 cbor_parse_body::<DET>(self.rec@).productive_inv()
1589 }
1590
1591 proof fn lemma_productive(&self, input: Seq<u8>) {
1592 cbor_parse_body::<DET>(self.rec@).lemma_productive(input);
1593 }
1594 }
1595
1596 impl SoundParser for CborBodyFmt<true> {
1597 open spec fn sound_inv(&self) -> bool {
1598 cbor_parse_body::<true>(self.rec@).sound_inv()
1599 }
1600
1601 proof fn lemma_parse_sound_consumption(&self, input: Seq<u8>) {
1602 cbor_parse_body::<true>(self.rec@).lemma_parse_sound_consumption(input);
1603 if let Some((_n, value)) = self.spec_parse(input) {
1604 lemma_parse_normalized_byte_len::<true>(self.rec@, value);
1605 }
1606 }
1607
1608 proof fn lemma_parse_sound_value(&self, input: Seq<u8>) {
1609 cbor_parse_body::<true>(self.rec@).lemma_parse_sound_value(input);
1610 if let Some((_n, value)) = self.spec_parse(input) {
1611 lemma_parse_normalized_consistency::<true>(self.rec@, value);
1612 }
1613 }
1614 }
1615
1616 impl<const DET: bool> GoodSerializer for CborBodyFmt<DET> {
1617 open spec fn serialize_inv(&self) -> bool {
1618 cbor_normalized_body::<DET>(self.rec@).serialize_inv()
1619 }
1620
1621 proof fn lemma_serialize_len(&self, value: Self::SVal) {
1622 cbor_normalized_body::<DET>(self.rec@).lemma_serialize_len(value);
1623 }
1624 }
1625
1626 impl<const DET: bool> NonTailFmt for CborBodyFmt<DET> {
1627 open spec fn serialize_dps_inv(&self) -> bool {
1628 cbor_normalized_body::<DET>(self.rec@).serialize_dps_inv()
1629 }
1630
1631 proof fn lemma_serialize_dps_prepend(&self, value: Self::SValue, out: Seq<u8>) {
1632 cbor_normalized_body::<DET>(self.rec@).lemma_serialize_dps_prepend(value, out);
1633 }
1634
1635 proof fn lemma_serialize_dps_len(&self, value: Self::SValue, out: Seq<u8>) {
1636 cbor_normalized_body::<DET>(self.rec@).lemma_serialize_dps_len(value, out);
1637 }
1638 }
1639
1640 impl<const DET: bool> SPRoundTripDps for CborBodyFmt<DET> {
1641 open spec fn unambiguous(&self) -> bool {
1642 cbor_normalized_body::<DET>(self.rec@).unambiguous()
1643 }
1644
1645 proof fn theorem_serialize_dps_parse_roundtrip(&self, value: Self::T, out: Seq<u8>) {
1646 let normalized = cbor_normalized_body::<DET>(self.rec@);
1647 normalized.theorem_serialize_dps_parse_roundtrip(value, out);
1648 lemma_normalized_parse_implies_parse::<DET>(
1649 self.rec@,
1650 normalized.spec_serialize_dps(value, out),
1651 );
1652 }
1653 }
1654
1655 impl NonMalleable for CborBodyFmt<true> {
1656 open spec fn nonmal_inv(&self) -> bool {
1657 cbor_parse_body::<true>(self.rec@).nonmal_inv()
1658 }
1659
1660 proof fn lemma_parse_non_malleable(&self, left: Seq<u8>, right: Seq<u8>) {
1661 cbor_parse_body::<true>(self.rec@).lemma_parse_non_malleable(left, right);
1662 }
1663 }
1664
1665 impl<const DET: bool> EquivSerializersGeneral for CborBodyFmt<DET> {
1666 open spec fn equiv_general_inv(&self) -> bool {
1667 cbor_normalized_body::<DET>(self.rec@).equiv_general_inv()
1668 }
1669
1670 proof fn lemma_serialize_equiv(&self, value: Self::SVal, out: Seq<u8>) {
1671 cbor_normalized_body::<DET>(self.rec@).lemma_serialize_equiv(value, out);
1672 }
1673 }
1674
1675 impl<const DET: bool> EquivSerializers for CborBodyFmt<DET> {
1676 open spec fn equiv_inv(&self) -> bool {
1677 cbor_normalized_body::<DET>(self.rec@).equiv_inv()
1678 }
1679
1680 proof fn lemma_serialize_equiv_on_empty(&self, value: Self::SVal) {
1681 cbor_normalized_body::<DET>(self.rec@).lemma_serialize_equiv_on_empty(value);
1682 }
1683 }
1684
1685 impl<const DET: bool, const LIMIT: usize> SafeParser for CborFmt<DET, LIMIT> {
1686 proof fn lemma_parse_safe(&self, input: Seq<u8>) {
1687 cbor_fmt::<DET, LIMIT>().lemma_parse_safe(input);
1688 }
1689 }
1690
1691 impl<const DET: bool, const LIMIT: usize> Productive for CborFmt<DET, LIMIT> {
1692 proof fn lemma_productive(&self, input: Seq<u8>) {
1693 cbor_fmt::<DET, LIMIT>().lemma_productive(input);
1694 }
1695 }
1696
1697 impl<const LIMIT: usize> SoundParser for CborFmt<true, LIMIT> {
1698 proof fn lemma_parse_sound_consumption(&self, input: Seq<u8>) {
1699 cbor_fmt::<true, LIMIT>().lemma_parse_sound_consumption(input);
1700 }
1701
1702 proof fn lemma_parse_sound_value(&self, input: Seq<u8>) {
1703 cbor_fmt::<true, LIMIT>().lemma_parse_sound_value(input);
1704 }
1705 }
1706
1707 impl<const DET: bool, const LIMIT: usize> GoodSerializer for CborFmt<DET, LIMIT> {
1708 proof fn lemma_serialize_len(&self, value: Self::SVal) {
1709 cbor_fmt::<DET, LIMIT>().lemma_serialize_len(value);
1710 }
1711 }
1712
1713 impl<const DET: bool, const LIMIT: usize> NonTailFmt for CborFmt<DET, LIMIT> {
1714 proof fn lemma_serialize_dps_prepend(&self, value: Self::SValue, out: Seq<u8>) {
1715 cbor_fmt::<DET, LIMIT>().lemma_serialize_dps_prepend(value, out);
1716 }
1717
1718 proof fn lemma_serialize_dps_len(&self, value: Self::SValue, out: Seq<u8>) {
1719 cbor_fmt::<DET, LIMIT>().lemma_serialize_dps_len(value, out);
1720 }
1721 }
1722
1723 impl<const DET: bool, const LIMIT: usize> SPRoundTripDps for CborFmt<DET, LIMIT> {
1724 proof fn theorem_serialize_dps_parse_roundtrip(&self, value: Self::T, out: Seq<u8>) {
1725 cbor_fmt::<DET, LIMIT>().theorem_serialize_dps_parse_roundtrip(value, out);
1726 }
1727 }
1728
1729 impl<const LIMIT: usize> NonMalleable for CborFmt<true, LIMIT> {
1730 proof fn lemma_parse_non_malleable(&self, left: Seq<u8>, right: Seq<u8>) {
1731 cbor_fmt::<true, LIMIT>().lemma_parse_non_malleable(left, right);
1732 }
1733 }
1734
1735 impl<const DET: bool, const LIMIT: usize> EquivSerializersGeneral for CborFmt<DET, LIMIT> {
1736 proof fn lemma_serialize_equiv(&self, value: Self::SVal, out: Seq<u8>) {
1737 cbor_fmt::<DET, LIMIT>().lemma_serialize_equiv(value, out);
1738 }
1739 }
1740
1741 impl<const DET: bool, const LIMIT: usize> EquivSerializers for CborFmt<DET, LIMIT> {
1742 proof fn lemma_serialize_equiv_on_empty(&self, value: Self::SVal) {
1743 cbor_fmt::<DET, LIMIT>().lemma_serialize_equiv_on_empty(value);
1744 }
1745 }
1746
1747}
1748
1749}