libvctrl_core 3.2.0

Reference implementations of the libvctrl contracts (in-memory store, SHA-512 hasher, binary codec)
Documentation
use libvctrl_handler::{Hash, ObjectStore, VctrlError};
use std::collections::HashMap;
use std::io::{Cursor, Read};

#[derive(Debug, Default)]
pub struct MemoryStore {
    objects: HashMap<Hash, Vec<u8>>,
}

impl MemoryStore {
    #[must_use]
    pub fn new() -> Self {
        Self {
            objects: HashMap::new(),
        }
    }
}

impl ObjectStore for MemoryStore {
    fn put(&mut self, hash: &Hash, data: &[u8]) -> Result<(), VctrlError> {
        let _ = self.objects.insert(*hash, data.to_vec());
        Ok(())
    }

    fn get(&self, hash: &Hash) -> Result<Box<dyn Read + Send + '_>, VctrlError> {
        let data = self
            .objects
            .get(hash)
            .ok_or(VctrlError::ObjectNotFound(*hash))?;
        Ok(Box::new(Cursor::new(data.as_slice())))
    }

    fn delete(&mut self, hash: &Hash) -> Result<(), VctrlError> {
        let _ = self.objects.remove(hash);
        Ok(())
    }

    fn exists(&self, hash: &Hash) -> Result<bool, VctrlError> {
        Ok(self.objects.contains_key(hash))
    }
}

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

    fn hash_byte(byte: u8) -> Result<Hash, VctrlError> {
        Hash::from_bytes(&[byte; 64])
    }

    #[test]
    fn put_and_get_roundtrip() -> Result<(), VctrlError> {
        let mut store = MemoryStore::new();
        let hash = hash_byte(0xAB)?;
        let data = vec![10_u8, 20, 30];

        store.put(&hash, &data)?;
        {
            let mut reader = store.get(&hash)?;
            let mut buf = Vec::new();
            let _ = reader.read_to_end(&mut buf)?;
            assert_eq!(buf, data);
        }
        Ok(())
    }

    #[test]
    fn get_missing_object_errors() -> Result<(), VctrlError> {
        let store = MemoryStore::new();
        let hash = hash_byte(0xCD)?;
        let result = store.get(&hash);
        assert!(matches!(result, Err(VctrlError::ObjectNotFound(_))));
        Ok(())
    }

    #[test]
    fn delete_removes_object() -> Result<(), VctrlError> {
        let mut store = MemoryStore::new();
        let hash = hash_byte(0xEF)?;
        let data = vec![1_u8, 2, 3];

        store.put(&hash, &data)?;
        assert!(store.exists(&hash)?);
        store.delete(&hash)?;
        assert!(!store.exists(&hash)?);
        Ok(())
    }

    #[test]
    fn exists_missing_object_returns_false() -> Result<(), VctrlError> {
        let store = MemoryStore::new();
        let hash = hash_byte(0x77)?;
        assert!(!store.exists(&hash)?);
        Ok(())
    }
}