Skip to main content

uts_core/codec/
proof.rs

1use crate::{
2    alloc::{Allocator, Global},
3    codec::{DecodeIn, Decoder, Encode, Encoder},
4    error::{DecodeError, EncodeError},
5};
6use core::fmt;
7use std::ops::{Deref, DerefMut};
8
9/// Version number of the serialization format.
10pub type Version = u32;
11
12/// Trait implemented by proof payloads for a specific serialization version.
13pub trait Proof<A: Allocator = Global>: Encode + DecodeIn<A> {
14    /// Version identifier that must match the encoded proof.
15    const VERSION: Version;
16}
17
18/// Wrapper that prefixes a proof with its version and magic bytes.
19#[derive(Clone, PartialEq, Eq, Debug)]
20pub struct VersionedProof<T: Proof<A>, A: Allocator = Global> {
21    pub proof: T,
22    allocator: A,
23}
24
25impl<T: Proof<Global>> VersionedProof<T, Global> {
26    /// Creates a new versioned proof with the global allocator.
27    pub fn new(proof: T) -> Self {
28        VersionedProof {
29            proof,
30            allocator: Global,
31        }
32    }
33}
34
35impl<T: Proof<A>, A: Allocator> VersionedProof<T, A> {
36    /// Creates a new versioned proof with the specified allocator.
37    pub fn new_with_allocator(proof: T, allocator: A) -> Self {
38        VersionedProof { proof, allocator }
39    }
40
41    /// Returns a reference to the proof payload.
42    pub fn proof(&self) -> &T {
43        &self.proof
44    }
45
46    /// Returns a reference to the allocator used by this proof.
47    pub fn allocator(&self) -> &A {
48        &self.allocator
49    }
50}
51
52impl<T: Proof<A>, A: Allocator + Clone> DecodeIn<A> for VersionedProof<T, A> {
53    fn decode_in(decoder: &mut impl Decoder, alloc: A) -> Result<Self, DecodeError> {
54        decoder.assert_magic()?;
55        let version: Version = decoder.decode()?;
56        if version != T::VERSION {
57            return Err(DecodeError::BadVersion);
58        }
59        Ok(VersionedProof {
60            proof: T::decode_in(decoder, alloc.clone())?,
61            allocator: alloc,
62        })
63    }
64}
65
66impl<T: Proof<A>, A: Allocator> Encode for VersionedProof<T, A> {
67    fn encode(&self, encoder: &mut impl Encoder) -> Result<(), EncodeError> {
68        encoder.encode_magic()?;
69        encoder.encode(T::VERSION)?;
70        self.proof.encode(encoder)
71    }
72}
73
74impl<T: Proof<A> + fmt::Display, A: Allocator> fmt::Display for VersionedProof<T, A> {
75    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76        write!(f, "Version {} Proof {}", T::VERSION, self.proof)
77    }
78}
79
80impl<T: Proof<A>, A: Allocator> Deref for VersionedProof<T, A> {
81    type Target = T;
82
83    fn deref(&self) -> &Self::Target {
84        &self.proof
85    }
86}
87
88impl<T: Proof<A>, A: Allocator> DerefMut for VersionedProof<T, A> {
89    fn deref_mut(&mut self) -> &mut Self::Target {
90        &mut self.proof
91    }
92}