Skip to main content

otter_support/
digestrw.rs

1// Copyright 2020-2021 Ian Jackson and contributors to Otter
2// SPDX-License-Identifier: AGPL-3.0-or-later
3// There is NO WARRANTY.
4
5use 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}