1pub use anyhow::Result;
2
3pub trait ConfigParser {
4 fn parse(&mut self, value: toml::Value) -> Result<()>;
5}
6
7pub use config_parser_derive::ConfigParse;
8
9#[macro_export]
10macro_rules! config_parser_impl {
11 ($($t:ty),+) => {
12 $(
13 impl ConfigParser for $t {
14 fn parse(&mut self, value: toml::Value) -> Result<()> {
15 *self = value.try_into::<$t>()?;
16 Ok(())
17 }
18 }
19 )*
20 };
21}
22
23impl<'de, T> ConfigParser for Option<T>
24where
25 T: serde::de::Deserialize<'de>,
26{
27 fn parse(&mut self, value: toml::Value) -> Result<()> {
28 if let Ok(value) = value.try_into::<T>() {
29 *self = Some(value);
30 }
31 Ok(())
32 }
33}
34
35impl<'de, T> ConfigParser for Vec<T>
36where
37 T: serde::de::Deserialize<'de>,
38{
39 fn parse(&mut self, value: toml::Value) -> Result<()> {
40 if let toml::Value::Array(array) = value {
41 let result: Result<Vec<_>> =
42 array.into_iter().map(|e| Ok(e.try_into::<T>()?)).collect();
43 match result {
44 Err(err) => Err(err),
45 Ok(value) => {
46 *self = value;
47 Ok(())
48 }
49 }
50 } else {
51 Err(anyhow::anyhow!(
52 "config parsing error: expect a TOML::Array, receive {:?}",
53 value
54 ))
55 }
56 }
57}
58
59config_parser_impl!(
60 String, usize, u128, u64, u32, u16, u8, isize, i128, i64, i32, i16, i8, f64, f32, bool, char
61);