Skip to main content

vest_lib/core/exec/
serializer.rs

1//! Executable serializer traits.
2use crate::core::exec::output::*;
3use crate::core::spec::{Consistency, GoodSerializer, SpecByteLen, SpecSerializer};
4use core::fmt;
5use core::marker::PhantomData;
6
7#[cfg(feature = "alloc")]
8use alloc::vec::Vec;
9
10use vstd::prelude::*;
11
12verus! {
13
14/// An executable serializer targeting `Output`.
15pub trait Serializer<Output, T> where
16    Output: OutputBuf,
17    Self: SpecByteLen<T = T::V> + SpecSerializer<SVal = T::V> + Consistency<Val = T::V>,
18    T: DeepView + ?Sized,
19 {
20    #[verifier::prophetic]
21    open spec fn exec_inv(&self) -> bool {
22        true
23    }
24
25    /// Serializes the value `v` into the output buffer `obuf` by (logically) appending the serialized bytes to the end of `obuf`.
26    /// This view has two main benefits:
27    /// 1. It matches the [specification](SpecSerializer) of the serializer closely, which simplifies the proofs;
28    /// 2. It is general enough to support both fixed-size (e.g., `&mut [u8]`) and growable (e.g., `Vec<u8>`) output buffers (see [`OutputBuf`]).
29    ///
30    /// ## Preconditions
31    ///
32    /// - The serializer's execution invariant holds (mainly used for [`super::fns::FnSerializer`], usually trivial for most combinators).
33    /// - The value `v` is [compliant](Consistency) with the format specification.
34    /// - The output buffer has enough space to hold the serialized value.
35    ///
36    /// ## Postconditions
37    ///
38    /// - The output buffer's contents are extended by the serialized value.
39    /// - The output buffer's remaining capacity is reduced by the serialized value's length.
40    /// - The output buffer's destination remains the same.
41    fn serialize_into(&self, v: &T, obuf: &mut Output)
42        requires
43            self.exec_inv(),
44            self.consistent(v.deep_view()),
45            old(obuf).fits(self.byte_len(v.deep_view())),
46        ensures
47            final(obuf)@ == old(obuf)@ + self.spec_serialize(v.deep_view()),
48            forall|n| old(obuf).fits(self.byte_len(v.deep_view()) + n) <==> final(obuf).fits(n),
49            old(obuf).same_destination(final(obuf)),
50    ;
51}
52
53/// Convenience entry points for the two standard output destinations.
54pub trait SerializerExt<T> where
55    Self: SpecByteLen<T = T::V> + SpecSerializer<SVal = T::V> + Consistency<Val = T::V>,
56    T: DeepView + ?Sized,
57 {
58    /// Serializes into an exactly-sized caller-provided slice without allocating.
59    fn serialize<'a>(&self, v: &T, obuf: &'a mut [u8]) where Self: Serializer<OutputSlice<'a>, T>
60        requires
61            self.exec_inv(),
62            self.consistent(v.deep_view()),
63            obuf@.len() == self.byte_len(v.deep_view()),
64        ensures
65            final(obuf)@ == self.spec_serialize(v.deep_view()),
66    {
67        let mut output = OutputSlice::new(obuf);
68        self.serialize_into(v, &mut output);
69        proof {
70            assert(output.fits(0));
71            assert(!output.fits(1));
72            assert(output.pos == output.obuf@.len());
73        }
74    }
75
76    /// Serializes by appending to a growable Vec (though the Vec can be preallocated with [`Prepare`]/[`ByteLen`]).
77    #[cfg(feature = "alloc")]
78    fn serialize_with_vec(&self, v: &T, obuf: &mut Vec<u8>) where Self: Serializer<Vec<u8>, T>
79        requires
80            self.exec_inv(),
81            self.consistent(v.deep_view()),
82        ensures
83            final(obuf)@ == old(obuf)@ + self.spec_serialize(v.deep_view()),
84    {
85        self.serialize_into(v, obuf);
86    }
87}
88
89impl<T: DeepView + ?Sized, S> SerializerExt<T> for S where
90    S: SpecByteLen<T = T::V> + SpecSerializer<SVal = T::V> + Consistency<Val = T::V>,
91 {
92
93}
94
95#[derive(Debug, Copy, Clone, PartialEq, Eq)]
96/// Why a value does not satisfy a format's specification.
97pub enum ComplianceErrorKind {
98    /// A stored or derived length does not match the corresponding value.
99    LengthInconsistent,
100    /// A tag is outside the domain accepted by the format.
101    InvalidTag,
102    /// A [`Refined`](crate::combinators::Refined) predicate rejected the value.
103    PredicateFailed,
104    /// A conditional combinator is disabled for this value.
105    CondRejected,
106    /// A recursive value exceeds the format's configured recursion limit.
107    RecursionLimitExceeded,
108    /// No branch of a choice accepts the value.
109    InvalidChoice,
110    /// A format-specific consistency error.
111    Custom(&'static str),
112}
113
114#[derive(Debug, Copy, Clone, PartialEq, Eq)]
115/// Top-level reason that preparation failed.
116pub enum PreSerializeErrorKind {
117    /// The exact serialized length cannot be represented by `usize`.
118    LengthTooLarge,
119    /// The value is not accepted by the format.
120    NotCompliant(ComplianceErrorKind),
121}
122
123#[derive(Debug, PartialEq, Eq)]
124/// Error returned by [`Prepare::prepare`].
125///
126/// `failed_format` identifies the innermost named format that attached
127/// context. With the `alloc` feature, `format_stack` retains the complete
128/// format trace.
129pub struct PreSerializeError {
130    /// The underlying failure category.
131    pub kind: PreSerializeErrorKind,
132    /// The innermost named format that reported the failure, if available.
133    pub failed_format: Option<&'static str>,
134    #[cfg(feature = "alloc")]
135    /// Nested format names collected while propagating the error.
136    pub format_stack: Vec<&'static str>,
137}
138
139impl Clone for PreSerializeError {
140    fn clone(&self) -> Self {
141        Self {
142            kind: self.kind,
143            failed_format: self.failed_format,
144            #[cfg(feature = "alloc")]
145            format_stack: self.format_stack.clone(),
146        }
147    }
148}
149
150impl PreSerializeError {
151    /// Creates an error without attached format context.
152    pub fn new(kind: PreSerializeErrorKind) -> Self {
153        Self {
154            kind,
155            failed_format: None,
156            #[cfg(feature = "alloc")]
157            format_stack: Vec::new(),
158        }
159    }
160
161    /// Creates a serialized-length overflow error.
162    pub fn length_too_large() -> Self {
163        Self::new(PreSerializeErrorKind::LengthTooLarge)
164    }
165
166    /// Creates a value-compliance error.
167    pub fn not_compliant(kind: ComplianceErrorKind) -> Self {
168        Self::new(PreSerializeErrorKind::NotCompliant(kind))
169    }
170
171    /// Creates a format-specific value-compliance error.
172    pub fn custom(msg: &'static str) -> Self {
173        Self::new(PreSerializeErrorKind::NotCompliant(ComplianceErrorKind::Custom(msg)))
174    }
175
176    /// Adds a named format to the error's propagation trace.
177    pub fn push_format(self, current_format: &'static str) -> Self {
178        let mut err = self;
179        if err.failed_format.is_none() {
180            err.failed_format = Some(current_format);
181        }
182        #[cfg(feature = "alloc")]
183        {
184            err.format_stack.push(current_format);
185        }
186        err
187    }
188
189    /// Returns the innermost named format that attached context.
190    pub fn failed_format(&self) -> Option<&'static str> {
191        self.failed_format
192    }
193
194    /// Returns the collected format trace, or an empty slice without `alloc`.
195    pub fn format_trace(&self) -> &[&'static str] {
196        #[cfg(feature = "alloc")]
197        { self.format_stack.as_slice() }
198        #[cfg(not(feature = "alloc"))]
199        { &[] }
200    }
201}
202
203/// Checks that a value can be serialized and computes its exact output length.
204///
205/// Call this before allocating an output or invoking [`SerializerExt::serialize`]
206/// on a value whose consistency has not already been established.
207pub trait Prepare<T>: SpecByteLen<T = T::V> + Consistency<Val = T::V> where T: DeepView + ?Sized {
208    /// Extra invariant required by the executable preparation implementation.
209    open spec fn exec_inv(&self) -> bool {
210        true
211    }
212
213    /// Validates `v` and returns its exact serialized length.
214    fn prepare(&self, v: &T) -> (checked: Result<usize, PreSerializeError>)
215        requires
216            self.exec_inv(),
217        ensures
218            checked matches Ok(len) ==> {
219                &&& self.consistent(v.deep_view())
220                &&& len == self.byte_len(v.deep_view())
221            },
222    ;
223}
224
225/// Computes the exact serialized length of a value already known to fit `usize`.
226///
227/// Unlike [`Prepare`], this operation does not check the format's consistency
228/// predicate. Use `Prepare::prepare` for untrusted or newly constructed values.
229pub trait ByteLen<T> where Self: SpecByteLen<T = T::V>, T: DeepView + ?Sized {
230    /// Extra invariant required by the executable length implementation.
231    open spec fn exec_inv(&self) -> bool {
232        true
233    }
234
235    /// Returns the exact number of bytes produced by serialization.
236    fn length(&self, v: &T) -> (len: usize)
237        requires
238            self.exec_inv(),
239            self.byte_len(v.deep_view()) <= usize::MAX,
240        ensures
241            len == self.byte_len(v.deep_view()),
242    ;
243}
244
245impl<T: ?Sized, S> Prepare<T> for &S where T: DeepView, S: Prepare<T> {
246    open spec fn exec_inv(&self) -> bool {
247        (*self).exec_inv()
248    }
249
250    fn prepare(&self, v: &T) -> (checked: Result<usize, PreSerializeError>) {
251        (*self).prepare(v)
252    }
253}
254
255impl<T: ?Sized, S> ByteLen<T> for &S where T: DeepView, S: ByteLen<T> {
256    open spec fn exec_inv(&self) -> bool {
257        (*self).exec_inv()
258    }
259
260    fn length(&self, v: &T) -> (len: usize) {
261        (*self).length(v)
262    }
263}
264
265impl<S: SpecSerializer> SpecSerializer for &S {
266    type SVal = S::SVal;
267
268    open spec fn spec_serialize(&self, v: Self::SVal) -> Seq<u8> {
269        (*self).spec_serialize(v)
270    }
271}
272
273impl<S: SpecByteLen> SpecByteLen for &S {
274    type T = S::T;
275
276    open spec fn byte_len(&self, v: Self::T) -> nat {
277        (*self).byte_len(v)
278    }
279}
280
281impl<S: GoodSerializer> GoodSerializer for &S {
282    open spec fn serialize_inv(&self) -> bool {
283        (*self).serialize_inv()
284    }
285
286    proof fn lemma_serialize_len(&self, v: Self::SVal) {
287        (*self).lemma_serialize_len(v)
288    }
289}
290
291impl<S: Consistency> Consistency for &S {
292    type Val = S::Val;
293
294    open spec fn consistent(&self, v: Self::Val) -> bool {
295        (*self).consistent(v)
296    }
297}
298
299impl<Output, T, S> Serializer<Output, T> for &S where
300    Output: OutputBuf,
301    T: DeepView + ?Sized,
302    S: Serializer<Output, T>,
303 {
304    #[verifier::prophetic]
305    open spec fn exec_inv(&self) -> bool {
306        (*self).exec_inv()
307    }
308
309    fn serialize_into(&self, v: &T, obuf: &mut Output) {
310        (*self).serialize_into(v, obuf)
311    }
312}
313
314// pub trait ByteLen<Fmt> where
315//     Self: DeepView,
316//     Fmt: ValueByteLen<T = Self::V> + Consistency<Val = Self::V>,
317//  {
318//     fn byte_len_for(&self, binary_fmt: &Fmt) -> (len: usize)
319//         requires
320//             binary_fmt.consistent(self.deep_view()),
321//             binary_fmt.byte_len(self.deep_view())
322//                 <= usize::MAX,
323//     // Fmt::value_byte_len(self.deep_view()) <= usize::MAX,
324//         ensures
325//             binary_fmt.consistent(self.deep_view()),
326//             len == binary_fmt.byte_len(
327//                 self.deep_view(),
328//             ),
329//     // len == Fmt::value_byte_len(self.deep_view()),
330//     ;
331// }
332// impl ByteLen<U8> for u8 {
333//     fn byte_len_for(&self, _binary_fmt: &U8) -> usize {
334//         1
335//     }
336// }
337// impl ByteLen<U16Be> for u16 {
338//     fn byte_len_for(&self, _binary_fmt: &U16Be) -> usize {
339//         2
340//     }
341// }
342// impl ByteLen<U16Le> for u16 {
343//     fn byte_len_for(&self, _binary_fmt: &U16Le) -> usize {
344//         2
345//     }
346// }
347// impl ByteLen<Const<U8, u8>> for u8 {
348//     fn byte_len_for(&self, _binary_fmt: &Const<U8, u8>) -> usize {
349//         1
350//     }
351// }
352// impl<'x, const N: usize> ByteLen<Fixed<N>> for &'x [u8] {
353//     fn byte_len_for(&self, _binary_fmt: &Fixed<N>) -> usize {
354//         N
355//     }
356// }
357// impl<'x, Len: AsLen> ByteLen<Varied<Len>> for &'x [u8] {
358//     fn byte_len_for(&self, _binary_fmt: &Varied<Len>) -> usize {
359//         self.len()
360//     }
361// }
362// impl<FmtA, FmtB, A, B> ByteLen<Pair<FmtA, FmtB>> for (A, B) where
363//     A: ByteLen<FmtA>,
364//     B: ByteLen<FmtB>,
365//     FmtA: ValueByteLen<T = A::V>,
366//     FmtB: ValueByteLen<T = B::V>,
367//  {
368//     fn byte_len_for(&self, binary_fmt: &Pair<FmtA, FmtB>) -> usize {
369//         self.0.byte_len_for(&binary_fmt.0) + self.1.byte_len_for(&binary_fmt.1)
370//     }
371// }
372// // impl<FmtA, FmtB, A, B> ByteLen<Preceded<FmtA, A, FmtB>> for B where
373// //     A: ByteLen<FmtA>,
374// //     B: ByteLen<FmtB>,
375// //     FmtA: ValueByteLen<T = A::V>,
376// //     FmtB: ValueByteLen<T = B::V>,
377// //  {
378// //     fn byte_len_for(&self, binary_fmt: &Preceded<FmtA, A, FmtB>) -> usize {
379// //         self.byte_len_for(&binary_fmt.b)
380// //     }
381// // }
382// impl<FmtA, FmtB, A, B> ByteLen<Choice<FmtA, FmtB>> for Sum<A, B> where
383//     A: ByteLen<FmtA>,
384//     B: ByteLen<FmtB>,
385//     FmtA: ValueByteLen<T = A::V>,
386//     FmtB: ValueByteLen<T = B::V>,
387//  {
388//     fn byte_len_for(&self, binary_fmt: &Choice<FmtA, FmtB>) -> usize {
389//         match self {
390//             Sum::Inl(a) => a.byte_len_for(&binary_fmt.0),
391//             Sum::Inr(b) => b.byte_len_for(&binary_fmt.1),
392//         }
393//     }
394// }
395// impl<Fmt, Predicate, T> ByteLen<Refined<Fmt, Predicate>> for T where
396//     T: ByteLen<Fmt>,
397//     Fmt: ValueByteLen<T = T::V>,
398//     Predicate: Pred<T>,
399//  {
400//     fn byte_len_for(&self, binary_fmt: &Refined<Fmt, Predicate>) -> usize {
401//         self.byte_len_for(&binary_fmt.0)
402//     }
403// }
404// impl<Fmt, Map, T> ByteLen<Mapped<Fmt, Map>> for T where
405//     T: DeepView<V = Map::Out>,
406//     Fmt: ValueByteLen<T = Map::In>,
407//     Map: for <'i>Mapper<&'i [u8], SOut = T>,
408//     for <'i><Map as Mapper<&'i [u8]>>::SIn: ByteLen<Fmt>,
409//  {
410//     fn byte_len_for(&self, binary_fmt: &Mapped<Fmt, Map>) -> usize {
411//         let mapped_in = Map::map_rev(self);
412//         mapped_in.byte_len_for(&binary_fmt.inner)
413//     }
414// }
415// #[verifier::allow_in_spec]
416// pub fn small_nonzero(value: &u16) -> bool
417//     returns
418//         *value != 0,
419// {
420//     *value != 0
421// }
422// struct SmallNonZero;
423// impl SpecPred<u16> for SmallNonZero {
424//     open spec fn apply(&self, value: u16) -> bool {
425//         small_nonzero(&value)
426//     }
427// }
428// impl Pred<u16> for SmallNonZero {
429//     fn test(&self, value: &u16) -> (ok: bool) {
430//         small_nonzero(value)
431//     }
432// }
433// pub struct Triple {
434//     pub a: u8,
435//     pub b: u16,
436//     pub c: u8,
437// }
438// impl DeepView for Triple {
439//     type V = Self;
440//     open spec fn deep_view(&self) -> Self::V {
441//         *self
442//     }
443// }
444// pub struct TripleMapper;
445// impl SpecMapper for TripleMapper {
446//     type In = (u8, (u16, u8));
447//     type Out = Triple;
448//     open spec fn spec_map(i: Self::In) -> Self::Out {
449//         Triple { a: i.0, b: i.1.0, c: i.1.1 }
450//     }
451//     open spec fn spec_map_rev(o: Self::Out) -> Self::In {
452//         (o.a, (o.b, o.c))
453//     }
454// }
455// impl Mapper<&[u8]> for TripleMapper {
456//     type PIn = (u8, (u16, u8));
457//     type POut = Triple;
458//     type SIn = (u8, (u16, u8));
459//     type SOut = Triple;
460//     fn map(i: Self::PIn) -> Self::POut {
461//         Triple { a: i.0, b: i.1.0, c: i.1.1 }
462//     }
463//     fn map_rev(o: &Self::SOut) -> Self::SIn {
464//         (o.a, (o.b, o.c))
465//     }
466// }
467// pub struct TrippleRefView {
468//     pub a: u8,
469//     pub b: u16,
470//     pub c: Seq<u8>,
471// }
472// pub struct TripleRef<'i> {
473//     pub a: u8,
474//     pub b: u16,
475//     pub c: &'i [u8],
476// }
477// impl DeepView for TripleRef<'_> {
478//     type V = TrippleRefView;
479//     open spec fn deep_view(&self) -> Self::V {
480//         TrippleRefView { a: self.a, b: self.b, c: self.c.deep_view() }
481//     }
482// }
483// pub struct TripleRefMapper;
484// impl SpecMapper for TripleRefMapper {
485//     type In = (u8, (u16, Seq<u8>));
486//     type Out = TrippleRefView;
487//     open spec fn spec_map(i: Self::In) -> Self::Out {
488//         TrippleRefView { a: i.0, b: i.1.0, c: i.1.1 }
489//     }
490//     open spec fn spec_map_rev(o: Self::Out) -> Self::In {
491//         (o.a, (o.b, o.c))
492//     }
493// }
494// impl<'i> Mapper<&'i [u8]> for TripleRefMapper {
495//     type PIn = (u8, (u16, &'i [u8]));
496//     type POut = TripleRef<'i>;
497//     type SIn = (u8, (u16, &'i [u8]));
498//     type SOut = TripleRef<'i>;
499//     fn map(i: Self::PIn) -> Self::POut {
500//         TripleRef { a: i.0, b: i.1.0, c: i.1.1 }
501//     }
502//     fn map_rev(o: &Self::SOut) -> Self::SIn {
503//         (o.a, (o.b, o.c))
504//     }
505// }
506// fn test_fmt_len() {
507//     // let x = (0u8, (2u16, 4u8));
508//     // let my_fmt = Pair(U8, Pair(Refined(U16Le, SmallNonZero), U8));
509//     // let x = Triple { a: 0u8, b: 2u16, c: 4u8 };
510//     // let my_fmt = Mapped {
511//     //     inner: Pair(U8, Pair(Refined(U16Le, SmallNonZero), U8)),
512//     //     mapper: TripleMapper,
513//     // };
514//     let arr = [1u8, 0u8, 2u8, 4u8];
515//     let x = TripleRef { a: 0u8, b: 2u16, c: &arr };
516//     let my_fmt = Mapped {
517//         inner: Pair(
518//             Const(U8, 0),
519//             Pair(Refined(U16Le, SmallNonZero), Fixed::<4>),
520//         ),
521//         mapper: TripleRefMapper,
522//     };
523//     let len = x.byte_len_for(&my_fmt);
524//     assert(len == 1 + 2 + 4);
525// }
526// pub trait ByteLen<Fmt> where Self: DeepView, Fmt: ValueByteLen<T = Self::V>,  {
527//     fn length(&self) -> (len: usize)
528//         requires
529//             Fmt::value_byte_len(self.deep_view()) <= usize::MAX,
530//         ensures
531//             len == Fmt::value_byte_len(self.deep_view()),
532//     ;
533// }
534// use crate::combinators::{U8, U16Le, U16Be, Pair};
535// impl ByteLen<U8> for u8 {
536//     fn length(&self) -> usize {
537//         1
538//     }
539// }
540// impl ByteLen<U16Be> for u16 {
541//     fn length(&self) -> usize {
542//         2
543//     }
544// }
545// impl ByteLen<U16Le> for u16 {
546//     fn length(&self) -> usize {
547//         2
548//     }
549// }
550// impl<FmtA, FmtB, A, B> ByteLen<Pair<FmtA, FmtB>> for (A, B) where
551//     A: ByteLen<FmtA>,
552//     B: ByteLen<FmtB>,
553//     FmtA: ValueByteLen<T = A::V>,
554//     FmtB: ValueByteLen<T = B::V>,
555//  {
556//     fn length(&self) -> usize {
557//         self.0.length() + self.1.length()
558//     }
559// }
560// fn test_fmt_len() {
561//     let x = (0u8, 0u16);
562//     let len = <_ as ByteLen<Pair<U8, U16Le>>>::length(&x);
563//     assert(len == 3);
564// }
565} // verus!
566impl fmt::Display for ComplianceErrorKind {
567    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
568        match self {
569            ComplianceErrorKind::LengthInconsistent => {
570                f.write_str("value length does not match the format's declared length")
571            }
572            ComplianceErrorKind::InvalidTag => {
573                f.write_str("value does not match the required tag or discriminant")
574            }
575            ComplianceErrorKind::PredicateFailed => {
576                f.write_str("value failed a refinement predicate")
577            }
578            ComplianceErrorKind::CondRejected => {
579                f.write_str("conditional format rejected this value")
580            }
581            ComplianceErrorKind::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
582            ComplianceErrorKind::InvalidChoice => {
583                f.write_str("value does not match any choice branch")
584            }
585            ComplianceErrorKind::Custom(s) => f.write_str(s),
586        }
587    }
588}
589
590impl fmt::Display for PreSerializeErrorKind {
591    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
592        match self {
593            PreSerializeErrorKind::LengthTooLarge => {
594                f.write_str("computed encoded length exceeds usize::MAX")
595            }
596            PreSerializeErrorKind::NotCompliant(kind) => write!(f, "{}", kind),
597        }
598    }
599}
600
601impl fmt::Display for PreSerializeError {
602    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
603        let format_trace = self.format_trace();
604        if !format_trace.is_empty() {
605            write!(f, "{} while preparing format stack ", self.kind)?;
606            for (i, format_name) in format_trace.iter().rev().enumerate() {
607                if i > 0 {
608                    f.write_str(" -> ")?;
609                }
610                write!(f, "`{}`", format_name)?;
611            }
612            Ok(())
613        } else {
614            match self.failed_format {
615                Some(current_format) => {
616                    write!(
617                        f,
618                        "{} while preparing format `{}`",
619                        self.kind, current_format
620                    )
621                }
622                None => write!(f, "{}", self.kind),
623            }
624        }
625    }
626}
627
628#[cfg(feature = "std")]
629impl std::error::Error for PreSerializeError {}