1 use super::{PathComponent, PathIter, Value};
2 use std::collections::BTreeMap;
3 
4 /// Returns a reference to a field value specified by the given path.
get<'a>(fields: &'a BTreeMap<String, Value>, path: &str) -> Option<&'a Value>5 pub fn get<'a>(fields: &'a BTreeMap<String, Value>, path: &str) -> Option<&'a Value> {
6     let mut path_iter = PathIter::new(path);
7 
8     match path_iter.next() {
9         Some(PathComponent::Key(key)) => match fields.get(&key) {
10             None => None,
11             Some(value) => get_value(value, path_iter),
12         },
13         _ => None,
14     }
15 }
16 
get_value<I>(mut value: &Value, mut path_iter: I) -> Option<&Value> where I: Iterator<Item = PathComponent>,17 fn get_value<I>(mut value: &Value, mut path_iter: I) -> Option<&Value>
18 where
19     I: Iterator<Item = PathComponent>,
20 {
21     loop {
22         match (path_iter.next(), value) {
23             (None, _) => return Some(value),
24             (Some(PathComponent::Key(ref key)), Value::Map(map)) => match map.get(key) {
25                 None => return None,
26                 Some(nested_value) => {
27                     value = nested_value;
28                 }
29             },
30             (Some(PathComponent::Index(index)), Value::Array(array)) => match array.get(index) {
31                 None => return None,
32                 Some(nested_value) => {
33                     value = nested_value;
34                 }
35             },
36             _ => return None,
37         }
38     }
39 }
40 
41 #[cfg(test)]
42 mod test {
43     use super::super::test::fields_from_json;
44     use super::*;
45     use serde_json::json;
46 
47     #[test]
get_simple()48     fn get_simple() {
49         let fields = fields_from_json(json!({
50             "field": 123
51         }));
52         assert_eq!(get(&fields, "field"), Some(&Value::Integer(123)));
53     }
54 
55     #[test]
get_nested()56     fn get_nested() {
57         let fields = fields_from_json(json!({
58             "a": {
59                 "b": {
60                     "c": 5
61                 },
62                 "d": 4,
63                 "array": [null, 3, {
64                     "x": 1
65                 }, [2]]
66             }
67         }));
68         let queries = [
69             ("a.b.c", Some(Value::Integer(5))),
70             ("a.d", Some(Value::Integer(4))),
71             ("a.array[1]", Some(Value::Integer(3))),
72             ("a.array[2].x", Some(Value::Integer(1))),
73             ("a.array[3][0]", Some(Value::Integer(2))),
74             ("a.array[3][1]", None),
75             ("a.x", None),
76             ("z", None),
77             (".123", None),
78             ("", None),
79         ];
80 
81         for (query, expected) in queries.iter() {
82             assert_eq!(get(&fields, query), expected.as_ref(), "{}", query);
83         }
84     }
85 }
86