@@ -146,10 +146,10 @@ impl From<PathIterItem> for ProofNode {
146146}
147147
148148/// A proof that a given key-value pair either exists or does not exist in a trie.
149- #[ derive( Clone , Debug ) ]
150- pub struct Proof < T : Hashable > ( pub Box < [ T ] > ) ;
149+ #[ derive( Clone , Debug , PartialEq , Eq , Default ) ]
150+ pub struct Proof < T : ? Sized > ( T ) ;
151151
152- impl < T : Hashable > Proof < T > {
152+ impl < T : ProofCollection + ? Sized > Proof < T > {
153153 /// Verify a proof
154154 pub fn verify < K : AsRef < [ u8 ] > , V : AsRef < [ u8 ] > > (
155155 & self ,
@@ -164,20 +164,20 @@ impl<T: Hashable> Proof<T> {
164164 /// with the given `root_hash`. If the key does not exist in the trie, returns `None`.
165165 /// Returns an error if the proof is invalid or doesn't prove the key for the
166166 /// given revision.
167- fn value_digest < K : AsRef < [ u8 ] > > (
167+ pub fn value_digest < K : AsRef < [ u8 ] > > (
168168 & self ,
169169 key : K ,
170170 root_hash : & TrieHash ,
171171 ) -> Result < Option < ValueDigest < & [ u8 ] > > , ProofError > {
172172 let key: Box < [ u8 ] > = NibblesIterator :: new ( key. as_ref ( ) ) . collect ( ) ;
173173
174- let Some ( last_node) = self . 0 . last ( ) else {
174+ let Some ( last_node) = self . 0 . as_ref ( ) . last ( ) else {
175175 return Err ( ProofError :: Empty ) ;
176176 } ;
177177
178178 let mut expected_hash = root_hash. clone ( ) . into_hash_type ( ) ;
179179
180- let mut iter = self . 0 . iter ( ) . peekable ( ) ;
180+ let mut iter = self . 0 . as_ref ( ) . iter ( ) . peekable ( ) ;
181181 while let Some ( node) = iter. next ( ) {
182182 if node. to_hash ( ) != expected_hash {
183183 return Err ( ProofError :: UnexpectedHash ) ;
@@ -224,6 +224,153 @@ impl<T: Hashable> Proof<T> {
224224 // This is an exclusion proof.
225225 Ok ( None )
226226 }
227+
228+ /// Returns the length of the proof.
229+ #[ must_use]
230+ pub fn len ( & self ) -> usize {
231+ self . 0 . as_ref ( ) . len ( )
232+ }
233+
234+ /// Returns true if the proof is empty.
235+ #[ must_use]
236+ pub fn is_empty ( & self ) -> bool {
237+ self . 0 . as_ref ( ) . is_empty ( )
238+ }
239+ }
240+
241+ impl < T : ProofCollection + ?Sized > std:: ops:: Deref for Proof < T > {
242+ type Target = T ;
243+
244+ #[ inline]
245+ fn deref ( & self ) -> & Self :: Target {
246+ & self . 0
247+ }
248+ }
249+
250+ impl < T : ProofCollection + ?Sized > std:: ops:: DerefMut for Proof < T > {
251+ #[ inline]
252+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
253+ & mut self . 0
254+ }
255+ }
256+
257+ impl < T : ProofCollection > Proof < T > {
258+ /// Constructs a new proof from a collection of proof nodes.
259+ #[ inline]
260+ #[ must_use]
261+ pub const fn new ( proof : T ) -> Self {
262+ Self ( proof)
263+ }
264+ }
265+
266+ impl Proof < EmptyProofCollection > {
267+ /// Constructs a new empty proof.
268+ #[ inline]
269+ #[ must_use]
270+ pub const fn empty ( ) -> Self {
271+ Self :: new ( EmptyProofCollection )
272+ }
273+
274+ /// Converts an empty immutable proof into an empty mutable proof.
275+ #[ inline]
276+ #[ must_use]
277+ pub const fn into_mutable < T : Hashable > ( self ) -> Proof < Vec < T > > {
278+ Proof :: new ( Vec :: new ( ) )
279+ }
280+ }
281+
282+ impl < T : Hashable > Proof < Box < [ T ] > > {
283+ /// Converts an immutable proof into a mutable proof.
284+ #[ inline]
285+ #[ must_use]
286+ pub fn into_mutable ( self ) -> Proof < Vec < T > > {
287+ Proof :: new ( self . 0 . into_vec ( ) )
288+ }
289+ }
290+
291+ impl < T : Hashable > Proof < Vec < T > > {
292+ /// Converts a mutable proof into an immutable proof.
293+ #[ inline]
294+ #[ must_use]
295+ pub fn into_immutable ( self ) -> Proof < Box < [ T ] > > {
296+ Proof :: new ( self . 0 . into_boxed_slice ( ) )
297+ }
298+ }
299+
300+ impl < T , V > Proof < V >
301+ where
302+ T : Hashable ,
303+ V : ProofCollection < Node = T > + IntoIterator < Item = T > + FromIterator < T > ,
304+ {
305+ /// Joins two proofs into one.
306+ #[ inline]
307+ #[ must_use]
308+ pub fn join < O : ProofCollection < Node = T > + IntoIterator < Item = T > > (
309+ self ,
310+ other : Proof < O > ,
311+ ) -> Proof < V > {
312+ self . into_iter ( ) . chain ( other) . collect ( )
313+ }
314+ }
315+
316+ impl < V : ProofCollection + FromIterator < V :: Node > > FromIterator < V :: Node > for Proof < V > {
317+ #[ inline]
318+ fn from_iter < I : IntoIterator < Item = V :: Node > > ( iter : I ) -> Self {
319+ Proof ( iter. into_iter ( ) . collect ( ) )
320+ }
321+ }
322+
323+ impl < V : ProofCollection + Extend < V :: Node > > Extend < V :: Node > for Proof < V > {
324+ #[ inline]
325+ fn extend < I : IntoIterator < Item = V :: Node > > ( & mut self , iter : I ) {
326+ self . 0 . extend ( iter) ;
327+ }
328+ }
329+
330+ impl < V : ProofCollection + IntoIterator < Item = V :: Node > > IntoIterator for Proof < V > {
331+ type Item = V :: Node ;
332+ type IntoIter = V :: IntoIter ;
333+
334+ #[ inline]
335+ fn into_iter ( self ) -> Self :: IntoIter {
336+ self . 0 . into_iter ( )
337+ }
338+ }
339+
340+ /// A trait representing a collection of proof nodes.
341+ ///
342+ /// This allows [`Proof`] to be generic over different types of collections such
343+ /// a `Box<[T]>` or `Vec<T>`, where `T` implements the `Hashable` trait.
344+ pub trait ProofCollection : AsRef < [ Self :: Node ] > {
345+ /// The type of nodes in the proof collection.
346+ type Node : Hashable ;
347+ }
348+
349+ impl < T : Hashable > ProofCollection for [ T ] {
350+ type Node = T ;
351+ }
352+
353+ impl < T : Hashable > ProofCollection for Box < [ T ] > {
354+ type Node = T ;
355+ }
356+
357+ impl < T : Hashable > ProofCollection for Vec < T > {
358+ type Node = T ;
359+ }
360+
361+ /// A zero-sized type to represent an empty proof collection.
362+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash , Default ) ]
363+ pub struct EmptyProofCollection ;
364+
365+ impl AsRef < [ ProofNode ] > for EmptyProofCollection {
366+ #[ inline]
367+ fn as_ref ( & self ) -> & [ ProofNode ] {
368+ & [ ]
369+ }
370+ }
371+
372+ impl ProofCollection for EmptyProofCollection {
373+ type Node = ProofNode ;
227374}
228375
229376/// Returns the next nibble in `c` after `b`.
0 commit comments