radixdb-storage 1.1.0

Storage contracts and physical persistence engine for RadixDB
Documentation
use std::sync::OnceLock;

use sha2::{Digest, Sha256};

pub(super) const EXACT_VALIDATION_SLOT_BYTES: usize = size_of::<OnceLock<[u8; 32]>>();

#[derive(Debug, Clone)]
pub(super) struct ValidatedExactPages(Vec<OnceLock<[u8; 32]>>);

impl ValidatedExactPages {
    pub(super) fn new(pages: usize) -> Self {
        Self((0..pages).map(|_| OnceLock::new()).collect())
    }

    pub(super) fn matches(&self, page: usize, logical: &[u8]) -> Option<bool> {
        self.0
            .get(page)
            .and_then(OnceLock::get)
            .map(|expected| *expected == <[u8; 32]>::from(Sha256::digest(logical)))
    }

    pub(super) fn remember(&self, page: usize, logical: &[u8]) {
        if let Some(slot) = self.0.get(page) {
            let _ = slot.set(Sha256::digest(logical).into());
        }
    }
}

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

    #[test]
    fn validation_identity_is_per_page_and_never_replaced() {
        let pages = ValidatedExactPages::new(2);
        assert_eq!(pages.matches(0, b"page"), None);
        pages.remember(0, b"page");
        assert_eq!(pages.matches(0, b"page"), Some(true));
        assert_eq!(pages.matches(0, b"changed page"), Some(false));
        assert_eq!(pages.matches(1, b"page"), None);
        pages.remember(0, b"changed page");
        assert_eq!(pages.matches(0, b"page"), Some(true));
        assert_eq!(pages.clone().matches(0, b"page"), Some(true));
    }
}