use std::path::Path;
use std::io::{Read, Write};
use std::fs::{self, File};
use serde::de::DeserializeOwned;
use serde::{Serialize, Deserialize};
use toml;
use failure::{Error, ResultExt};
#[derive(Debug)]
pub struct ConfigFile {}
impl ConfigFile {
pub fn load<P, T>(path: P) -> Result<T, Error>
where
T: for<'r> Deserialize<'r>,
P: AsRef<Path>,
{
let path = path.as_ref();
let res = do_load(path).context(format!(
"loading config from {}",
path.display()
))?;
Ok(res)
}
pub fn save<P, T>(value: &T, path: P) -> Result<(), Error>
where
T: Serialize,
P: AsRef<Path>,
{
let path = path.as_ref();
do_save(value, path).with_context(|_| {
format!("saving config to {}", path.display())
})?;
Ok(())
}
}
fn do_load<T: DeserializeOwned>(path: &Path) -> Result<T, Error> {
let mut file = File::open(path)?;
let mut toml = String::new();
file.read_to_string(&mut toml)?;
Ok(toml::de::from_str(&toml)?)
}
fn do_save<T: Serialize>(value: &T, path: &Path) -> Result<(), Error> {
if let Some(dir) = path.parent() {
fs::create_dir_all(dir)?;
}
let mut file = File::create(path)?;
let value_toml = toml::Value::try_from(value)?;
file.write_all(value_toml.to_string().as_bytes())?;
Ok(())
}