fixity 0.0.1

Storage for structured and unstructured data backed by an immutable storage engine
use {
    crate::{
        core::{
            cache::{AsCacheRef, CacheRead, CacheWrite},
            primitive::{BytesCreate, BytesRead},
            workspace::{AsWorkspaceRef, Guard, Workspace},
        },
        Addr, Error, Path,
    },
    tokio::io::{AsyncRead, AsyncWrite},
};
pub struct Bytes<'f, C, W> {
    storage: &'f C,
    workspace: &'f W,
    path: Path,
}
impl<'f, C, W> Bytes<'f, C, W> {
    pub fn new(storage: &'f C, workspace: &'f W, path: Path) -> Self {
        Self {
            storage,
            workspace,
            path,
        }
    }
    pub async fn read<Writer>(&self, w: Writer) -> Result<Option<u64>, Error>
    where
        C: CacheRead,
        W: Workspace,
        Writer: AsyncWrite + Unpin + Send,
    {
        let workspace_guard = self.workspace.lock().await?;
        let root_content_addr = workspace_guard
            .status()
            .await?
            .content_addr(self.storage)
            .await?;
        let content_addr = self
            .path
            .resolve_last(self.storage, root_content_addr)
            .await?;
        let reader = if let Some(content_addr) = content_addr {
            BytesRead::new(self.storage, content_addr)
        } else {
            return Ok(None);
        };
        let n = reader.read(w).await?;
        Ok(Some(n))
    }
    pub async fn write<Reader>(&self, r: Reader) -> Result<Addr, Error>
    where
        C: CacheRead + CacheWrite,
        W: Workspace,
        Reader: AsyncRead + Unpin + Send,
    {
        let workspace_guard = self.workspace.lock().await?;
        let root_content_addr = workspace_guard
            .status()
            .await?
            .content_addr(self.storage)
            .await?;
        let resolved_path = self.path.resolve(self.storage, root_content_addr).await?;
        let new_self_addr = BytesCreate::new(self.storage).write(r).await?;
        let new_staged_content = self
            .path
            .update(self.storage, resolved_path, new_self_addr)
            .await?;
        workspace_guard.stage(new_staged_content.clone()).await?;
        Ok(new_staged_content)
    }
}
impl<C, W> AsWorkspaceRef for Bytes<'_, C, W>
where
    W: Workspace,
{
    type Workspace = W;
    fn as_workspace_ref(&self) -> &Self::Workspace {
        &self.workspace
    }
}
impl<C, W> AsCacheRef for Bytes<'_, C, W>
where
    C: CacheRead + CacheWrite,
{
    type Cache = C;
    fn as_cache_ref(&self) -> &Self::Cache {
        &self.storage
    }
}