use std::{ ops::Deref, path::{Path, PathBuf}, }; use thiserror::Error; use uuid::Uuid; mod file; mod fileinfo; mod thumbnail; pub mod utils; pub use file::File; pub use fileinfo::FileInfo; pub use thumbnail::Thumbnail; #[derive(Debug, Error)] pub enum WriteFileError { #[error("root file path does not exist")] RootNotFound, #[error("permission denied")] PermissionDenied, #[error("JSON error")] JSONError(#[from] serde_json::error::Error), #[error("IO error")] IOError(#[from] std::io::Error), } #[derive(Debug, Error)] pub enum ReadFileError { #[error("file not found")] FileNotFound, #[error("path is not a file")] NotAFile, #[error("permission denied")] PermissionDenied, #[error("JSON error")] JSONError(#[from] serde_json::error::Error), #[error("IO error")] IOError(#[from] std::io::Error), } #[derive(Clone, Debug)] pub struct PathResolver(pub PathBuf); impl PathResolver { fn file_path(&self) -> PathBuf { self.0.clone() } fn metadata_path(&self) -> PathBuf { let mut path = self.0.clone(); path.set_extension("json"); path } fn thumbnail_path(&self) -> PathBuf { let mut path = self.0.clone(); path.set_extension("tn"); path } } impl From for PathResolver { fn from(s: String) -> Self { Self(PathBuf::from(s)) } } impl From<&str> for PathResolver { fn from(s: &str) -> Self { Self(PathBuf::from(s.to_owned())) } } #[derive(Clone, Debug)] pub struct FileId(String); impl From for FileId { fn from(s: String) -> Self { Self(s) } } impl From<&str> for FileId { fn from(s: &str) -> Self { Self(s.to_owned()) } } impl Deref for FileId { type Target = String; fn deref(&self) -> &Self::Target { &self.0 } } pub trait FileRoot { fn root(&self) -> PathBuf; } pub struct Context(PathBuf); impl FileRoot for Context { fn root(&self) -> PathBuf { self.0.clone() } } pub struct Store { files_root: PathBuf, } impl Store { pub fn new(files_root: PathBuf) -> Self { Self { files_root } } pub fn list_files(&self) -> Vec> { unimplemented!() } pub fn add_file(&mut self, filename: String, content: Vec) -> Result { let context = Context(self.files_root.clone()); let mut file = File::new(filename, context)?; file.set_content(content)?; Ok(file) } pub fn delete_file(&mut self, id: String) -> Result<(), WriteFileError> { /* let f = File::open(&id, &self.files_root)?; f.delete() */ unimplemented!() } pub fn get_metadata(&self, id: String) -> Result { // FileInfo::open(&id, &self.files_root) unimplemented!() } pub fn get_file(&self, id: &str) -> Result<(FileInfo, std::fs::File), ReadFileError> { /* let f = File::open(&id, &self.files_root)?; let info = f.info(); let stream = f.stream()?; Ok((info, stream)) */ unimplemented!() } pub fn get_thumbnail(&self, id: &str) -> Result<(FileInfo, std::fs::File), ReadFileError> { /* let f = File::open(id, &self.files_root)?; let stream = f.thumbnail().stream()?; Ok((f.info(), stream)) */ unimplemented!() } } #[cfg(test)] mod test { use crate::store::utils::FileCleanup; use super::*; use std::io::Read; #[test] fn paths() { let resolver = PathResolver::from("path/82420255-d3c8-4d90-a582-f94be588c70c"); assert_eq!( resolver.file_path(), PathBuf::from("path/82420255-d3c8-4d90-a582-f94be588c70c") ); assert_eq!( resolver.metadata_path(), PathBuf::from("path/82420255-d3c8-4d90-a582-f94be588c70c.json") ); assert_eq!( resolver.thumbnail_path(), PathBuf::from("path/82420255-d3c8-4d90-a582-f94be588c70c.tn") ); } #[test] fn adds_files() { let mut buf = Vec::new(); let mut file = std::fs::File::open("fixtures/rawr.png").unwrap(); file.read_to_end(&mut buf).unwrap(); let mut store = Store::new(PathBuf::from("var/")); let file_record = store.add_file("rawr.png".to_owned(), buf).unwrap(); let _file = FileCleanup(PathBuf::from(format!("var/{}", *file_record.id))); let _md = FileCleanup(PathBuf::from(format!("var/{}.json", *file_record.id))); let _tn = FileCleanup(PathBuf::from(format!("var/{}.tn", *file_record.id))); assert!(PathBuf::from(format!("var/{}", *file_record.id)).exists()); assert!(PathBuf::from(format!("var/{}.json", *file_record.id)).exists()); assert!(PathBuf::from(format!("var/{}.tn", *file_record.id)).exists()); } #[test] fn sets_up_metadata_for_file() {} #[test] fn sets_up_thumbnail_for_file() {} #[test] fn deletes_associated_files() {} #[test] fn lists_files_in_the_db() {} }