use crate::{Error, Result};
use std::{
fs::{create_dir_all, read_to_string, OpenOptions},
io::Write,
path::PathBuf,
};
use tracing::{debug, info, instrument};
#[instrument(skip(filename), level = "debug")]
pub fn load<C>(filename: impl AsRef<str>, existence: Existence) -> Result<C>
where
C: std::str::FromStr<Err = Error>,
{
let path = config_dir()?.join(filename.as_ref());
debug!("Load configuration file {path:?}");
let data = match read_to_string(path) {
Ok(data) => Ok(data),
Err(err) => {
if existence == Existence::NotRequired {
if err.kind() == std::io::ErrorKind::NotFound {
Ok(String::new())
} else {
Err(err)
}
} else {
Err(err)
}
}
}?;
data.parse::<C>()
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub enum Existence {
#[default]
Required,
NotRequired,
}
#[instrument(skip(filename, config), level = "debug")]
pub fn save<C>(filename: impl AsRef<str>, config: C) -> Result<()>
where
C: std::fmt::Display,
{
let path = config_dir()?.join(filename.as_ref());
debug!("Save configuration file {path:?}");
OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(path)?
.write_all(config.to_string().as_bytes())
.map_err(Error::from)
}
pub fn home_dir() -> Result<PathBuf> {
dirs::home_dir().ok_or(Error::NoWayHome)
}
pub fn config_dir() -> Result<PathBuf> {
let config_dir = dirs::config_dir().map(|path| path.join("ocd")).ok_or(Error::NoWayHome)?;
if !config_dir.exists() {
info!("create configuration directory at {config_dir:?}");
create_dir_all(&config_dir)?;
}
Ok(config_dir)
}
pub fn data_dir() -> Result<PathBuf> {
dirs::data_dir().map(|path| path.join("ocd")).ok_or(Error::NoWayHome)
}