otter_support/
digestrw.rs1use crate::prelude::*;
6
7#[derive(Debug,Copy,Clone)]
8pub struct DigestRead<D: Digest, R: Read> {
9 d: D,
10 r: R,
11}
12
13impl<D: Digest, R: Read> DigestRead<D, R> {
14 pub fn new(r: R) -> Self { DigestRead { r, d: D::new() } }
15 pub fn into_inner(self) -> (D, R) { (self.d, self.r) }
16 pub fn finish(self) -> digest::Output<D> {
17 self.d.finalize()
18 }
19}
20
21impl<D: Digest, R: Read> Read for DigestRead<D, R> {
22 #[throws(io::Error)]
23 fn read(&mut self, buf: &mut [u8]) -> usize {
24 let count = self.r.read(buf)?;
25 self.d.update(&buf[0..count]);
26 count
27 }
28}
29
30#[test]
31#[cfg(not(miri))]
32fn test_digest_read() {
33 let ibuffer = b"abc";
34 let exp = Sha512_256::digest(&ibuffer[..]);
35 let inner = &ibuffer[..];
36 let mut dr = DigestRead::<Sha512_256,_>::new(inner);
37 let mut obuffer = [0;4];
38 assert_eq!( dr.read(&mut obuffer).unwrap(), 3 );
39 assert_eq!( &obuffer, b"abc\0" );
40 let got = dr.finish();
41 assert_eq!( got, exp );
42}
43
44#[derive(Debug,Copy,Clone)]
45pub struct DigestWrite<D: Digest, W: Write> {
46 d: D,
47 w: W,
48}
49
50impl<D: Digest, W: Write> DigestWrite<D, W> {
51 pub fn new(w: W) -> Self { DigestWrite { w, d: D::new() } }
52 pub fn into_inner(self) -> (D, W) { (self.d, self.w) }
53 pub fn finish(self) -> (digest::Output<D>, W) {
54 (self.d.finalize(), self.w)
55 }
56}
57impl<D: Digest> DigestWrite<D, io::Sink> {
58 pub fn sink() -> Self { DigestWrite::new(io::sink()) }
59
60 #[throws(io::Error)]
61 pub fn of<R>(r: &mut R) -> digest::Output<D> where R: Read {
62 let mut dw = DigestWrite::<D,_>::sink();
63 io::copy(r, &mut dw)?;
64 dw.finish().0
65 }
66}
67
68impl<D: Digest, W: Write> Write for DigestWrite<D, W> {
69 #[throws(io::Error)]
70 fn write(&mut self, buf: &[u8]) -> usize {
71 let count = self.w.write(buf)?;
72 self.d.update(&buf[0..count]);
73 count
74 }
75 #[throws(io::Error)]
76 fn flush(&mut self) { self.w.flush()? }
77}