1use super::spec::*;
3use crate::combinators::length::AsLen;
4use crate::core::exec::output::*;
5use crate::core::{
6 exec::{
7 input::InputBuf,
8 parser::{PResult, Parser},
9 serializer::{ByteLen, ComplianceErrorKind, PreSerializeError, Prepare, Serializer},
10 ParseError,
11 },
12 proof::Productive,
13 spec::{Consistency, SafeParser, SpecByteLen, SpecParser, SpecSerializer},
14};
15#[cfg(feature = "alloc")]
16use alloc::vec::Vec;
17use vstd::prelude::*;
18use OutputBuf;
19
20verus! {
21
22#[cfg(feature = "alloc")]
23const MAX_INITIAL_BYTES: usize = 16_384;
24
25#[cfg(feature = "alloc")]
27fn initial_capacity<T>(estimated: usize) -> (cap: usize)
28 ensures
29 cap <= estimated,
30{
31 let size = core::mem::size_of::<T>();
32 if size == 0 {
33 0
34 } else {
35 let limit = MAX_INITIAL_BYTES / size;
36 if estimated < limit {
37 estimated
38 } else {
39 limit
40 }
41 }
42}
43
44#[cfg(feature = "alloc")]
45impl<I, Inner> Parser<I> for super::Star<Inner> where I: InputBuf, Inner: Parser<I> + Productive {
46 type PT = Vec<Inner::PT>;
47
48 fn min_byte_len(&self) -> usize {
49 0
51 }
52
53 open spec fn exec_inv(&self) -> bool {
54 &&& self.0.exec_inv()
55 &&& self.0.safe_inv()
56 &&& self.0.productive_inv()
57 }
58
59 fn parse(&self, ibuf: &I) -> (r: PResult<Self::PT>) {
60 reveal(<super::Star::<_> as SpecParser>::spec_parse);
61 broadcast use vstd::seq_lib::lemma_seq_skip_nothing;
62
63 let total_len = ibuf.len();
64 let mut consumed: usize = 0;
65 let mut remaining = total_len;
66 let mut rest = ibuf.skip(0);
67 let min_len = self.0.min_byte_len();
72 let per = if min_len == 0 {
73 1
74 } else {
75 min_len
76 };
77 let estimate = remaining / per;
78 let mut values = Vec::with_capacity(initial_capacity::<Inner::PT>(estimate));
79
80 while remaining > 0
81 invariant
82 self.exec_inv(),
83 consumed + remaining == total_len,
84 remaining == rest@.len(),
85 ({
86 let prefix = values.deep_view();
87 let (n, suffix) = self.parse_rec(rest@);
88 self.parse_rec(ibuf@) == (consumed + n, prefix + suffix)
89 }),
90 decreases remaining,
91 {
92 broadcast use crate::core::spec::SafeParser::lemma_parse_safe;
93
94 reveal(<super::Star::<_> as SpecParser>::spec_parse);
95
96 match self.0.parse(&rest) {
97 Ok((n, v)) => {
98 proof {
99 self.0.lemma_productive(rest@);
100 assert(n > 0);
101 }
102 values.push(v);
103 rest = rest.skip(n);
104 consumed += n;
105 remaining -= n;
106 },
107 Err(_) => return Ok((consumed, values)),
108 }
109 }
110 Ok((consumed, values))
111 }
112}
113
114#[cfg(feature = "alloc")]
115impl<I, A, B> Parser<I> for super::Repeat<A, B> where
116 I: InputBuf,
117 A: Parser<I> + SafeParser + Productive + Copy,
118 B: Parser<I> + SafeParser + Copy,
119 {
120 type PT = (Vec<A::PT>, B::PT);
121
122 fn min_byte_len(&self) -> usize {
123 self.1.min_byte_len()
125 }
126
127 open spec fn exec_inv(&self) -> bool {
128 &&& self.0.exec_inv()
129 &&& self.0.safe_inv()
130 &&& self.0.productive_inv()
131 &&& self.1.exec_inv()
132 &&& self.1.safe_inv()
133 }
134
135 fn parse(&self, ibuf: &I) -> (r: PResult<Self::PT>) {
136 crate::combinators::Pair(super::Star(self.0), self.1).parse(ibuf)
137 }
138}
139
140#[cfg(feature = "alloc")]
141impl<I, Inner, N> Parser<I> for super::RepeatN<Inner, N> where
142 I: InputBuf,
143 Inner: Parser<I> + SafeParser,
144 N: AsLen,
145 {
146 type PT = Vec<Inner::PT>;
147
148 fn min_byte_len(&self) -> usize {
149 self.0.get().saturating_mul(self.1.min_byte_len())
151 }
152
153 open spec fn exec_inv(&self) -> bool {
154 &&& self.1.exec_inv()
155 &&& self.1.safe_inv()
156 }
157
158 fn parse(&self, ibuf: &I) -> (r: PResult<Self::PT>) {
159 broadcast use vstd::seq_lib::lemma_seq_skip_nothing;
160
161 let count = self.0.get();
162 let _total_len = ibuf.len();
163 let mut consumed: usize = 0;
164 let mut rest = ibuf.skip(0);
165 let reserve = if count < _total_len {
168 count
169 } else {
170 _total_len
171 };
172 let mut values = Vec::with_capacity(initial_capacity::<Inner::PT>(reserve));
173
174 for _i in 0..count
175 invariant
176 self.exec_inv(),
177 count as nat == self.0.as_nat(),
178 consumed + rest@.len() == _total_len,
179 ({
180 let prefix = values.deep_view();
181 let parsed = self.parse_n_rec(count as nat, ibuf@);
182 match self.parse_n_rec((count - _i) as nat, rest@) {
183 Some((n, suffix)) => parsed == Some((consumed + n, prefix + suffix)),
184 None => parsed is None,
185 }
186 }),
187 {
188 broadcast use crate::core::spec::SafeParser::lemma_parse_safe;
189
190 let (n, v) = self.1.parse(&rest)?;
191 values.push(v);
192 rest = rest.skip(n);
193 consumed += n;
194 }
195 Ok((consumed, values))
196 }
197}
198
199#[inline(always)]
220#[verifier::external_body]
221pub fn array_of_none<T, const N: usize>() -> (out: [Option<T>; N])
222 ensures
223 forall|j: int| 0 <= j < N ==> #[trigger] out@[j] is None,
224{
225 core::array::from_fn(|_i| None)
226}
227
228#[inline(always)]
229#[verifier::external_body]
230pub fn array_option_unwrap<T: DeepView, const N: usize>(arr: [Option<T>; N]) -> (out: [T; N])
231 requires
232 forall|j: int| 0 <= j < N ==> #[trigger] arr@[j] is Some,
233 ensures
234 out.deep_view() == Seq::new(N as nat, |j| arr@[j]->0.deep_view()),
235{
236 arr.map(Option::<T>::unwrap)
237}
238
239impl<I, Inner, const N: usize> Parser<I> for super::Array<N, Inner> where
240 I: InputBuf,
241 Inner: Parser<I> + SafeParser,
242 {
243 type PT = [Inner::PT; N];
244
245 fn min_byte_len(&self) -> usize {
246 N.saturating_mul(self.0.min_byte_len())
247 }
248
249 open spec fn exec_inv(&self) -> bool {
250 &&& self.0.exec_inv()
251 &&& self.0.safe_inv()
252 }
253
254 fn parse(&self, ibuf: &I) -> (r: PResult<Self::PT>) {
255 broadcast use vstd::seq_lib::lemma_seq_skip_nothing;
256
257 let mut consumed: usize = 0;
258 let _total_len = ibuf.len();
259 let mut rest = ibuf.skip(0);
260 let mut arr: [Option<Inner::PT>; N] = array_of_none();
261
262 for i in 0..N
263 invariant
264 self.exec_inv(),
265 consumed + rest@.len() == _total_len,
266 forall|j: int| 0 <= j < i ==> #[trigger] arr@[j] is Some,
267 forall|j: int| i <= j < N ==> #[trigger] arr@[j] is None,
268 ({
269 let prefix = Seq::new(i as nat, |j| arr@[j]->0.deep_view());
270 match super::RepeatN(N, self.0).parse_n_rec((N - i) as nat, rest@) {
271 Some((n, suffix)) => self.spec_parse(ibuf@) == Some(
272 (consumed + n, prefix + suffix),
273 ),
274 None => self.spec_parse(ibuf@) is None,
275 }
276 }),
277 {
278 broadcast use crate::core::spec::SafeParser::lemma_parse_safe;
279
280 let (n, v) = self.0.parse(&rest)?;
281 let elem = Some(v);
282 arr[i] = elem;
283 rest = rest.skip(n);
284 consumed += n;
285 }
286
287 let arr = array_option_unwrap(arr);
288
289 Ok((consumed, arr))
290 }
291}
292
293#[verifier::loop_isolation(false)]
294pub fn serialize_slice<Output, Inner, T>(inner: &Inner, values: &[T], obuf: &mut Output) where
295 Output: OutputBuf,
296 T: DeepView,
297 Inner: Serializer<Output, T>,
298
299 requires
300 inner.exec_inv(),
301 (super::Star(*inner)).consistent(values.deep_view()),
302 old(obuf).fits((super::Star(*inner)).byte_len(values.deep_view())),
303 ensures
304 final(obuf)@ == old(obuf)@ + spec_serialize_seq(inner, values.deep_view()),
305 forall|n|
306 old(obuf).fits((super::Star(*inner)).byte_len(values.deep_view()) + n)
307 <==> #[trigger] final(obuf).fits(n),
308 old(obuf).same_destination(final(obuf)),
309{
310 broadcast use crate::core::exec::output::outbuf_lemmas;
311
312 reveal(<super::Star::<_> as SpecByteLen>::byte_len);
313 reveal(<super::Star::<_> as Consistency>::consistent);
314
315 let ghost vs = values.deep_view();
316 let ghost star = super::Star(*inner);
317 let ghost mut consumed: nat = 0;
318
319 for value in iter: values.iter()
320 invariant
321 consumed + star.byte_len(vs[iter.index()..]) == star.byte_len(vs),
322 obuf@ == old(obuf)@ + spec_serialize_seq(inner, vs[0..iter.index()]),
323 forall|n| old(obuf).fits(consumed + n) <==> #[trigger] obuf.fits(n),
324 old(obuf).same_destination(obuf),
325 {
326 proof {
327 let i = iter.index();
328 let elem_len = inner.byte_len(vs[i as int]);
329 assert(vs[i..] == seq![vs[i]] + vs[i + 1..]);
330 star.lemma_byte_len_cons(vs[i], vs[i + 1..]);
331 assert(vs[0..i + 1] == vs[0..i].push(vs[i]));
332 assert(vs[0..i].push(vs[i]).drop_last() == vs[0..i]);
333 consumed = consumed + elem_len;
334 }
335 inner.serialize_into(value, obuf);
336 }
337}
338
339#[verifier::loop_isolation(false)]
340pub fn length_slice<Inner, T>(fmt: &Inner, values: &[T]) -> (len: usize) where
341 Inner: ByteLen<T>,
342 T: DeepView,
343
344 requires
345 fmt.exec_inv(),
346 (super::Star(*fmt)).byte_len(values.deep_view()) <= usize::MAX,
347 ensures
348 len == (super::Star(*fmt)).byte_len(values.deep_view()),
349{
350 reveal(<super::Star::<_> as SpecByteLen>::byte_len);
351 let ghost vs = values.deep_view();
352 let ghost star = super::Star(*fmt);
353
354 let mut len = 0usize;
355 for value in iter: values.iter()
356 invariant
357 len + star.byte_len(vs[iter.index()..]) == star.byte_len(vs),
358 {
359 proof {
360 let i = iter.index();
361 assert(vs[i..] == seq![vs[i]] + vs[i + 1..]);
362 star.lemma_byte_len_cons(vs[i], vs[i + 1..]);
363 }
364 let l = fmt.length(value);
365 len += l;
366 }
367 len
368}
369
370#[verifier::loop_isolation(false)]
371pub fn prepare_slice<Inner, T>(fmt: &Inner, values: &[T]) -> (checked: Result<
372 usize,
373 PreSerializeError,
374>) where Inner: Prepare<T>, T: DeepView
375 requires
376 fmt.exec_inv(),
377 ensures
378 checked matches Ok(len) ==> {
379 &&& (super::Star(*fmt)).consistent(values.deep_view())
380 &&& len == (super::Star(*fmt)).byte_len(values.deep_view())
381 },
382{
383 reveal(<super::Star::<_> as Consistency>::consistent);
384 reveal(<super::Star::<_> as SpecByteLen>::byte_len);
385 let ghost vs = values.deep_view();
386 let ghost star = super::Star(*fmt);
387
388 let mut len = 0usize;
389 for value in iter: values.iter()
390 invariant
391 forall|j: int| 0 <= j < iter.index() ==> fmt.consistent(#[trigger] vs[j]),
392 len + star.byte_len(vs[iter.index()..]) == star.byte_len(vs),
393 {
394 proof {
395 let i = iter.index();
396 assert(vs[i..] == seq![vs[i]] + vs[i + 1..]);
397 star.lemma_byte_len_cons(vs[i], vs[i + 1..]);
398 }
399 let elem_len = fmt.prepare(value)?;
400 match len.checked_add(elem_len) {
401 Some(total) => len = total,
402 None => return Err(PreSerializeError::length_too_large()),
403 }
404 }
405 Ok(len)
406}
407
408impl<Output: OutputBuf, Inner, T> Serializer<Output, [T]> for super::Star<Inner> where
409 T: DeepView,
410 Inner: Serializer<Output, T>,
411 {
412 #[verifier::prophetic]
413 open spec fn exec_inv(&self) -> bool {
414 self.0.exec_inv()
415 }
416
417 fn serialize_into(&self, v: &[T], obuf: &mut Output) {
418 reveal(<super::Star::<_> as SpecSerializer>::spec_serialize);
419 serialize_slice(&self.0, v, obuf);
420 }
421}
422
423impl<Inner, T> ByteLen<[T]> for super::Star<Inner> where Inner: ByteLen<T>, T: DeepView {
424 open spec fn exec_inv(&self) -> bool {
425 self.0.exec_inv()
426 }
427
428 fn length(&self, v: &[T]) -> (len: usize) {
429 length_slice(&self.0, v)
430 }
431}
432
433impl<Inner, T> Prepare<[T]> for super::Star<Inner> where Inner: Prepare<T>, T: DeepView {
434 open spec fn exec_inv(&self) -> bool {
435 self.0.exec_inv()
436 }
437
438 fn prepare(&self, v: &[T]) -> (checked: Result<usize, PreSerializeError>) {
439 prepare_slice(&self.0, v)
440 }
441}
442
443impl<Output: OutputBuf, A, B, TA, TB> Serializer<Output, (&[TA], TB)> for super::Repeat<A, B> where
444 TA: DeepView,
445 TB: DeepView,
446 A: Serializer<Output, TA> + Copy,
447 B: Serializer<Output, TB>,
448 {
449 #[verifier::prophetic]
450 open spec fn exec_inv(&self) -> bool {
451 &&& self.0.exec_inv()
452 &&& self.1.exec_inv()
453 }
454
455 fn serialize_into(&self, v: &(&[TA], TB), obuf: &mut Output) {
456 broadcast use crate::core::exec::output::outbuf_lemmas;
457
458 reveal(<super::Star<_> as SpecSerializer>::spec_serialize);
459
460 super::Star(self.0).serialize_into(v.0, obuf);
461 assert(obuf.fits(self.1.byte_len(v.deep_view().1)));
462 self.1.serialize_into(&v.1, obuf);
463 }
464}
465
466impl<A, B, TA, TB> ByteLen<(&[TA], TB)> for super::Repeat<A, B> where
467 A: ByteLen<TA> + Copy,
468 B: ByteLen<TB>,
469 TA: DeepView,
470 TB: DeepView,
471 {
472 open spec fn exec_inv(&self) -> bool {
473 &&& self.0.exec_inv()
474 &&& self.1.exec_inv()
475 }
476
477 fn length(&self, v: &(&[TA], TB)) -> (len: usize) {
478 let la = super::Star(self.0).length(v.0);
479 let lb = self.1.length(&v.1);
480 la + lb
481 }
482}
483
484impl<A, B, TA, TB> Prepare<(&[TA], TB)> for super::Repeat<A, B> where
485 A: Prepare<TA> + Copy,
486 B: Prepare<TB>,
487 TA: DeepView,
488 TB: DeepView,
489 {
490 open spec fn exec_inv(&self) -> bool {
491 &&& self.0.exec_inv()
492 &&& self.1.exec_inv()
493 }
494
495 fn prepare(&self, v: &(&[TA], TB)) -> (checked: Result<usize, PreSerializeError>) {
496 let la = super::Star(self.0).prepare(v.0)?;
497 let lb = self.1.prepare(&v.1)?;
498 match la.checked_add(lb) {
499 Some(total) => Ok(total),
500 None => Err(PreSerializeError::length_too_large()),
501 }
502 }
503}
504
505impl<Output: OutputBuf, Inner, N, T> Serializer<Output, [T]> for super::RepeatN<Inner, N> where
506 T: DeepView,
507 Inner: Serializer<Output, T>,
508 N: AsLen,
509 {
510 #[verifier::prophetic]
511 open spec fn exec_inv(&self) -> bool {
512 self.1.exec_inv()
513 }
514
515 fn serialize_into(&self, v: &[T], obuf: &mut Output) {
516 broadcast use crate::core::exec::output::outbuf_lemmas;
517
518 serialize_slice(&self.1, v, obuf);
519 }
520}
521
522impl<Inner, N, T> ByteLen<[T]> for super::RepeatN<Inner, N> where
523 Inner: ByteLen<T>,
524 T: DeepView,
525 N: AsLen,
526 {
527 open spec fn exec_inv(&self) -> bool {
528 self.1.exec_inv()
529 }
530
531 fn length(&self, v: &[T]) -> (len: usize) {
532 length_slice(&self.1, v)
533 }
534}
535
536impl<Inner, N, T> Prepare<[T]> for super::RepeatN<Inner, N> where
537 Inner: Prepare<T>,
538 T: DeepView,
539 N: AsLen,
540 {
541 open spec fn exec_inv(&self) -> bool {
542 self.1.exec_inv()
543 }
544
545 fn prepare(&self, v: &[T]) -> (checked: Result<usize, PreSerializeError>) {
546 if v.len() == self.0.get() {
547 prepare_slice(&self.1, v)
548 } else {
549 Err(PreSerializeError::not_compliant(ComplianceErrorKind::LengthInconsistent))
550 }
551 }
552}
553
554impl<Output: OutputBuf, Inner, T, const N: usize> Serializer<Output, [T; N]> for super::Array<
555 N,
556 Inner,
557> where T: DeepView, Inner: Serializer<Output, T> {
558 #[verifier::prophetic]
559 open spec fn exec_inv(&self) -> bool {
560 self.0.exec_inv()
561 }
562
563 fn serialize_into(&self, v: &[T; N], obuf: &mut Output) {
564 broadcast use crate::core::exec::output::outbuf_lemmas;
565
566 serialize_slice(&self.0, v, obuf);
567 }
568}
569
570impl<Inner, T, const N: usize> ByteLen<[T; N]> for super::Array<N, Inner> where
571 Inner: ByteLen<T>,
572 T: DeepView,
573 {
574 open spec fn exec_inv(&self) -> bool {
575 self.0.exec_inv()
576 }
577
578 fn length(&self, v: &[T; N]) -> (len: usize) {
579 length_slice(&self.0, v.as_slice())
580 }
581}
582
583impl<Inner, T, const N: usize> Prepare<[T; N]> for super::Array<N, Inner> where
584 Inner: Prepare<T>,
585 T: DeepView,
586 {
587 open spec fn exec_inv(&self) -> bool {
588 self.0.exec_inv()
589 }
590
591 fn prepare(&self, v: &[T; N]) -> (checked: Result<usize, PreSerializeError>) {
592 prepare_slice(&self.0, v.as_slice())
593 }
594}
595
596} #[cfg(all(test, feature = "alloc"))]
598mod reservation_tests {
599 use super::initial_capacity;
600
601 #[test]
602 fn speculative_reservation_is_bounded_in_bytes() {
603 assert_eq!(initial_capacity::<u8>(32), 32);
604 assert_eq!(initial_capacity::<u8>(usize::MAX), 16_384);
605 assert_eq!(initial_capacity::<[u8; 832]>(309_417), 19);
606 assert_eq!(initial_capacity::<[u8; 32_768]>(usize::MAX), 0);
607 assert_eq!(initial_capacity::<()>(usize::MAX), 0);
608 assert_eq!(initial_capacity::<u64>(0), 0);
609 }
610}