[IO] Provide a macro which implements `io::Write` for types
With the new `bitcoin_io` library, implementing `io::Write` manually is somewhat tricky - for `std` users we really want to provide an `std::io::Write` implementation, however for `no-std` users we want to implement against our internal trait. Sadly we cannot provide a blanket implementation of `std::io::Write` for all types whcih implement our `io::Write` trait as its an out-of-crate impl. Instead, we provide a macro which will either implement `std::io::Write` or our `io::Write` depending on the feature flags set on `bitcoin_io`.
This commit is contained in:
parent
ac678bb435
commit
7eb5d65bda
|
@ -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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
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<usize> {
|
||||
self.input(buf);
|
||||
impl_write!(
|
||||
siphash24::HashEngine,
|
||||
|us: &mut siphash24::HashEngine, buf| {
|
||||
us.input(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
}
|
||||
},
|
||||
|_us| { Ok(()) }
|
||||
);
|
||||
|
||||
impl<T: crate::Hash> io::Write for hmac::HmacEngine<T> {
|
||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.input(buf);
|
||||
impl_write!(
|
||||
hmac::HmacEngine<T>,
|
||||
|us: &mut hmac::HmacEngine<T>, 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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<usize> {
|
||||
$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<usize> {
|
||||
$write_fn(self, buf)
|
||||
}
|
||||
#[inline]
|
||||
fn flush(&mut self) -> $crate::_std::io::Result<()> {
|
||||
$flush_fn(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue