Skip to content

Commit 2d7cd35

Browse files
committed
feat: implement std::io::Write trait for the hashers
Instead of having a (non-working) wrapper struct for implementing std::io::Write for a hasher, implement it directly on the hasher. Closes #95.
1 parent 32d5b00 commit 2d7cd35

File tree

4 files changed

+47
-19
lines changed

4 files changed

+47
-19
lines changed

src/hasher.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,19 +134,3 @@ impl<T: StatefulHasher> Hasher for T {
134134
hasher.finalize()
135135
}
136136
}
137-
138-
/// New type wrapper for a hasher that implements the `std::io::Write` trait.
139-
#[cfg(feature = "std")]
140-
pub struct WriteHasher<H: Hasher>(H);
141-
142-
#[cfg(feature = "std")]
143-
impl<H: StatefulHasher> std::io::Write for WriteHasher<H> {
144-
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
145-
self.0.update(buf);
146-
Ok(buf.len())
147-
}
148-
149-
fn flush(&mut self) -> std::io::Result<()> {
150-
Ok(())
151-
}
152-
}

src/hasher_impl.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ macro_rules! derive_digest {
5050
};
5151
}
5252

53+
macro_rules! derive_write {
54+
($name:ident) => {
55+
#[cfg(feature = "std")]
56+
impl<S: Size> std::io::Write for $name<S> {
57+
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
58+
self.update(buf);
59+
Ok(buf.len())
60+
}
61+
62+
fn flush(&mut self) -> std::io::Result<()> {
63+
Ok(())
64+
}
65+
}
66+
};
67+
}
68+
5369
#[cfg(any(feature = "blake2b", feature = "blake2s"))]
5470
macro_rules! derive_hasher_blake {
5571
($module:ident, $name:ident, $digest:ident) => {
@@ -91,6 +107,8 @@ macro_rules! derive_hasher_blake {
91107
self.state = state;
92108
}
93109
}
110+
111+
derive_write!($name);
94112
};
95113
}
96114

@@ -169,6 +187,8 @@ pub mod blake3 {
169187
}
170188
}
171189

190+
derive_write!(Blake3Hasher);
191+
172192
/// blake3-256 hasher.
173193
pub type Blake3_256 = Blake3Hasher<U32>;
174194
}
@@ -201,6 +221,18 @@ macro_rules! derive_hasher_sha {
201221
self.state.reset();
202222
}
203223
}
224+
225+
#[cfg(feature = "std")]
226+
impl std::io::Write for $name {
227+
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
228+
self.update(buf);
229+
Ok(buf.len())
230+
}
231+
232+
fn flush(&mut self) -> std::io::Result<()> {
233+
Ok(())
234+
}
235+
}
204236
};
205237
}
206238

@@ -342,6 +374,8 @@ pub mod identity {
342374
}
343375
}
344376

377+
derive_write!(IdentityHasher);
378+
345379
/// 32 byte Identity hasher (constrained to 32 bytes).
346380
///
347381
/// # Panics
@@ -403,6 +437,8 @@ pub mod strobe {
403437
}
404438
}
405439

440+
derive_write!(StrobeHasher);
441+
406442
/// 256 bit strobe hasher.
407443
pub type Strobe256 = StrobeHasher<U32>;
408444

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ mod multihash;
6262
mod multihash_impl;
6363

6464
pub use crate::error::{Error, Result};
65-
#[cfg(feature = "std")]
66-
pub use crate::hasher::WriteHasher;
6765
pub use crate::hasher::{Digest, Hasher, Size, StatefulHasher};
6866
pub use crate::multihash::{Multihash as MultihashGeneric, MultihashDigest};
6967
pub use generic_array::typenum::{self, U128, U16, U20, U28, U32, U48, U64};

tests/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::io::Cursor;
1+
use std::io::{Cursor, Write};
22

33
use multihash::{
44
derive::Multihash, Blake2b256, Blake2b512, Blake2bDigest, Blake2s128, Blake2s256,
@@ -167,6 +167,16 @@ macro_rules! assert_roundtrip {
167167
hash.code()
168168
);
169169
}
170+
// Hashing as `Write` implementation
171+
{
172+
let mut hasher = <$alg>::default();
173+
hasher.write_all(b"helloworld").unwrap();
174+
let hash = Code::multihash_from_digest(&hasher.finalize());
175+
assert_eq!(
176+
Multihash::from_bytes(&hash.to_bytes()).unwrap().code(),
177+
hash.code()
178+
);
179+
}
170180
)*
171181
}
172182
}

0 commit comments

Comments
 (0)