2023-09-23 00:03:58 +00:00
|
|
|
use std::{
|
|
|
|
ops::Deref,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
};
|
|
|
|
use thiserror::Error;
|
2023-09-19 22:55:53 +00:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
|
|
mod file;
|
|
|
|
mod fileinfo;
|
|
|
|
mod thumbnail;
|
2023-09-21 03:06:34 +00:00
|
|
|
pub mod utils;
|
2023-09-19 22:55:53 +00:00
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
pub use file::File;
|
2023-09-19 22:55:53 +00:00
|
|
|
pub use fileinfo::FileInfo;
|
|
|
|
pub use thumbnail::Thumbnail;
|
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
#[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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-23 01:56:43 +00:00
|
|
|
impl From<String> 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()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct FileId(String);
|
|
|
|
|
|
|
|
impl From<String> 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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-19 22:55:53 +00:00
|
|
|
pub struct App {
|
|
|
|
files_root: PathBuf,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl App {
|
|
|
|
pub fn new(files_root: &Path) -> App {
|
|
|
|
App {
|
|
|
|
files_root: PathBuf::from(files_root),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
pub fn list_files(&self) -> Vec<Result<File, ReadFileError>> {
|
|
|
|
unimplemented!()
|
2023-09-19 22:55:53 +00:00
|
|
|
}
|
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
pub fn add_file(&mut self, filename: String, content: Vec<u8>) -> Result<File, WriteFileError> {
|
|
|
|
let context = Context(self.files_root.clone());
|
|
|
|
let mut file = File::new(filename, context)?;
|
|
|
|
file.set_content(content)?;
|
|
|
|
Ok(file)
|
2023-09-19 22:55:53 +00:00
|
|
|
}
|
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
/*
|
2023-09-21 03:06:34 +00:00
|
|
|
pub fn delete_file(&mut self, id: String) -> Result<(), FileError> {
|
2023-09-19 22:55:53 +00:00
|
|
|
let f = File::open(&id, &self.files_root)?;
|
|
|
|
f.delete()
|
|
|
|
}
|
|
|
|
|
2023-09-21 03:06:34 +00:00
|
|
|
pub fn get_metadata(&self, id: String) -> Result<FileInfo, FileError> {
|
2023-09-19 22:55:53 +00:00
|
|
|
FileInfo::open(&id, &self.files_root)
|
|
|
|
}
|
2023-09-23 00:03:58 +00:00
|
|
|
*/
|
2023-09-19 22:55:53 +00:00
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
pub fn get_file(&self, id: &str) -> Result<(FileInfo, std::fs::File), ReadFileError> {
|
|
|
|
/*
|
2023-09-19 22:55:53 +00:00
|
|
|
let f = File::open(&id, &self.files_root)?;
|
|
|
|
let info = f.info();
|
|
|
|
let stream = f.stream()?;
|
|
|
|
Ok((info, stream))
|
2023-09-23 00:03:58 +00:00
|
|
|
*/
|
|
|
|
unimplemented!()
|
2023-09-19 22:55:53 +00:00
|
|
|
}
|
|
|
|
|
2023-09-23 00:03:58 +00:00
|
|
|
pub fn get_thumbnail(&self, id: &str) -> Result<(FileInfo, std::fs::File), ReadFileError> {
|
|
|
|
/*
|
2023-09-19 22:55:53 +00:00
|
|
|
let f = File::open(id, &self.files_root)?;
|
|
|
|
let stream = f.thumbnail().stream()?;
|
|
|
|
Ok((f.info(), stream))
|
2023-09-23 00:03:58 +00:00
|
|
|
*/
|
|
|
|
unimplemented!()
|
2023-09-19 22:55:53 +00:00
|
|
|
}
|
|
|
|
}
|
2023-09-23 01:56:43 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[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")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|