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#[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]
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 }