use std::{
fmt::Display,
path::{Path, PathBuf},
};
use crate::{DocumentError, FileSystemEntity};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Folder<'a> {
User(User<'a>),
Project((Project<'a>, &'a str, &'a str, &'a str)),
}
fn join_all(path: &Path, subdirs: &[&str]) -> PathBuf {
let mut pathbuf = path.to_path_buf();
for subdir in subdirs {
pathbuf.push(subdir);
}
pathbuf
}
impl<'a> Folder<'a> {
pub(crate) fn into_pathbuf_result(
&self,
filename: impl Display,
) -> Result<PathBuf, DocumentError> {
match self {
Folder::User(subdir) => match subdir {
User::Pictures(subdirs) => {
if let Some(dir) = directories::UserDirs::new() {
if let Some(path) = dir.picture_dir() {
let mut pathbuf = join_all(path, subdirs);
pathbuf = pathbuf.join(filename.to_string());
Ok(pathbuf)
} else {
Err(DocumentError::PicturesDirNotFound)?
}
} else {
Err(DocumentError::UserDirsNotFound)?
}
}
User::Videos(subdirs) => {
if let Some(dir) = directories::UserDirs::new() {
if let Some(path) = dir.video_dir() {
let mut pathbuf = join_all(path, subdirs);
pathbuf = pathbuf.join(filename.to_string());
Ok(pathbuf)
} else {
Err(DocumentError::VideosDirNotFound)?
}
} else {
Err(DocumentError::UserDirsNotFound)?
}
}
User::Downloads(subdirs) => {
if let Some(dir) = directories::UserDirs::new() {
if let Some(path) = dir.download_dir() {
let mut pathbuf = join_all(path, subdirs);
pathbuf = pathbuf.join(filename.to_string());
Ok(pathbuf)
} else {
Err(DocumentError::DownloadsDirNotFound)?
}
} else {
Err(DocumentError::UserDirsNotFound)?
}
}
User::Documents(subdirs) => {
if let Some(dir) = directories::UserDirs::new() {
if let Some(path) = dir.document_dir() {
let mut pathbuf = join_all(path, subdirs);
pathbuf = pathbuf.join(filename.to_string());
Ok(pathbuf)
} else {
Err(DocumentError::DocumentsDirNotFound)?
}
} else {
Err(DocumentError::UserDirsNotFound)?
}
}
User::Home(subdirs) => {
if let Some(dir) = directories::UserDirs::new() {
let path = dir.home_dir();
let mut pathbuf = join_all(path, subdirs);
pathbuf = pathbuf.join(filename.to_string());
Ok(pathbuf)
} else {
Err(DocumentError::UserDirsNotFound)?
}
}
},
Folder::Project((subdir, qualifier, organization, application)) => match subdir {
Project::Data(subdirs) => {
if let Some(dir) =
directories::ProjectDirs::from(qualifier, organization, application)
{
let mut pathbuf = join_all(dir.data_dir(), subdirs);
pathbuf = pathbuf.join(filename.to_string());
Ok(pathbuf)
} else {
Err(DocumentError::ProjectDirsNotFound)?
}
}
Project::Config(subdirs) => {
if let Some(dir) =
directories::ProjectDirs::from(qualifier, organization, application)
{
let mut pathbuf = join_all(dir.config_dir(), subdirs);
pathbuf = pathbuf.join(filename.to_string());
Ok(pathbuf)
} else {
Err(DocumentError::ProjectDirsNotFound)?
}
}
},
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum User<'a> {
Documents(&'a [&'a str]),
Pictures(&'a [&'a str]),
Videos(&'a [&'a str]),
Downloads(&'a [&'a str]),
Home(&'a [&'a str]),
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Project<'a> {
Config(&'a [&'a str]),
Data(&'a [&'a str]),
}
impl<'a> Project<'a> {
pub fn with_id(
self,
qualifier: &'a str,
organization: &'a str,
application: &'a str,
) -> (Self, &'a str, &'a str, &'a str) {
(self, qualifier, organization, application)
}
}
impl<'a> FileSystemEntity for Folder<'a> {
fn exists(&self) -> bool {
self.into_pathbuf_result("").unwrap_or_default().exists()
}
fn name(&self) -> String {
self.into_pathbuf_result("")
.unwrap_or_default()
.file_name()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.to_string()
}
fn path(&self) -> String {
self.into_pathbuf_result("")
.unwrap_or_default()
.display()
.to_string()
}
}