use crate::error::CoreError;
use crate::slab_store::SlabStore;
pub trait SlabSource: Send + Sync {
#[must_use]
fn plaintext_for(&self, drop_id: &[u8; 32]) -> Option<Result<Vec<u8>, CoreError>>;
#[must_use]
fn slab_count(&self) -> usize;
#[must_use]
fn drop_count(&self) -> usize;
}
pub struct MmapSlabSource {
inner: SlabStore,
}
impl MmapSlabSource {
#[must_use]
pub fn new(inner: SlabStore) -> Self {
Self { inner }
}
#[must_use]
pub fn inner(&self) -> &SlabStore {
&self.inner
}
pub fn inner_mut(&mut self) -> &mut SlabStore {
&mut self.inner
}
}
pub struct ChainedSlabSource<'a> {
chain: Vec<&'a dyn SlabSource>,
}
impl<'a> ChainedSlabSource<'a> {
#[must_use]
pub fn new(chain: Vec<&'a dyn SlabSource>) -> Self {
Self { chain }
}
}
pub struct OwnedSlabChain {
sources: Vec<Box<dyn SlabSource>>,
}
impl OwnedSlabChain {
#[must_use]
pub fn new(sources: Vec<Box<dyn SlabSource>>) -> Self {
Self { sources }
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.sources.is_empty()
}
}
impl SlabSource for OwnedSlabChain {
fn plaintext_for(&self, drop_id: &[u8; 32]) -> Option<Result<Vec<u8>, CoreError>> {
self.sources.iter().find_map(|s| s.plaintext_for(drop_id))
}
fn slab_count(&self) -> usize {
self.sources.iter().map(|s| s.slab_count()).sum()
}
fn drop_count(&self) -> usize {
self.sources.iter().map(|s| s.drop_count()).sum()
}
}
impl SlabSource for ChainedSlabSource<'_> {
fn plaintext_for(&self, drop_id: &[u8; 32]) -> Option<Result<Vec<u8>, CoreError>> {
self.chain.iter().find_map(|s| s.plaintext_for(drop_id))
}
fn slab_count(&self) -> usize {
self.chain.iter().map(|s| s.slab_count()).sum()
}
fn drop_count(&self) -> usize {
self.chain.iter().map(|s| s.drop_count()).sum()
}
}
impl SlabSource for MmapSlabSource {
fn plaintext_for(&self, drop_id: &[u8; 32]) -> Option<Result<Vec<u8>, CoreError>> {
self.inner.plaintext_for(drop_id)
}
fn slab_count(&self) -> usize {
self.inner.slab_count()
}
fn drop_count(&self) -> usize {
self.inner.drop_count()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mmap_source_delegates_to_inner() {
let store = SlabStore::default();
let source = MmapSlabSource::new(store);
assert_eq!(source.slab_count(), 0);
assert_eq!(source.drop_count(), 0);
let drop_id = [0u8; 32];
assert!(source.plaintext_for(&drop_id).is_none());
}
}