[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`.
|
//! 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 {
|
use crate::{hmac, ripemd160, sha1, sha256, sha512, siphash24, HashEngine};
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
|
||||||
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
impl_write!(
|
||||||
self.input(buf);
|
sha1::HashEngine,
|
||||||
|
|us: &mut sha1::HashEngine, buf| {
|
||||||
|
us.input(buf);
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
},
|
||||||
}
|
|_us| { Ok(()) }
|
||||||
|
);
|
||||||
|
|
||||||
impl io::Write for sha256::HashEngine {
|
impl_write!(
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
sha256::HashEngine,
|
||||||
|
|us: &mut sha256::HashEngine, buf| {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
us.input(buf);
|
||||||
self.input(buf);
|
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
},
|
||||||
}
|
|_us| { Ok(()) }
|
||||||
|
);
|
||||||
|
|
||||||
impl io::Write for sha512::HashEngine {
|
impl_write!(
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
sha512::HashEngine,
|
||||||
|
|us: &mut sha512::HashEngine, buf| {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
us.input(buf);
|
||||||
self.input(buf);
|
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
},
|
||||||
}
|
|_us| { Ok(()) }
|
||||||
|
);
|
||||||
|
|
||||||
impl io::Write for ripemd160::HashEngine {
|
impl_write!(
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
ripemd160::HashEngine,
|
||||||
|
|us: &mut ripemd160::HashEngine, buf| {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
us.input(buf);
|
||||||
self.input(buf);
|
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
},
|
||||||
}
|
|_us| { Ok(()) }
|
||||||
|
);
|
||||||
|
|
||||||
impl io::Write for siphash24::HashEngine {
|
impl_write!(
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
siphash24::HashEngine,
|
||||||
|
|us: &mut siphash24::HashEngine, buf| {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
us.input(buf);
|
||||||
self.input(buf);
|
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
},
|
||||||
}
|
|_us| { Ok(()) }
|
||||||
|
);
|
||||||
|
|
||||||
impl<T: crate::Hash> io::Write for hmac::HmacEngine<T> {
|
impl_write!(
|
||||||
fn flush(&mut self) -> io::Result<()> { Ok(()) }
|
hmac::HmacEngine<T>,
|
||||||
|
|us: &mut hmac::HmacEngine<T>, buf| {
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
us.input(buf);
|
||||||
self.input(buf);
|
|
||||||
Ok(buf.len())
|
Ok(buf.len())
|
||||||
}
|
},
|
||||||
}
|
|_us| { Ok(()) },
|
||||||
|
T: crate::Hash
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::io::Write;
|
use bitcoin_io::io::Write;
|
||||||
|
|
||||||
use crate::{hash160, hmac, ripemd160, sha1, sha256, sha256d, sha512, siphash24, Hash};
|
use crate::{hash160, hmac, ripemd160, sha1, sha256, sha256d, sha512, siphash24, Hash};
|
||||||
|
|
||||||
macro_rules! write_test {
|
macro_rules! write_test {
|
||||||
|
|
|
@ -130,9 +130,6 @@ pub mod siphash24;
|
||||||
|
|
||||||
use core::{borrow, fmt, hash, ops};
|
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};
|
pub use hmac::{Hmac, HmacEngine};
|
||||||
|
|
||||||
/// A hashing engine which bytes can be serialized into.
|
/// A hashing engine which bytes can be serialized into.
|
||||||
|
|
|
@ -96,3 +96,57 @@ pub mod io {
|
||||||
fn flush(&mut self) -> Result<()> { Ok(()) }
|
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