Refactor PathResolver so it cannot fail

This commit is contained in:
Savanni D'Gerinel 2023-09-25 00:05:45 -04:00
parent 759a4b6a1a
commit f7012ee11a
1 changed files with 34 additions and 53 deletions

View File

@ -21,27 +21,34 @@ pub enum PathError {
pub struct PathResolver { pub struct PathResolver {
base: PathBuf, base: PathBuf,
id: FileId, id: FileId,
extension: String,
} }
impl PathResolver { impl PathResolver {
pub fn new(base: &Path, id: FileId) -> Self { pub fn new(base: &Path, id: FileId, extension: String) -> Self {
Self { Self {
base: base.to_owned(), base: base.to_owned(),
id, id,
extension,
} }
} }
pub fn metadata_path_by_id(base: &Path, id: FileId) -> PathBuf {
let mut path = base.to_path_buf();
path.push(PathBuf::from(id.clone()));
path.set_extension("json");
path
}
pub fn id(&self) -> FileId { pub fn id(&self) -> FileId {
self.id.clone() self.id.clone()
} }
pub fn file_path(&self) -> Result<PathBuf, ReadFileError> { pub fn file_path(&self) -> PathBuf {
let info = FileInfo::load(self.metadata_path())?;
let mut path = self.base.clone(); let mut path = self.base.clone();
path.push(PathBuf::from(self.id.clone())); path.push(PathBuf::from(self.id.clone()));
path.set_extension(info.extension); path.set_extension(self.extension.clone());
Ok(path) path
} }
pub fn metadata_path(&self) -> PathBuf { pub fn metadata_path(&self) -> PathBuf {
@ -51,13 +58,11 @@ impl PathResolver {
path path
} }
pub fn thumbnail_path(&self) -> Result<PathBuf, ReadFileError> { pub fn thumbnail_path(&self) -> PathBuf {
let info = FileInfo::load(self.metadata_path())?;
let mut path = self.base.clone(); let mut path = self.base.clone();
path.push(PathBuf::from(self.id.clone())); path.push(PathBuf::from(self.id.clone()));
path.set_extension(format!("tn.{}", info.extension)); path.set_extension(format!("tn.{}", self.extension));
Ok(path) path
} }
} }
@ -94,6 +99,10 @@ impl TryFrom<&Path> for PathResolver {
.file_stem() .file_stem()
.and_then(|s| s.to_str().map(|s| FileId::from(s))) .and_then(|s| s.to_str().map(|s| FileId::from(s)))
.ok_or(PathError::InvalidPath)?, .ok_or(PathError::InvalidPath)?,
extension: path
.extension()
.and_then(|s| s.to_str().map(|s| s.to_owned()))
.ok_or(PathError::InvalidPath)?,
}) })
} }
} }
@ -119,6 +128,7 @@ impl FileHandle {
let path = PathResolver { let path = PathResolver {
base: root.clone(), base: root.clone(),
id: id.clone(), id: id.clone(),
extension: extension.clone(),
}; };
let file_type = mime_guess::from_ext(&extension) let file_type = mime_guess::from_ext(&extension)
@ -142,8 +152,8 @@ impl FileHandle {
} }
pub fn load(id: &FileId, root: &Path) -> Result<Self, ReadFileError> { pub fn load(id: &FileId, root: &Path) -> Result<Self, ReadFileError> {
let resolver = PathResolver::new(root, id.clone()); let info = FileInfo::load(PathResolver::metadata_path_by_id(root, id.clone()))?;
let info = FileInfo::load(resolver.metadata_path())?; let resolver = PathResolver::new(root, id.clone(), info.extension.clone());
Ok(Self { Ok(Self {
id: info.id.clone(), id: info.id.clone(),
path: resolver, path: resolver,
@ -152,11 +162,7 @@ impl FileHandle {
} }
pub fn set_content(&mut self, content: Vec<u8>) -> Result<(), WriteFileError> { pub fn set_content(&mut self, content: Vec<u8>) -> Result<(), WriteFileError> {
let mut content_file = std::fs::File::create( let mut content_file = std::fs::File::create(self.path.file_path())?;
self.path
.file_path()
.map_err(|_| WriteFileError::NoMetadata)?,
)?;
let byte_count = content_file.write(&content)?; let byte_count = content_file.write(&content)?;
self.info.size = byte_count; self.info.size = byte_count;
self.info.hash = self.hash_content(&content).as_string(); self.info.hash = self.hash_content(&content).as_string();
@ -170,11 +176,11 @@ impl FileHandle {
} }
pub fn content(&self) -> Result<Vec<u8>, ReadFileError> { pub fn content(&self) -> Result<Vec<u8>, ReadFileError> {
load_content(&self.path.file_path()?) load_content(&self.path.file_path())
} }
pub fn thumbnail(&self) -> Result<Vec<u8>, ReadFileError> { pub fn thumbnail(&self) -> Result<Vec<u8>, ReadFileError> {
load_content(&self.path.thumbnail_path()?) load_content(&self.path.thumbnail_path())
} }
fn hash_content(&self, data: &Vec<u8>) -> HexString { fn hash_content(&self, data: &Vec<u8>) -> HexString {
@ -182,35 +188,15 @@ impl FileHandle {
} }
fn write_thumbnail(&self) -> Result<(), WriteFileError> { fn write_thumbnail(&self) -> Result<(), WriteFileError> {
let img = image::open( let img = image::open(&self.path.file_path())?;
&self
.path
.file_path()
.map_err(|_| WriteFileError::NoMetadata)?,
)?;
let tn = img.resize(640, 640, FilterType::Nearest); let tn = img.resize(640, 640, FilterType::Nearest);
tn.save( tn.save(&self.path.thumbnail_path())?;
&self
.path
.thumbnail_path()
.map_err(|_| WriteFileError::NoMetadata)?,
)?;
Ok(()) Ok(())
} }
pub fn delete(self) { pub fn delete(self) {
match self.path.thumbnail_path() { let _ = std::fs::remove_file(self.path.thumbnail_path());
Ok(path) => { let _ = std::fs::remove_file(self.path.file_path());
let _ = std::fs::remove_file(path);
}
Err(_) => {}
};
match self.path.file_path() {
Ok(path) => {
let _ = std::fs::remove_file(path);
}
Err(_) => {}
};
let _ = std::fs::remove_file(self.path.metadata_path()); let _ = std::fs::remove_file(self.path.metadata_path());
} }
} }
@ -226,7 +212,6 @@ fn load_content(path: &Path) -> Result<Vec<u8>, ReadFileError> {
mod test { mod test {
use super::*; use super::*;
use crate::store::utils::DirCleanup; use crate::store::utils::DirCleanup;
use cool_asserts::assert_matches;
use std::{convert::TryFrom, path::PathBuf}; use std::{convert::TryFrom, path::PathBuf};
#[test] #[test]
@ -234,21 +219,17 @@ mod test {
let resolver = PathResolver::try_from("path/82420255-d3c8-4d90-a582-f94be588c70c.png") let resolver = PathResolver::try_from("path/82420255-d3c8-4d90-a582-f94be588c70c.png")
.expect("to have a valid path"); .expect("to have a valid path");
assert_matches!( assert_eq!(
resolver.file_path(), resolver.file_path(),
Ok(path) => assert_eq!(path, PathBuf::from( PathBuf::from("path/82420255-d3c8-4d90-a582-f94be588c70c.png")
"path/82420255-d3c8-4d90-a582-f94be588c70c.png"
))
); );
assert_eq!( assert_eq!(
resolver.metadata_path(), resolver.metadata_path(),
PathBuf::from("path/82420255-d3c8-4d90-a582-f94be588c70c.json") PathBuf::from("path/82420255-d3c8-4d90-a582-f94be588c70c.json")
); );
assert_matches!( assert_eq!(
resolver.thumbnail_path(), resolver.thumbnail_path(),
Ok(path) => assert_eq!(path, PathBuf::from( PathBuf::from("path/82420255-d3c8-4d90-a582-f94be588c70c.tn.png")
"path/82420255-d3c8-4d90-a582-f94be588c70c.tn.png"
))
); );
} }