ocinoco 0.1.1

Build OCI image with no container
use std::io::Write;

use sha2::Digest;
use sha2::digest::array::Array;

pub(crate) struct HashedWriter<D: Digest, W: Write> {
    hasher: D,
    writer: W,
}

impl<D: Digest, W: Write> HashedWriter<D, W> {
    pub(crate) fn new(hasher: D, writer: W) -> Self {
        Self { hasher, writer }
    }

    pub(crate) fn finalize(self) -> Array<u8, D::OutputSize> {
        self.hasher.finalize()
    }
}

impl<D: Digest, W: Write> Write for HashedWriter<D, W> {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.hasher.update(buf);
        self.writer.write(buf)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.writer.flush()
    }

    fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
        self.hasher.update(buf);
        self.writer.write_all(buf)
    }
}

#[cfg(test)]
mod tests {
    use sha2::Sha256;

    use super::*;

    #[test]
    fn hashes_and_forwards_written_bytes() {
        let mut output = Vec::new();
        let digest = {
            let mut writer = HashedWriter::new(Sha256::new(), &mut output);

            writer.write_all(b"hello").unwrap();
            writer.write_all(b" world").unwrap();
            writer.flush().unwrap();
            writer.finalize()
        };

        assert_eq!(output, b"hello world");
        assert_eq!(digest.as_slice(), Sha256::digest(b"hello world").as_slice());
    }
}