use bytes::Bytes;
use crate::{
BlobId, RusticResult,
backend::{cache::Cache, decrypt::DecryptBackend},
crypto::aespoly1305::Key,
index::GlobalIndex,
repofile::{ConfigFile, KeyId},
};
pub trait Open {
fn open_status(&self) -> &OpenStatus;
fn open_status_mut(&mut self) -> &mut OpenStatus;
fn into_open_status(self) -> OpenStatus;
}
pub trait IndexedTree: Open {
fn index(&self) -> &GlobalIndex;
}
pub trait IndexedIds: IndexedTree {
fn into_indexed_tree(self) -> IndexedTreesStatus;
}
pub trait IndexedFull: IndexedIds {
fn get_blob_or_insert_with(
&self,
id: &BlobId,
with: impl FnOnce() -> RusticResult<Bytes>,
) -> RusticResult<Bytes>;
}
#[derive(Debug)]
pub struct OpenStatus {
pub(super) cache: Option<Cache>,
pub(super) dbe: DecryptBackend<Key>,
pub(super) config: ConfigFile,
pub(super) key_id: Option<KeyId>,
}
impl Open for OpenStatus {
fn open_status(&self) -> &OpenStatus {
self
}
fn open_status_mut(&mut self) -> &mut OpenStatus {
self
}
fn into_open_status(self) -> OpenStatus {
self
}
}
#[derive(Debug)]
pub struct IndexedTreesStatus {
pub(super) open: OpenStatus,
pub(super) index: GlobalIndex,
}
impl Open for IndexedTreesStatus {
fn open_status(&self) -> &OpenStatus {
&self.open
}
fn open_status_mut(&mut self) -> &mut OpenStatus {
&mut self.open
}
fn into_open_status(self) -> OpenStatus {
self.open
}
}
impl IndexedTree for IndexedTreesStatus {
fn index(&self) -> &GlobalIndex {
&self.index
}
}
#[derive(Debug)]
pub struct IndexedIdsStatus {
pub(super) open: OpenStatus,
pub(super) index: GlobalIndex,
}
impl Open for IndexedIdsStatus {
fn open_status(&self) -> &OpenStatus {
&self.open
}
fn open_status_mut(&mut self) -> &mut OpenStatus {
&mut self.open
}
fn into_open_status(self) -> OpenStatus {
self.open
}
}
impl IndexedTree for IndexedIdsStatus {
fn index(&self) -> &GlobalIndex {
&self.index
}
}
impl IndexedIds for IndexedIdsStatus {
fn into_indexed_tree(self) -> IndexedTreesStatus {
IndexedTreesStatus {
open: self.open,
index: self.index.drop_data(),
}
}
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct BytesWeighter;
impl quick_cache::Weighter<BlobId, Bytes> for BytesWeighter {
fn weight(&self, _key: &BlobId, val: &Bytes) -> u64 {
u64::try_from(val.len())
.expect("weight overflow in cache should not happen")
.max(1)
}
}
#[derive(Debug)]
pub struct IndexedFullStatus {
pub(super) open: OpenStatus,
pub(super) index: GlobalIndex,
pub(super) cache: quick_cache::sync::Cache<BlobId, Bytes, BytesWeighter>,
}
impl Open for IndexedFullStatus {
fn open_status(&self) -> &OpenStatus {
&self.open
}
fn open_status_mut(&mut self) -> &mut OpenStatus {
&mut self.open
}
fn into_open_status(self) -> OpenStatus {
self.open
}
}
impl IndexedTree for IndexedFullStatus {
fn index(&self) -> &GlobalIndex {
&self.index
}
}
impl IndexedIds for IndexedFullStatus {
fn into_indexed_tree(self) -> IndexedTreesStatus {
IndexedTreesStatus {
open: self.open,
index: self.index.drop_data(),
}
}
}
impl IndexedFull for IndexedFullStatus {
fn get_blob_or_insert_with(
&self,
id: &BlobId,
with: impl FnOnce() -> RusticResult<Bytes>,
) -> RusticResult<Bytes> {
self.cache.get_or_insert_with(id, with)
}
}