Skip to main content

kellnr_storage/
fs_storage.rs

1use std::fs::DirBuilder;
2
3use async_trait::async_trait;
4use bytes::Bytes;
5use object_store::local::LocalFileSystem;
6use object_store::path::Path;
7use object_store::{ObjectStore, ObjectStoreExt, PutMode};
8
9use crate::storage::Storage;
10use crate::storage_error::StorageError;
11
12pub struct FSStorage(LocalFileSystem);
13
14#[async_trait]
15impl Storage for FSStorage {
16    async fn get(&self, key: &str) -> Result<Bytes, StorageError> {
17        self.storage()
18            .get(&Path::from(key))
19            .await?
20            .bytes()
21            .await
22            .map_err(StorageError::from)
23    }
24
25    async fn put(&self, key: &str, object: Bytes) -> Result<(), StorageError> {
26        self.storage()
27            .put_opts(&Path::from(key), object.into(), PutMode::Create.into())
28            .await?;
29        Ok(())
30    }
31
32    async fn delete(&self, key: &str) -> Result<(), StorageError> {
33        self.storage().delete(&Path::from(key)).await?;
34        Ok(())
35    }
36
37    async fn exists(&self, key: &str) -> Result<bool, StorageError> {
38        self.storage()
39            .head(&Path::from(key))
40            .await
41            .map(|_| true)
42            .or_else(|e| match e {
43                object_store::Error::NotFound { .. } => Ok(false),
44                _ => Err(StorageError::from(e)),
45            })
46    }
47}
48
49impl FSStorage {
50    pub fn new(crate_folder: &str) -> Result<Self, StorageError> {
51        let path = std::path::Path::new(crate_folder);
52        if !path.exists() {
53            DirBuilder::new()
54                .recursive(true)
55                .create(crate_folder)
56                .map_err(|e| StorageError::CreateBinPath(path.to_path_buf(), e))?;
57        }
58        let client = LocalFileSystem::new_with_prefix(path)?;
59        Ok(Self(client))
60    }
61
62    fn storage(&self) -> &LocalFileSystem {
63        &self.0
64    }
65}