Skip to main content

vest_lib/core/exec/
serializer.rs

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