libvctrl_core 3.2.0

Reference implementations of the libvctrl contracts (in-memory store, SHA-512 hasher, binary codec)
Documentation
use alloc::sync::Arc;
use std::io;

use libvctrl_handler::{Hash, Hasher, VctrlError};
use libvctrl_sha512::Hash as Sha512Hash;

#[derive(Debug, Default, Clone, Copy)]
pub struct Sha512Hasher;

impl Hasher for Sha512Hasher {
    fn hash<R: io::Read + Send>(&self, mut reader: R) -> Result<Hash, VctrlError> {
        let mut hasher = Sha512Hash::new();
        let mut buffer = [0u8; 4096];
        loop {
            let n = reader.read(&mut buffer).map_err(VctrlError::from_io)?;
            if n == 0 {
                break;
            }
            let chunk = buffer.get(..n).ok_or_else(|| {
                VctrlError::IoError(Arc::new(io::Error::new(
                    io::ErrorKind::UnexpectedEof,
                    "read returned invalid length",
                )))
            })?;
            hasher.update(chunk);
        }
        let digest = hasher.finalize();
        Hash::from_bytes(&digest)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Cursor;

    #[test]
    fn hash_empty_input() -> Result<(), VctrlError> {
        let hash = Sha512Hasher.hash(Cursor::new(Vec::<u8>::new()))?;
        assert_eq!(
            hash.as_bytes(),
            &[
                0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d,
                0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21,
                0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83,
                0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
                0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
            ]
        );
        Ok(())
    }

    #[test]
    fn hash_abc() -> Result<(), VctrlError> {
        let hash = Sha512Hasher.hash(Cursor::new(b"abc"))?;
        assert_eq!(
            hash.as_bytes(),
            &[
                0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20,
                0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6,
                0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba,
                0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd, 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
                0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
            ]
        );
        Ok(())
    }

    #[test]
    fn hash_multiple_chunks() -> Result<(), VctrlError> {
        let data = vec![0xAB; 8192];
        let hash = Sha512Hasher.hash(Cursor::new(data))?;
        assert_eq!(hash.as_bytes().len(), 64);
        Ok(())
    }
}