// Copyright 2020-2021 Ian Jackson and contributors to Otter // SPDX-License-Identifier: AGPL-3.0-or-later // There is NO WARRANTY. use crate::prelude::*; #[derive(Debug,Copy,Clone)] pub struct DigestRead { d: D, r: R, } impl DigestRead { pub fn new(r: R) -> Self { DigestRead { r, d: D::new() } } pub fn into_inner(self) -> (D, R) { (self.d, self.r) } pub fn finish(self) -> digest::Output { self.d.finalize() } } impl Read for DigestRead { #[throws(io::Error)] fn read(&mut self, buf: &mut [u8]) -> usize { let count = self.r.read(buf)?; self.d.update(&buf[0..count]); count } } #[test] #[cfg(not(miri))] fn test_digest_read() { let ibuffer = b"abc"; let exp = Sha512_256::digest(&ibuffer[..]); let inner = &ibuffer[..]; let mut dr = DigestRead::::new(inner); let mut obuffer = [0;4]; assert_eq!( dr.read(&mut obuffer).unwrap(), 3 ); assert_eq!( &obuffer, b"abc\0" ); let got = dr.finish(); assert_eq!( got, exp ); } #[derive(Debug,Copy,Clone)] pub struct DigestWrite { d: D, w: W, } impl DigestWrite { pub fn new(w: W) -> Self { DigestWrite { w, d: D::new() } } pub fn into_inner(self) -> (D, W) { (self.d, self.w) } pub fn finish(self) -> (digest::Output, W) { (self.d.finalize(), self.w) } } impl DigestWrite { pub fn sink() -> Self { DigestWrite::new(io::sink()) } #[throws(io::Error)] pub fn of(r: &mut R) -> digest::Output where R: Read { let mut dw = DigestWrite::::sink(); io::copy(r, &mut dw)?; dw.finish().0 } } impl Write for DigestWrite { #[throws(io::Error)] fn write(&mut self, buf: &[u8]) -> usize { let count = self.w.write(buf)?; self.d.update(&buf[0..count]); count } #[throws(io::Error)] fn flush(&mut self) { self.w.flush()? } }