jubako 0.4.0

The reference implementation of the Jubako container format
Documentation
use std::sync::{Arc, OnceLock};

pub(crate) trait CachableSource<Value> {
    type Error;
    type Idx: Into<usize> + Copy;
    fn get_len(&self) -> usize;
    fn get_value(&self, id: Self::Idx) -> Result<Arc<Value>, Self::Error>;
}

pub(crate) struct VecCache<Value, Source>
where
    Source: CachableSource<Value>,
{
    source: Arc<Source>,
    values: Vec<OnceLock<Arc<Value>>>,
}

impl<Value, Source> VecCache<Value, Source>
where
    Source: CachableSource<Value>,
{
    pub fn new(source: Arc<Source>) -> Self {
        let mut values = Vec::new();
        values.resize_with(source.get_len(), Default::default);
        Self { source, values }
    }

    pub fn get(&self, index: Source::Idx) -> Result<&Arc<Value>, Source::Error> {
        let cache_slot = &self.values[index.into()];
        if cache_slot.get().is_none() {
            let new_value = self.source.get_value(index)?;
            let _ = cache_slot.set(new_value);
        }

        Ok(cache_slot.get().unwrap())
    }
}