realme/value/
mod.rs

1mod access;
2mod cast;
3mod des;
4mod ser;
5
6use std::fmt::{
7    Display,
8    Formatter,
9};
10
11use ser::ValueSerializer;
12use serde::{
13    Deserialize,
14    Serialize,
15};
16
17use crate::{
18    Map,
19    Result,
20};
21
22pub type Array = Vec<Value>;
23pub type Table = Map<String, Value>;
24
25/// Representation of a TOML value.
26#[derive(Default, PartialEq, Clone, Debug)]
27pub enum Value {
28    #[default]
29    Null,
30    Boolean(bool),
31    Integer(i64),
32    Float(f64),
33    String(String),
34    Array(Array),
35    Table(Table),
36}
37
38impl Display for Value {
39    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40        match self {
41            Self::Null => write!(f, "null"),
42            Self::Boolean(b) => write!(f, "{b}"),
43            Self::Integer(i) => write!(f, "{i}"),
44            Self::Float(fl) => write!(f, "{fl}"),
45            Self::String(s) => write!(f, "{s}"),
46            Self::Array(a) => write!(f, "{a:?}"),
47            Self::Table(t) => write!(f, "{t:?}"),
48        }
49    }
50}
51
52impl Value {
53    pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
54        T::deserialize(self).map_err(std::convert::Into::into)
55    }
56
57    pub fn try_serialize<T: Serialize>(from: &T) -> Result<Self> {
58        from.serialize(ValueSerializer)
59            .map_err(std::convert::Into::into)
60    }
61
62    pub const fn value_type(&self) -> &'static str {
63        match self {
64            Self::Null => "null",
65            Self::Boolean(_) => "boolean",
66            Self::Integer(_) => "integer",
67            Self::Float(_) => "float",
68            Self::String(_) => "string",
69            Self::Array(_) => "array",
70            Self::Table(_) => "table",
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    pub fn prepare_value() -> Value {
80        Value::Table(Table::from_iter(vec![(
81            "a".to_string(),
82            Value::Table(Table::from_iter(vec![(
83                "b".to_string(),
84                Value::Array(vec![
85                    Value::Integer(1),
86                    Value::Integer(2),
87                    Value::Integer(3),
88                ]),
89            )])),
90        )]))
91    }
92
93    #[test]
94    fn test_get() {
95        let value = prepare_value();
96        assert_eq!(
97            value.get("a.b"),
98            Some(&Value::Array(vec![
99                Value::Integer(1),
100                Value::Integer(2),
101                Value::Integer(3)
102            ]))
103        );
104        assert_eq!(value.get("a.b[0]"), Some(&Value::Integer(1)));
105        assert_eq!(value.get("a.b[3]"), None);
106        assert_eq!(value.get("a.b[-1]"), Some(&Value::Integer(3)));
107        assert_eq!(value.get("a.b[-4]"), None);
108        assert_eq!(value.get("a.c"), None);
109    }
110
111    #[test]
112    fn test_set() -> anyhow::Result<()> {
113        let mut value = Value::Table(Table::new());
114        value.set(
115            "b",
116            Value::Array(vec![
117                Value::Integer(1),
118                Value::Integer(2),
119                Value::Integer(3),
120            ]),
121        )?;
122        assert_eq!(
123            value.get("b"),
124            Some(&Value::Array(vec![
125                Value::Integer(1),
126                Value::Integer(2),
127                Value::Integer(3)
128            ]))
129        );
130        value.set("b[0]", Value::Integer(6))?;
131        assert_eq!(value.get("b[0]"), Some(&Value::Integer(6)));
132        value.set(
133            "a.b",
134            Value::Array(vec![
135                Value::Integer(1),
136                Value::Integer(2),
137                Value::Integer(3),
138            ]),
139        )?;
140        value.set("a.b[0]", Value::Integer(9))?;
141        assert_eq!(value.get("a.b[0]"), Some(&Value::Integer(9)));
142        Ok(())
143    }
144
145    // #[test]
146    // fn test_replace_value() {
147    //     let value = Value::Table(Table::from_iter(vec![(
148    //         "a".to_string(),
149    //         Value::String("{{env}}".to_string()),
150    //     )]));
151    //     assert_eq!(
152    //         Value::replace_value(
153    //             "{{env}}",
154    //             &Value::String("hello".to_string()),
155    //             value
156    //         )
157    //         ?,
158    //         Value::Table(Table::from_iter(vec![(
159    //             "a".to_string(),
160    //             Value::String("hello".to_string()),
161    //         )]))
162    //     );
163    // }
164
165    #[test]
166    fn test_get_mut() -> anyhow::Result<()> {
167        let mut value = Value::Table(Table::new());
168        value.set("a", Value::Integer(42))?;
169        if let Some(v) = value.get_mut("a") {
170            *v = Value::Integer(43);
171        }
172        assert_eq!(value.get("a"), Some(&Value::Integer(43)));
173        Ok(())
174    }
175
176    #[test]
177    fn test_chain_get() {
178        let value = prepare_value();
179        assert_eq!(
180            value.get("a").and_then(|b| b.get("b")),
181            Some(&Value::Array(vec![
182                Value::Integer(1),
183                Value::Integer(2),
184                Value::Integer(3),
185            ]))
186        );
187    }
188
189    #[test]
190    fn test_chain_set() -> anyhow::Result<()> {
191        let mut value = Value::Table(Table::new());
192        value
193            .set("a", Value::Integer(42))?
194            .set("b", Value::Integer(43))?;
195        assert_eq!(value.get("a"), Some(&Value::Integer(42)));
196        assert_eq!(value.get("b"), Some(&Value::Integer(43)));
197        Ok(())
198    }
199
200    #[test]
201    fn test_get_with_index() {
202        let value = prepare_value();
203        assert_eq!(
204            value
205                .get("a")
206                .and_then(|b| b.get("b"))
207                .and_then(|c| c.get(0)),
208            Some(&Value::Integer(1))
209        );
210    }
211
212    #[test]
213    fn test_get_as() {
214        let value = Value::Table(Table::from_iter(vec![(
215            "a".to_string(),
216            Value::String("42".to_string()),
217        )]));
218        let res: Option<i32> = value.get_as("a");
219        assert_eq!(res, Some(42));
220    }
221
222    #[test]
223    fn test_and_set() -> anyhow::Result<()> {
224        let mut value = Value::Table(Table::new());
225        value.set("a", Value::Table(Table::new()))?;
226        value.set("a.b", Value::Integer(42))?;
227        assert_eq!(
228            value.get("a").and_then(|v| v.get("b")),
229            Some(&Value::Integer(42))
230        );
231        value.set("a.b", Value::Integer(43))?;
232        assert_eq!(
233            value.get("a").and_then(|v| v.get("b")),
234            Some(&Value::Integer(43))
235        );
236        value
237            .get_mut("a")
238            .ok_or(anyhow::anyhow!("a not found"))?
239            .set("b", Value::Integer(44))?;
240        assert_eq!(
241            value.get("a").and_then(|v| v.get("b")),
242            Some(&Value::Integer(44))
243        );
244        let mut value = prepare_value();
245        value
246            .get_mut("a")
247            .ok_or(anyhow::anyhow!("a not found"))?
248            .get_mut("b")
249            .ok_or(anyhow::anyhow!("b not found"))?
250            .set(0, Value::Integer(10))?;
251        assert_eq!(
252            value.get("a").and_then(|v| v.get("b")),
253            Some(&Value::Array(vec![
254                Value::Integer(10),
255                Value::Integer(2),
256                Value::Integer(3),
257            ]))
258        );
259        Ok(())
260    }
261
262    #[test]
263    fn test_merge() {
264        let mut a_map = Map::new();
265        a_map.insert("name".to_string(), Value::String("Tom".to_string()));
266        a_map.insert(
267            "dob".to_string(),
268            Value::String("1979-05-27T07:32:00Z".to_string()),
269        );
270        let mut nested = Map::new();
271        nested
272            .insert("city".to_string(), Value::String("New York".to_string()));
273        a_map.insert("address".to_string(), Value::Table(nested));
274
275        let mut a = Value::Table(a_map);
276
277        let mut b_map = Map::new();
278        b_map.insert("name".to_string(), Value::String("Jasper".to_string()));
279        let mut nested = Map::new();
280        nested.insert(
281            "city".to_string(),
282            Value::String("San Francisco".to_string()),
283        );
284        nested.insert("zip".to_string(), Value::String("94105".to_string()));
285        b_map.insert("address".to_string(), Value::Table(nested));
286
287        let b = Value::Table(b_map);
288
289        a.merge(&b);
290        eprintln!("a: {a:#?}");
291        eprintln!("b: {b:#?}");
292
293        if let Value::Table(merged_map) = a {
294            assert_eq!(
295                merged_map.get("name"),
296                Some(&Value::String("Jasper".to_string()))
297            );
298            assert_eq!(
299                merged_map.get("dob"),
300                Some(&Value::String("1979-05-27T07:32:00Z".to_string()))
301            );
302            if let Some(Value::Table(address)) = merged_map.get("address") {
303                assert_eq!(
304                    address.get("city"),
305                    Some(&Value::String("San Francisco".to_string()))
306                );
307                assert_eq!(
308                    address.get("zip"),
309                    Some(&Value::String("94105".to_string()))
310                );
311            } else {
312                panic!("Expected nested address table");
313            }
314        } else {
315            panic!("Expected merged result to be a table");
316        }
317    }
318
319    // #[test]
320    // fn test_set_with_key() {
321    //     let mut value = Value::Table(Table::new());
322    //     value.set("a", Value::Table(Table::new()));
323    //     value.set("a.b", Value::Integer(42));
324    //     value.set("a.c", Value::Integer(42));
325    //     assert_eq!(
326    //         value.get("a").and_then(|v| v.get("b")),
327    //         Some(Value::Integer(42))
328    //     );
329    //     assert_eq!(
330    //         value.get("a").and_then(|v| v.get("c")),
331    //         Some(Value::Integer(42))
332    //     );
333    //     value.with("a", |a| {
334    //         a.set("c", Value::Integer(43)).set("b", Value::Integer(44));
335    //     });
336    //     assert_eq!(
337    //         value.get("a").and_then(|v| v.get("b")),
338    //         Some(Value::Integer(44))
339    //     );
340    //     assert_eq!(
341    //         value.get("a").and_then(|v| v.get("c")),
342    //         Some(Value::Integer(43))
343    //     );
344    // }
345}