toml_input/
toml_input.rs

1use std::path::PathBuf;
2
3use crate::{
4    Schema, TomlContent, TomlValue, Value,
5    error::Error,
6    schema::{Meta, PrimSchema},
7    value::{ArrayValue, PrimValue},
8};
9use serde::Serialize;
10
11pub trait TomlInput: Serialize + Sized {
12    fn schema() -> Result<Schema, Error>;
13    fn into_value(self) -> Result<Value, Error>;
14    fn schema_to_string() -> Result<String, Error> {
15        let schema = Self::schema()?;
16        let sections = schema.flatten();
17        let mut content = TomlContent { sections };
18        content.config_commented(false);
19        content.render()
20    }
21    fn into_string(self) -> Result<String, Error> {
22        let schema = Self::schema()?;
23        let sections = schema.flatten();
24        let mut content = TomlContent { sections };
25        let value = self.into_value()?;
26        content.merge_value(value);
27        content.render()
28    }
29    fn into_content(self) -> Result<TomlContent, Error> {
30        let schema = Self::schema()?;
31        let sections = schema.flatten();
32        let mut content = TomlContent { sections };
33        let value = self.into_value()?;
34        content.merge_value(value);
35        Ok(content)
36    }
37}
38
39macro_rules! impl_type_info_primary {
40    ($t:ty, $name:expr) => {
41        impl TomlInput for $t {
42            fn schema() -> Result<Schema, Error> {
43                let default = <$t as Default>::default();
44                let raw = TomlValue::try_from(default)?;
45                let mut meta = Meta::default();
46                meta.inner_type = $name.to_string();
47                meta.inner_default = PrimValue::new(raw);
48                let data = PrimSchema {
49                    meta,
50                    ..Default::default()
51                };
52                Ok(Schema::Prim(data))
53            }
54            fn into_value(self) -> Result<Value, Error> {
55                let raw = TomlValue::try_from(self)?;
56                Ok(Value::new_prim(raw))
57            }
58        }
59    };
60}
61
62impl_type_info_primary!(bool, "bool");
63impl_type_info_primary!(String, "string");
64impl_type_info_primary!(i8, "i8");
65impl_type_info_primary!(i16, "i16");
66impl_type_info_primary!(i32, "i32");
67impl_type_info_primary!(i64, "i64");
68impl_type_info_primary!(isize, "isize");
69impl_type_info_primary!(u8, "u8");
70impl_type_info_primary!(u16, "u16");
71impl_type_info_primary!(u32, "u32");
72impl_type_info_primary!(u64, "u64");
73impl_type_info_primary!(usize, "usize");
74impl_type_info_primary!(f32, "f32");
75impl_type_info_primary!(f64, "f64");
76impl_type_info_primary!(PathBuf, "path");
77
78impl<T: TomlInput> TomlInput for Option<T> {
79    fn schema() -> Result<Schema, Error> {
80        let mut schema = T::schema()?;
81        schema.set_wrap_type("Option".to_string());
82        Ok(schema)
83    }
84    fn into_value(self) -> Result<Value, Error> {
85        if let Some(item) = self {
86            item.into_value()
87        } else {
88            Ok(Value::Prim(PrimValue::default()))
89        }
90    }
91}
92
93impl<T: TomlInput> TomlInput for Vec<T> {
94    fn schema() -> Result<Schema, Error> {
95        let mut schema = T::schema()?;
96        schema.set_wrap_type("Vec".to_string());
97        schema.meta_mut().is_array = true;
98        Ok(schema)
99    }
100    fn into_value(self) -> Result<Value, Error> {
101        let schema = T::schema()?;
102        let mut values = Vec::new();
103        let mut as_prim = schema.is_prim();
104        for item in self {
105            let value = item.into_value()?;
106            if as_prim || value.is_prim() || value.is_array() {
107                as_prim = true;
108                let prim = value.into_prim();
109                values.push(Value::Prim(prim));
110            } else {
111                values.push(value)
112            }
113        }
114        let array = ArrayValue { values };
115        if as_prim {
116            Ok(Value::Prim(array.into_prim()))
117        } else {
118            Ok(Value::Array(array))
119        }
120    }
121}