starlane 0.3.19

Starlane -- An Orchestration and Infrastructure Framework for WebAssembly Components (https://starlane.io) This packaged manages `HyperSpace` which provides infrastructure for `Space` Apis (WebAssembly & external programs meant to provide custom behaviors in Starlane), This package references the `starlane-space` package and reuses of it to run the infrastructure and it also contains mechanisms (Drivers) for extending the Starlane Type system
Documentation
use crate::err::StarErr;
use crate::hyperspace::err::HyperErr;
use crate::hyperspace::platform::Platform;
use itertools::Itertools;
use starlane::space::substance::Substance;
use std::path::PathBuf;

#[async_trait]
pub trait FileStore<K>
where
    K: Clone + Sized,
    Self: Clone + Sized,
{
    async fn get<'a>(&'a self, point: &'a K) -> Result<Substance, StarErr>;
    async fn insert<'a>(&'a self, point: &'a K, substance: Substance) -> Result<(), StarErr>;

    async fn mkdir<'a>(&'a self, point: &'a K) -> Result<(), StarErr>;
    async fn remove<'a>(&'a self, point: &'a K) -> Result<(), StarErr>;

    async fn list<'a>(&'a self, point: &'a K) -> Result<Vec<K>, StarErr>;

    async fn child<F, S>(&self, seg: S) -> Result<F, StarErr>
    where
        F: FileStore<K>,
        S: ToString;
}

#[derive(Clone)]
pub struct LocalFileStore
{
    pub root: PathBuf,
}

impl LocalFileStore
{
    pub fn new<B>(root: B) -> Self
    where
        B: Into<PathBuf>
    {
        let root = root.into();
        Self {
            root,
        }
    }
}

#[async_trait]
impl FileStore<PathBuf> for LocalFileStore

{
    async fn get<'a>(&'a self, path: &'a PathBuf) -> Result<Substance, StarErr> {
        let path = self.root.join(path);
        let data = tokio::fs::read(path).await?;
        Ok(Substance::from_vec(data))
    }

    async fn insert<'a>(&'a self, path: &'a PathBuf, substance: Substance) -> Result<(), StarErr> {
        let path = self.root.join(path);
        let data = substance.to_bin()?;
        tokio::fs::write(path, data).await?;
        Ok(())
    }

    async fn mkdir<'a>(&'a self, path: &'a PathBuf) -> Result<(), StarErr> {
        let path = self.root.join(path);
        tokio::fs::create_dir_all(path).await?;
        Ok(())
    }

    async fn remove<'a>(&'a self, path: &'a PathBuf) -> Result<(), StarErr> {
        let path = self.root.join(path);
        tokio::fs::remove_dir_all(path).await?;
        Ok(())
    }

    async fn list<'a>(&'a self, path: &'a PathBuf) -> Result<Vec<PathBuf>, StarErr> {
        let path = self.root.join(path);
        let mut read = tokio::fs::read_dir(path).await?;
        let mut rtn = vec![];
        while let Some(entry) = read.next_entry().await? {
            rtn.push(entry.path());
        }
        Ok(rtn)
    }

    async fn child<F, S>(&self, seg: S) -> Result<F, StarErr>
    where
        F: FileStore<PathBuf>,
        S: ToString,
    {
        if Path::new(&seg).iter().count() != 1 {
            return Result::Err(StarErr::new(format!(
                "invalid child path segment: '{}' ... Child path can only be one path segment",
                seg.to_string()
            )));
        }
        self.mkdir(&seg).await?;
        let root = self.root.join(seg);
        Ok(Self::new(root))
    }
}