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 {}