use std::ffi::OsStr;
use std::path::Path;
use std::path::PathBuf;
use crate::HomeDirError;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct AppStrategyArgs {
pub top_level_domain: String,
pub author: String,
pub app_name: String,
}
impl AppStrategyArgs {
pub fn bundle_id(&self) -> String {
let author = self.author.to_lowercase().replace(' ', "-");
let app_name = self.app_name.replace(' ', "-");
let mut parts = vec![
self.top_level_domain.as_str(),
author.as_str(),
app_name.as_str(),
];
parts.retain(|part| !part.is_empty());
parts.join(".")
}
pub fn unixy_name(&self) -> String {
self.app_name.to_lowercase().replace(' ', "-")
}
}
macro_rules! in_dir_method {
($self: ident, $path_extra: expr, $dir_method_name: ident) => {{
let mut path = $self.$dir_method_name();
path.push(Path::new(&$path_extra));
path
}};
(opt: $self: ident, $path_extra: expr, $dir_method_name: ident) => {{
let mut path = $self.$dir_method_name()?;
path.push(Path::new(&$path_extra));
Some(path)
}};
}
pub trait AppStrategy {
fn home_dir(&self) -> &Path;
fn config_dir(&self) -> PathBuf;
fn data_dir(&self) -> PathBuf;
fn cache_dir(&self) -> PathBuf;
fn state_dir(&self) -> Option<PathBuf>;
fn runtime_dir(&self) -> Option<PathBuf>;
fn in_config_dir<P: AsRef<OsStr>>(&self, path: P) -> PathBuf {
in_dir_method!(self, path, config_dir)
}
fn in_data_dir<P: AsRef<OsStr>>(&self, path: P) -> PathBuf {
in_dir_method!(self, path, data_dir)
}
fn in_cache_dir<P: AsRef<OsStr>>(&self, path: P) -> PathBuf {
in_dir_method!(self, path, cache_dir)
}
fn in_state_dir<P: AsRef<OsStr>>(&self, path: P) -> Option<PathBuf> {
in_dir_method!(opt: self, path, state_dir)
}
fn in_runtime_dir<P: AsRef<OsStr>>(&self, path: P) -> Option<PathBuf> {
in_dir_method!(opt: self, path, runtime_dir)
}
}
macro_rules! create_strategies {
($native: ty, $app: ty) => {
pub fn choose_native_strategy(args: AppStrategyArgs) -> Result<$native, HomeDirError> {
<$native>::new(args)
}
pub fn choose_app_strategy(args: AppStrategyArgs) -> Result<$app, HomeDirError> {
<$app>::new(args)
}
};
}
cfg_if::cfg_if! {
if #[cfg(target_os = "windows")] {
create_strategies!(Windows, Windows);
} else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
create_strategies!(Apple, Xdg);
} else {
create_strategies!(Xdg, Xdg);
}
}
mod apple;
mod unix;
mod windows;
mod xdg;
pub use apple::Apple;
pub use unix::Unix;
pub use windows::Windows;
pub use xdg::Xdg;