use dirs;
use std::{
fs, io,
path::{Path, PathBuf},
};
#[derive(Debug, PartialEq, Eq)]
enum StoreType {
Home,
Config,
ConfigLocal,
Executable,
Audio,
Cache,
Data,
DataLocal,
Desktop,
Download,
Document,
Font,
Picture,
Preference,
Public,
Runtime,
State,
Template,
Video,
}
impl StoreType {
pub fn path(&self) -> fn() -> Option<PathBuf> {
match *self {
Self::Home => dirs::home_dir,
Self::Config => dirs::config_dir,
Self::ConfigLocal => dirs::config_local_dir,
Self::Executable => dirs::executable_dir,
Self::Audio => dirs::audio_dir,
Self::Cache => dirs::cache_dir,
Self::Data => dirs::data_dir,
Self::DataLocal => dirs::data_local_dir,
Self::Desktop => dirs::desktop_dir,
Self::Download => dirs::download_dir,
Self::Document => dirs::document_dir,
Self::Font => dirs::font_dir,
Self::Picture => dirs::picture_dir,
Self::Preference => dirs::preference_dir,
Self::Public => dirs::public_dir,
Self::Runtime => dirs::runtime_dir,
Self::State => dirs::state_dir,
Self::Template => dirs::template_dir,
Self::Video => dirs::video_dir,
}
}
}
fn create_dir(path: &PathBuf) -> io::Result<()> {
if !path.exists() {
fs::create_dir_all(&path)?;
}
Ok(())
}
fn create_store(store: StoreType, path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
let dir_fn = store.path();
if let Some(root) = dir_fn() {
let store_dir = root.join(format!(".{}", path.as_ref().display()));
create_dir(&store_dir)?;
Ok(Some(store_dir))
} else {
Ok(None)
}
}
pub fn audio_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Audio, path)
}
pub fn cache_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Cache, path)
}
pub fn config_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Config, path)
}
pub fn local_config_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::ConfigLocal, path)
}
pub fn data_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Data, path)
}
pub fn local_data_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::DataLocal, path)
}
pub fn desktop_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Desktop, path)
}
pub fn document_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Document, path)
}
pub fn download_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Download, path)
}
pub fn executable_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Executable, path)
}
pub fn font_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Font, path)
}
pub fn home_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Home, path)
}
pub fn picture_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Picture, path)
}
pub fn preference_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Preference, path)
}
pub fn public_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Public, path)
}
pub fn runtime_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Runtime, path)
}
pub fn state_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::State, path)
}
pub fn template_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Template, path)
}
pub fn video_store(path: impl AsRef<Path>) -> io::Result<Option<PathBuf>> {
create_store(StoreType::Video, path)
}
pub fn custom_store(
root_path: impl AsRef<Path>,
target: impl AsRef<Path>,
) -> io::Result<Option<PathBuf>> {
let root = PathBuf::from(root_path.as_ref());
let store_dir = root.join(format!(".{}", target.as_ref().display()));
create_dir(&store_dir)?;
Ok(Some(store_dir))
}