chiark / gitweb /
changelog: document further make-release changes
[otter.git] / 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
5 use crate::prelude::*;
6
7 #[derive(Debug,Copy,Clone)]
8 pub struct DigestRead<D: Digest, R: Read> {
9   d: D,
10   r: R,
11 }
12
13 impl<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
21 impl<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))]
32 fn 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)]
45 pub struct DigestWrite<D: Digest, W: Write> {
46   d: D,
47   w: W,
48 }
49
50 impl<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 }
57 impl<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
68 impl<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 }