eight 1.0.0-alpha.2

Modular asynchronous embedded key-value database
Documentation
//! Official filesystem based storage implementation for eight.

use crate::{
    embedded::{self, filesystem},
    err,
};
use async_trait::async_trait;
use std::path::PathBuf;

/// Filesystem based storage. Preferred when you need to keep key-values on disk.
#[derive(Debug, Default)]
pub struct Storage {
    path: PathBuf,
}

impl Storage {
    /// Create new file-storage.
    ///
    /// This function is same with [`Default::default`].
    pub fn new() -> Self {
        Default::default()
    }

    /// Create new file-storage from path.
    ///
    /// ```no_run
    /// use eight::embedded::storage::filesystem;
    ///
    /// filesystem::Storage::from_path("/tmp/test");
    /// ```
    pub fn from_path<T>(path: T) -> Self
    where
        T: Into<PathBuf>,
    {
        Self { path: path.into() }
    }
}

#[async_trait]
impl super::Storage for Storage {
    async fn set(&self, key: String, value: String) -> embedded::Result<()> {
        let mut path = filesystem::create_path(&self.path, &key)?;
        filesystem::write(&mut path, value).await
    }

    async fn get(&self, key: String) -> embedded::Result<String> {
        let path = filesystem::create_path(&self.path, &key)?;
        filesystem::read(&path).await
    }

    async fn delete(&self, key: String) -> embedded::Result<()> {
        let path = filesystem::create_path(&self.path, &key)?;
        filesystem::delete(&path).await
    }

    async fn exists(&self, key: String) -> embedded::Result<bool> {
        let path = filesystem::create_path(&self.path, &key)?;
        filesystem::exists(&path).await
    }

    async fn increment(&self, key: String, num: usize) -> embedded::Result<usize> {
        let mut path = filesystem::create_path(&self.path, &key)?;

        let raw = filesystem::read(&path).await?;
        let new = raw
            .parse::<usize>()
            .map_err(|_| err!(embedded, UIntParseFail))?
            + num;

        filesystem::write(&mut path, new.to_string()).await?;
        Ok(new)
    }

    async fn decrement(&self, key: String, num: usize) -> embedded::Result<usize> {
        let mut path = filesystem::create_path(&self.path, &key)?;

        let raw = filesystem::read(&path).await?;
        let new = raw
            .parse::<usize>()
            .map_err(|_| err!(embedded, UIntParseFail))?
            - num;

        filesystem::write(&mut path, new.to_string()).await?;
        Ok(new)
    }

    async fn search(&self, key: String) -> embedded::Result<Vec<String>> {
        filesystem::search(&self.path, &key).await
    }

    async fn flush(&self) -> embedded::Result<()> {
        filesystem::flush(&self.path).await
    }
}