1use serde::Deserialize;
2
3use std::fmt;
4use std::fs;
5use std::path::Path;
6use std::path::PathBuf;
7use std::error::Error;
8
9pub fn read_toml_from_file<T>(path: impl AsRef<Path>) -> Result<T,TomlError>
27where T: for<'de> Deserialize<'de> {
28 let text = match fs::read_to_string(&path) {
29 Ok(t) => t,
30 Err(e) => {
31 return Err(TomlError::FileError{
32 path: path.as_ref().into(),
33 io_error: e
34 });
35 }
36 };
37 match toml::from_str(&text) {
38 Ok(t) => Ok(t),
39 Err(e) => {
40 return Err(TomlError::ParseError{
41 path: path.as_ref().into(),
42 toml_error: e
43 });
44 }
45 }
46}
47
48#[derive(Debug)]
52pub enum TomlError {
53
54 FileError{
56 path: PathBuf,
58 io_error: std::io::Error
60 },
61
62 ParseError{
64 path: PathBuf,
66 toml_error: toml::de::Error
68 },
69}
70
71impl fmt::Display for TomlError {
72 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73 match self {
74 Self::FileError{path, io_error} =>
75 write!(f,"Error while reading file '{path:?}': {io_error}"),
76 Self::ParseError{path, toml_error} =>
77 write!(f,"Unable to parse file as toml '{path:?}':\n{toml_error}"),
78 }
79 }
80}
81
82impl Error for TomlError {
83 fn source(&self) -> Option<&(dyn Error + 'static)> {
84 match self {
85 Self::FileError{io_error, ..} =>
86 Some(io_error),
87 Self::ParseError{toml_error, ..} =>
88 Some(toml_error),
89 }
90 }
91}