From 791501eabc4ba000d194301e816aa27f8cc6be5d Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 20 Feb 2025 13:29:05 +1100 Subject: [PATCH] io: Use function in place of GeneralHashExt We would like to remove the `GeneralHash` trait but we want to keep the `hash_reader` functionality. Add a stand alone function (when `hashes` is enabled) `hash_reader`. Remove the extension trait. --- io/src/hash.rs | 51 +++++++++++++++++++------------------------------- io/src/lib.rs | 2 +- 2 files changed, 20 insertions(+), 33 deletions(-) diff --git a/io/src/hash.rs b/io/src/hash.rs index 6a311b8fd..859f035b7 100644 --- a/io/src/hash.rs +++ b/io/src/hash.rs @@ -10,9 +10,11 @@ use hashes::hmac::HmacEngine; use hashes::{ hash160, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512, sha512_256, siphash24, - GeneralHash, HashEngine as _, + HashEngine as _, }; +use crate::BufRead; + macro_rules! impl_write { ($ty: ty, $write_fn: expr, $flush_fn: expr $(, $bounded_ty: ident : $bounds: path),*) => { // `std::io::Write` is implemented in `bitcoin_hashes` because of the orphan rule. @@ -132,39 +134,24 @@ impl_write!( ); /// Hashes data from a reader. -/// -/// Adds functionality to a [`hashes::GeneralHash`] type to support hashing data read from a -/// buffered reader. -pub trait GeneralHashExt: GeneralHash + sealed::Sealed { - /// Hashes the entire contents of the `reader`. - fn hash_reader(reader: &mut R) -> Result - where - Self::Engine: Default, - { - let mut engine = Self::engine(); // This calls `Self::Engine::default()`. - loop { - let bytes = reader.fill_buf()?; +pub fn hash_reader(reader: &mut impl BufRead) -> Result +where + T: hashes::HashEngine + Default, +{ + let mut engine = T::default(); + loop { + let bytes = reader.fill_buf()?; - let read = bytes.len(); - // Empty slice means EOF. - if read == 0 { - break; - } - - engine.input(bytes); - reader.consume(read); + let read = bytes.len(); + // Empty slice means EOF. + if read == 0 { + break; } - Ok(Self::from_engine(engine)) + + engine.input(bytes); + reader.consume(read); } -} - -impl GeneralHashExt for T {} - -mod sealed { - /// Used to seal the `GeneralHashExt` trait. - pub trait Sealed {} - - impl Sealed for T {} + Ok(engine.finalize()) } #[cfg(test)] @@ -308,7 +295,7 @@ mod tests { assert_eq!(got, $want); let mut reader = Cursor::new(DATA); - let hash_from_reader = $module::Hash::hash_reader(&mut reader).unwrap(); + let hash_from_reader = $crate::hash_reader::<$module::HashEngine>(&mut reader).unwrap(); assert_eq!(hash_from_reader, hash) } )* diff --git a/io/src/lib.rs b/io/src/lib.rs index 0b7ee5093..8da2d108d 100644 --- a/io/src/lib.rs +++ b/io/src/lib.rs @@ -46,7 +46,7 @@ pub use bridge::{FromStd, ToStd}; #[rustfmt::skip] // Keep public re-exports separate. pub use self::error::{Error, ErrorKind}; #[cfg(feature = "hashes")] -pub use self::hash::GeneralHashExt; +pub use self::hash::hash_reader; /// Result type returned by functions in this crate. pub type Result = core::result::Result;