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
9pub type Version = u32;
11
12pub trait Proof<A: Allocator = Global>: Encode + DecodeIn<A> {
14 const VERSION: Version;
16}
17
18#[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 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 pub fn new_with_allocator(proof: T, allocator: A) -> Self {
38 VersionedProof { proof, allocator }
39 }
40
41 pub fn proof(&self) -> &T {
43 &self.proof
44 }
45
46 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}