77
88use std:: borrow:: Borrow ;
99use std:: collections:: VecDeque ;
10+ use std:: ops:: Deref ;
1011
1112use bincode:: Decode ;
1213use bincode:: Encode ;
@@ -35,38 +36,26 @@ pub enum HashError {
3536}
3637
3738/// Size of digest produced by the underlying hash function
38- pub const DIGEST_SIZE : usize = 32 ;
39+ const DIGEST_SIZE : usize = 32 ;
3940
4041/// A value of type [struct@Hash] indicates that the enclosed array is a digest
4142/// produced by a preset hash function, currently BLAKE2b. It can be obtained
4243/// by either hashing data directly or after hashing by converting from
4344/// a suitably sized byte slice or vector.
44- #[ derive(
45- Clone ,
46- Copy ,
47- PartialEq ,
48- Eq ,
49- Encode ,
50- Decode ,
51- Hash ,
52- PartialOrd ,
53- Ord ,
54- derive_more:: From ,
55- derive_more:: Debug ,
56- ) ]
45+ #[ derive( Clone , Copy , PartialEq , Eq , Encode , Decode , Hash , PartialOrd , Ord , derive_more:: Debug ) ]
5746#[ debug( "{}" , self ) ]
5847pub struct Hash {
5948 digest : [ u8 ; DIGEST_SIZE ] ,
6049}
6150
6251impl Hash {
63- /// Hashes a byte slice into a [`Hash`] object .
52+ /// Hashes a byte slice into a [`struct@ Hash`].
6453 pub fn hash_bytes ( bytes : & [ u8 ] ) -> Self {
6554 let digest = blake3:: hash ( bytes) . into ( ) ;
6655 Hash { digest }
6756 }
6857
69- /// Creates a [`Hash`] object from something that implements the
58+ /// Creates a [`struct@ Hash`] from something that implements the
7059 /// [`bincode::enc::Encode`] trait.
7160 pub fn hash_encodable < T : Encode > ( data : T ) -> Result < Self , EncodeError > {
7261 let mut hasher = blake3:: Hasher :: new ( ) ;
@@ -76,9 +65,9 @@ impl Hash {
7665 Ok ( Hash { digest } )
7766 }
7867
79- /// Creates a [`Hash`] object from a collection of iterables
80- /// that can be [`Borrow `]ed as a [`Hash`]. Note that this
81- /// method is rehashing the hashes!
68+ /// Creates a [`struct@ Hash`] from a collection of iterables that can be
69+ /// [`Deref `]ed as a [`struct@ Hash`]. Note that this method is rehashing the
70+ /// hashes!
8271 pub fn combine_hashes < H : Borrow < Hash > , HS : IntoIterator < Item = H > > ( hashes : HS ) -> Hash {
8372 let mut hasher = blake3:: Hasher :: new ( ) ;
8473
@@ -95,6 +84,11 @@ impl Hash {
9584 pub fn from_foldable ( foldable : & impl Foldable < HashFold > ) -> Self {
9685 foldable. fold ( HashFold )
9786 }
87+
88+ /// The length of the hash digest
89+ pub const fn digest_len ( ) -> usize {
90+ DIGEST_SIZE
91+ }
9892}
9993
10094impl std:: fmt:: Display for Hash {
@@ -103,6 +97,12 @@ impl std::fmt::Display for Hash {
10397 }
10498}
10599
100+ impl From < [ u8 ; DIGEST_SIZE ] > for Hash {
101+ fn from ( value : [ u8 ; DIGEST_SIZE ] ) -> Self {
102+ Self { digest : value }
103+ }
104+ }
105+
106106impl From < Hash > for [ u8 ; DIGEST_SIZE ] {
107107 fn from ( value : Hash ) -> Self {
108108 value. digest
@@ -121,34 +121,42 @@ impl Foldable<HashFold> for Hash {
121121 }
122122}
123123
124+ impl Deref for Hash {
125+ type Target = [ u8 ; DIGEST_SIZE ] ;
126+
127+ fn deref ( & self ) -> & Self :: Target {
128+ & self . digest
129+ }
130+ }
131+
132+ /// [struct@Hasher] can be dynamically updated with byte arrays and [`struct@Hash`]s and
133+ /// can be turned into a [`struct@Hash`].
134+ #[ derive( Default ) ]
124135pub struct Hasher {
125136 hasher : blake3:: Hasher ,
126137}
127138
128139impl Hasher {
129- /// Creates a new [`Hasher`] object
130- pub fn new ( ) -> Self {
131- Self {
132- hasher : blake3:: Hasher :: new ( ) ,
133- }
134- }
135-
136140 /// Updates the [`Hasher`] with some bytes
137141 pub fn update_with_bytes ( & mut self , bytes : & [ u8 ] ) {
138142 self . hasher . update ( bytes) ;
139143 }
140144
141- /// Updates the [`Hasher`] with the digest of a [`Hash`]
142- pub fn update_with_hash ( & mut self , hash : Hash ) {
143- let digest: [ u8 ; DIGEST_SIZE ] = hash. into ( ) ;
144- self . hasher . update ( digest. as_slice ( ) ) ;
145+ /// Updates the [`Hasher`] with the digest of a [`struct@Hash`]
146+ pub fn update_with_hash ( & mut self , hash : & Hash ) {
147+ self . hasher . update ( hash. deref ( ) ) ;
145148 }
146149
147- /// Turns the [`Hasher`] into a [`Hash`]
150+ /// Turns the [`Hasher`] into a [`struct@ Hash`]
148151 pub fn to_hash ( self ) -> Hash {
149152 let digest: [ u8 ; DIGEST_SIZE ] = self . hasher . finalize ( ) . into ( ) ;
150153 Hash { digest }
151154 }
155+
156+ /// Returns the number of bytes hashed so far.
157+ pub fn count ( & self ) -> u64 {
158+ self . hasher . count ( )
159+ }
152160}
153161
154162/// [`Fold`] implementation producing a [`struct@Hash`]
@@ -171,20 +179,19 @@ impl Fold for HashFold {
171179#[ derive( Default ) ]
172180pub struct HashNodeFold {
173181 /// Hasher used to combine children's hashes
174- hasher : blake3 :: Hasher ,
182+ hasher : Hasher ,
175183}
176184
177185impl NodeFold for HashNodeFold {
178186 type Parent = HashFold ;
179187
180188 fn add < F : Foldable < HashFold > > ( & mut self , child : & F ) {
181189 let folded_child = child. fold ( HashFold ) ;
182- self . hasher . update ( folded_child. as_ref ( ) ) ;
190+ self . hasher . update_with_bytes ( folded_child. as_ref ( ) ) ;
183191 }
184192
185193 fn done ( self ) -> Hash {
186- let digest = self . hasher . finalize ( ) . into ( ) ;
187- Hash { digest }
194+ self . hasher . to_hash ( )
188195 }
189196}
190197
@@ -343,7 +350,7 @@ impl<'tree> NodeFold for PartialHashNodeFold<'tree> {
343350
344351 fn done ( self ) -> PartialHash {
345352 let mut saw_absent_child = false ;
346- let mut hasher = blake3 :: Hasher :: new ( ) ;
353+ let mut hasher = Hasher :: default ( ) ;
347354
348355 for child_hash in self . child_hashes {
349356 match child_hash {
@@ -365,7 +372,7 @@ impl<'tree> NodeFold for PartialHashNodeFold<'tree> {
365372 return PartialHash :: InvalidProof ;
366373 }
367374
368- hasher. update ( hash. as_ref ( ) ) ;
375+ hasher. update_with_hash ( & hash) ;
369376 }
370377
371378 PartialHash :: InvalidProof => {
@@ -383,20 +390,19 @@ impl<'tree> NodeFold for PartialHashNodeFold<'tree> {
383390 . unwrap_or ( PartialHash :: Previous ) ;
384391 }
385392
386- let digest: [ u8 ; 32 ] = hasher. finalize ( ) . into ( ) ;
387- let hash = Hash :: from ( digest) ;
388- PartialHash :: Present ( hash)
393+ PartialHash :: Present ( hasher. to_hash ( ) )
389394 }
390395}
391396
392397#[ cfg( test) ]
393398mod tests {
394- use super :: DIGEST_SIZE ;
399+ use std:: borrow:: Borrow ;
400+
401+ use bincode:: Encode ;
402+
395403 use super :: Hash ;
396404 use super :: Hasher ;
397405 use crate :: serialisation:: bincode_default_config;
398- use bincode:: Encode ;
399- use std:: borrow:: Borrow ;
400406
401407 #[ derive( Clone , Encode ) ]
402408 struct Encodable {
@@ -430,20 +436,20 @@ mod tests {
430436 fn hash_bytes_works_as_blake3_hashing ( ) {
431437 let bytes = [ 1 , 2 , 3 ] ;
432438 let hash = Hash :: hash_bytes ( & bytes) ;
433- let hash_digest: [ u8 ; DIGEST_SIZE ] = hash. into ( ) ;
434- let blake3_digest: [ u8 ; DIGEST_SIZE ] = blake3:: hash ( & bytes) . into ( ) ;
439+ let hash_digest: [ u8 ; Hash :: digest_len ( ) ] = hash. into ( ) ;
440+ let blake3_digest: [ u8 ; 32 ] = blake3:: hash ( & bytes) . into ( ) ;
435441 assert_eq ! ( hash_digest, blake3_digest) ;
436442 }
437443
438444 #[ test]
439- fn hash_encodable_can_hash_encodable_objects ( ) {
440- let object = Encodable :: new ( 12 ) ;
441- let bytes =
442- bincode :: encode_to_vec ( object . clone ( ) , bincode_default_config ( ) ) . expect ( "Should work" ) ;
443- let object_hash_digest : [ u8 ; DIGEST_SIZE ] = blake3:: hash ( bytes. as_slice ( ) ) . into ( ) ;
444- let hash_digest: [ u8 ; DIGEST_SIZE ] =
445- Hash :: hash_encodable ( object ) . expect ( "Should work" ) . into ( ) ;
446- assert_eq ! ( object_hash_digest , hash_digest) ;
445+ fn hash_encodable_can_hash_encodables ( ) {
446+ let encodable = Encodable :: new ( 12 ) ;
447+ let bytes = bincode :: encode_to_vec ( encodable . clone ( ) , bincode_default_config ( ) )
448+ . expect ( "Should work" ) ;
449+ let encodable_hash_digest : blake3 :: Hash = blake3:: hash ( bytes. as_slice ( ) ) ;
450+ let hash_digest: [ u8 ; Hash :: digest_len ( ) ] =
451+ Hash :: hash_encodable ( encodable ) . expect ( "Should work" ) . into ( ) ;
452+ assert_eq ! ( encodable_hash_digest , hash_digest) ;
447453 }
448454
449455 #[ test]
@@ -453,14 +459,14 @@ mod tests {
453459 Borrowable :: new( Hash :: hash_bytes( & [ 4 , 5 , 6 ] ) ) ,
454460 ] ;
455461 let hash = Hash :: combine_hashes ( coll. clone ( ) ) ;
456- let hash_digest: [ u8 ; DIGEST_SIZE ] = hash. into ( ) ;
462+ let hash_digest: [ u8 ; Hash :: digest_len ( ) ] = hash. into ( ) ;
457463
458464 let mut hasher = blake3:: Hasher :: new ( ) ;
459465 let mut borrowed_hash: & Hash = coll[ 0 ] . borrow ( ) ;
460466 hasher. update ( borrowed_hash. as_ref ( ) ) ;
461467 borrowed_hash = coll[ 1 ] . borrow ( ) ;
462468 hasher. update ( borrowed_hash. as_ref ( ) ) ;
463- let hasher_digest: [ u8 ; DIGEST_SIZE ] = hasher. finalize ( ) . into ( ) ;
469+ let hasher_digest: [ u8 ; Hash :: digest_len ( ) ] = hasher. finalize ( ) . into ( ) ;
464470
465471 assert_eq ! ( hash_digest, hasher_digest) ;
466472
@@ -472,7 +478,7 @@ mod tests {
472478 #[ test]
473479 fn hasher_update_with_bytes_is_the_same_as_hash_bytes ( ) {
474480 let elems: Vec < Vec < u8 > > = vec ! [ vec![ 1 , 2 , 3 ] , vec![ 4 , 5 , 6 ] ] ;
475- let mut hasher: Hasher = Hasher :: new ( ) ;
481+ let mut hasher: Hasher = Hasher :: default ( ) ;
476482
477483 for elem in elems. iter ( ) {
478484 hasher. update_with_bytes ( elem. as_slice ( ) ) ;
@@ -490,10 +496,10 @@ mod tests {
490496
491497 let hash = Hash :: combine_hashes ( elems. clone ( ) ) ;
492498
493- let mut hasher = Hasher :: new ( ) ;
499+ let mut hasher = Hasher :: default ( ) ;
494500
495501 for elem in elems. into_iter ( ) {
496- hasher. update_with_hash ( elem) ;
502+ hasher. update_with_hash ( & elem) ;
497503 }
498504
499505 assert_eq ! ( hash, hasher. to_hash( ) ) ;
0 commit comments