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