use serde::Deserialize;
use std::fmt;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
use std::error::Error;
pub fn read_toml_from_file<T>(path: impl AsRef<Path>) -> Result<T,TomlError>
where T: for<'de> Deserialize<'de> {
let text = match fs::read_to_string(&path) {
Ok(t) => t,
Err(e) => {
return Err(TomlError::FileError{
path: path.as_ref().into(),
io_error: e
});
}
};
match toml::from_str(&text) {
Ok(t) => Ok(t),
Err(e) => {
return Err(TomlError::ParseError{
path: path.as_ref().into(),
toml_error: e
});
}
}
}
#[derive(Debug)]
pub enum TomlError {
FileError{
path: PathBuf,
io_error: std::io::Error
},
ParseError{
path: PathBuf,
toml_error: toml::de::Error
},
}
impl fmt::Display for TomlError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::FileError{path, io_error} =>
write!(f,"Error while reading file '{path:?}': {io_error}"),
Self::ParseError{path, toml_error} =>
write!(f,"Unable to parse file as toml '{path:?}':\n{toml_error}"),
}
}
}
impl Error for TomlError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::FileError{io_error, ..} =>
Some(io_error),
Self::ParseError{toml_error, ..} =>
Some(toml_error),
}
}
}