1use std::collections::HashMap;
2use std::error::Error;
3use std::path::PathBuf;
4
5use log::LevelFilter;
6use serde::Deserialize;
7use toml::Value;
8
9pub trait SerdeReplace {
10 fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>>;
11}
12
13#[macro_export]
14macro_rules! impl_replace {
15 ($($ty:ty),*$(,)*) => {
16 $(
17 impl SerdeReplace for $ty {
18 fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>> {
19 replace_simple(self, value)
20 }
21 }
22 )*
23 };
24}
25
26#[rustfmt::skip]
27impl_replace!(
28 usize, u8, u16, u32, u64, u128,
29 isize, i8, i16, i32, i64, i128,
30 f32, f64,
31 bool,
32 char,
33 String,
34 PathBuf,
35 LevelFilter,
36);
37
38fn replace_simple<'de, D>(data: &mut D, value: Value) -> Result<(), Box<dyn Error>>
39where
40 D: Deserialize<'de>,
41{
42 *data = D::deserialize(value)?;
43
44 Ok(())
45}
46
47impl<'de, T: Deserialize<'de>> SerdeReplace for Vec<T> {
48 fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>> {
49 replace_simple(self, value)
50 }
51}
52
53impl<'de, T: SerdeReplace + Deserialize<'de>> SerdeReplace for Option<T> {
54 fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>> {
55 match self {
56 Some(inner) => inner.replace(value),
57 None => replace_simple(self, value),
58 }
59 }
60}
61
62impl<'de, T: Deserialize<'de>> SerdeReplace for HashMap<String, T> {
63 fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>> {
64 let hashmap: HashMap<String, T> = Self::deserialize(value)?;
66
67 for (key, value) in hashmap {
69 self.insert(key, value);
70 }
71
72 Ok(())
73 }
74}