This repository has been archived on 2024-08-23. You can view files and clone it, but cannot push or open issues or pull requests.
project/src/file_storage.rs

74 lines
2.2 KiB
Rust
Raw Normal View History

2024-06-27 12:04:57 +00:00
use std::{
env, io,
path::{Path, PathBuf},
sync::Arc,
};
use tokio::fs;
use uuid::Uuid;
#[derive(Clone)]
pub struct FileStorage(Arc<Path>);
impl FileStorage {
pub fn new() -> anyhow::Result<Self> {
let var = env::var("DRIVE_STORAGE_PATH");
let path_str = match var {
Ok(ref string) => string,
Err(err) => {
tracing::info!(
%err,
"Error getting DRIVE_STORAGE_PATH variable. Defaulting to ./files"
);
"./files"
}
};
let path = Path::new(path_str);
match path.metadata() {
Ok(meta) => anyhow::ensure!(meta.is_dir(), "Expected path to a directory"),
Err(err) if err.kind() == io::ErrorKind::NotFound => {
std::fs::create_dir_all(path)?;
}
Err(err) => return Err(err.into()),
};
Ok(FileStorage(path.into()))
}
fn path_for_file(&self, file_id: Uuid) -> PathBuf {
let file_name = file_id.as_hyphenated().to_string();
self.0.join(file_name)
}
async fn create_inner(&self, file_id: Uuid) -> anyhow::Result<impl tokio::io::AsyncWrite> {
fs::File::create_new(self.path_for_file(file_id))
.await
.map_err(Into::into)
}
pub async fn create(&self) -> anyhow::Result<(Uuid, impl tokio::io::AsyncWrite)> {
let mut error = anyhow::anyhow!("Error creating a file");
for _ in 0..3 {
let file_id = Uuid::new_v4();
match self.create_inner(file_id).await {
Ok(file) => return Ok((file_id, file)),
Err(err) => error = error.context(err),
}
}
Err(error)
}
pub async fn read(&self, file_id: Uuid) -> anyhow::Result<impl tokio::io::AsyncRead> {
fs::File::open(self.path_for_file(file_id))
.await
.map_err(Into::into)
}
pub async fn delete(&self, file_id: Uuid) -> anyhow::Result<bool> {
match fs::remove_file(self.path_for_file(file_id)).await {
Ok(()) => Ok(true),
Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(false),
Err(err) => Err(err.into()),
}
}
}