diff --git a/hashes/src/impls.rs b/hashes/src/impls.rs index 088a7f1f..57c9a723 100644 --- a/hashes/src/impls.rs +++ b/hashes/src/impls.rs @@ -5,65 +5,69 @@ //! Implementations of traits defined in `std` / `core2` and not in `core`. //! -use crate::{hmac, io, ripemd160, sha1, sha256, sha512, siphash24, HashEngine}; +use bitcoin_io::impl_write; -impl io::Write for sha1::HashEngine { - fn flush(&mut self) -> io::Result<()> { Ok(()) } +use crate::{hmac, ripemd160, sha1, sha256, sha512, siphash24, HashEngine}; - fn write(&mut self, buf: &[u8]) -> io::Result { - self.input(buf); +impl_write!( + sha1::HashEngine, + |us: &mut sha1::HashEngine, buf| { + us.input(buf); Ok(buf.len()) - } -} + }, + |_us| { Ok(()) } +); -impl io::Write for sha256::HashEngine { - fn flush(&mut self) -> io::Result<()> { Ok(()) } - - fn write(&mut self, buf: &[u8]) -> io::Result { - self.input(buf); +impl_write!( + sha256::HashEngine, + |us: &mut sha256::HashEngine, buf| { + us.input(buf); Ok(buf.len()) - } -} + }, + |_us| { Ok(()) } +); -impl io::Write for sha512::HashEngine { - fn flush(&mut self) -> io::Result<()> { Ok(()) } - - fn write(&mut self, buf: &[u8]) -> io::Result { - self.input(buf); +impl_write!( + sha512::HashEngine, + |us: &mut sha512::HashEngine, buf| { + us.input(buf); Ok(buf.len()) - } -} + }, + |_us| { Ok(()) } +); -impl io::Write for ripemd160::HashEngine { - fn flush(&mut self) -> io::Result<()> { Ok(()) } - - fn write(&mut self, buf: &[u8]) -> io::Result { - self.input(buf); +impl_write!( + ripemd160::HashEngine, + |us: &mut ripemd160::HashEngine, buf| { + us.input(buf); Ok(buf.len()) - } -} + }, + |_us| { Ok(()) } +); -impl io::Write for siphash24::HashEngine { - fn flush(&mut self) -> io::Result<()> { Ok(()) } - - fn write(&mut self, buf: &[u8]) -> io::Result { - self.input(buf); +impl_write!( + siphash24::HashEngine, + |us: &mut siphash24::HashEngine, buf| { + us.input(buf); Ok(buf.len()) - } -} + }, + |_us| { Ok(()) } +); -impl io::Write for hmac::HmacEngine { - fn flush(&mut self) -> io::Result<()> { Ok(()) } - - fn write(&mut self, buf: &[u8]) -> io::Result { - self.input(buf); +impl_write!( + hmac::HmacEngine, + |us: &mut hmac::HmacEngine, buf| { + us.input(buf); Ok(buf.len()) - } -} + }, + |_us| { Ok(()) }, + T: crate::Hash +); #[cfg(test)] mod tests { - use super::io::Write; + use bitcoin_io::io::Write; + use crate::{hash160, hmac, ripemd160, sha1, sha256, sha256d, sha512, siphash24, Hash}; macro_rules! write_test { diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs index 91740f4e..10c47d75 100644 --- a/hashes/src/lib.rs +++ b/hashes/src/lib.rs @@ -130,9 +130,6 @@ pub mod siphash24; use core::{borrow, fmt, hash, ops}; -// You get I/O if you enable "std" or "core2" (as well as during testing). -#[cfg(feature = "bitcoin-io")] -use bitcoin_io::io; pub use hmac::{Hmac, HmacEngine}; /// A hashing engine which bytes can be serialized into. diff --git a/io/src/lib.rs b/io/src/lib.rs index 85b2afe9..93d09795 100644 --- a/io/src/lib.rs +++ b/io/src/lib.rs @@ -96,3 +96,57 @@ pub mod io { fn flush(&mut self) -> Result<()> { Ok(()) } } } + +#[doc(hidden)] +#[cfg(feature = "std")] +/// Re-export std for the below macro +pub use std as _std; + +#[macro_export] +/// Because we cannot provide a blanket implementation of [`std::io::Write`] for all implementers +/// of this crate's `io::Write` trait, we provide this macro instead. +/// +/// This macro will implement `Write` given a `write` and `flush` fn, either by implementing the +/// crate's native `io::Write` trait directly, or a more generic trait from `std` for users using +/// that feature. In any case, this crate's `io::Write` feature will be implemented for the given +/// type, even if indirectly. +#[cfg(not(feature = "std"))] +macro_rules! impl_write { + ($ty: ty, $write_fn: expr, $flush_fn: expr $(, $bounded_ty: ident : $bounds: path),*) => { + impl<$($bounded_ty: $bounds),*> $crate::io::Write for $ty { + #[inline] + fn write(&mut self, buf: &[u8]) -> $crate::io::Result { + $write_fn(self, buf) + } + #[inline] + fn flush(&mut self) -> $crate::io::Result<()> { + $flush_fn(self) + } + } + } +} + + +#[macro_export] +/// Because we cannot provide a blanket implementation of [`std::io::Write`] for all implementers +/// of this crate's `io::Write` trait, we provide this macro instead. +/// +/// This macro will implement `Write` given a `write` and `flush` fn, either by implementing the +/// crate's native `io::Write` trait directly, or a more generic trait from `std` for users using +/// that feature. In any case, this crate's `io::Write` feature will be implemented for the given +/// type, even if indirectly. +#[cfg(feature = "std")] +macro_rules! impl_write { + ($ty: ty, $write_fn: expr, $flush_fn: expr $(, $bounded_ty: ident : $bounds: path),*) => { + impl<$($bounded_ty: $bounds),*> $crate::_std::io::Write for $ty { + #[inline] + fn write(&mut self, buf: &[u8]) -> $crate::_std::io::Result { + $write_fn(self, buf) + } + #[inline] + fn flush(&mut self) -> $crate::_std::io::Result<()> { + $flush_fn(self) + } + } + } +}