Refactor PathResolver so it cannot fail
This commit is contained in:
parent
a3add82294
commit
5c23427fdb
|
@ -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"
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue