json_utils/json/
query_for_js_value.rs

1use crate::json::JsValue;
2
3use crate::query::Path;
4use crate::query::PathComponent;
5use crate::query::Query;
6
7impl<'v> Query<'v> for JsValue {
8    type Item = Self;
9    type ItemRef = &'v Self::Item;
10
11    fn lookup<'p, P>(&'v self, path: P) -> Option<Self::ItemRef>
12    where
13        P: Path<'p>,
14    {
15        lookup(self, path.path())
16    }
17
18    fn take<'p, P>(self, path: P) -> (Option<Self>, Option<Self::Item>)
19    where
20        P: Path<'p>,
21    {
22        take(self, path.path())
23    }
24
25    fn insert<'p, P>(&mut self, path: P, insertee: Self::Item) -> Result<(), Self::Item>
26    where
27        P: Path<'p>,
28    {
29        insert(self, path.path(), insertee)
30    }
31}
32
33fn lookup<'v, 'p, P: PathComponent<'p>, I: Iterator<Item = P>>(
34    v: &'v JsValue,
35    mut components: I,
36) -> Option<&'v JsValue> {
37    if let Some(component) = components.next() {
38        match *v {
39            JsValue::Object(ref fields) => fields
40                .get(component.as_str_slice())
41                .and_then(move |child| lookup(child, components)),
42            _ => None,
43        }
44    } else {
45        Some(v)
46    }
47}
48
49fn take<'p, P: PathComponent<'p>, I: Iterator<Item = P>>(
50    v: JsValue,
51    mut components: I,
52) -> (Option<JsValue>, Option<JsValue>) {
53    if let Some(component) = components.next() {
54        match v {
55            JsValue::Object(mut fields) => {
56                let child_key = component.as_str_slice();
57                if let Some(child) = fields.remove(child_key) {
58                    let (child_opt, taken_opt) = take(child, components);
59                    
60                    if let Some(child) = child_opt {
61                        fields.insert(child_key.to_owned(), child);
62                    };
63
64                    if fields.is_empty() {
65                        (None, taken_opt)
66                    } else {
67                        (Some(JsValue::Object(fields)), taken_opt)
68                    }
69                } else {
70                    (Some(JsValue::Object(fields)), None)
71                }
72            }
73            as_is => (Some(as_is), None),
74        }
75    } else {
76        (None, Some(v))
77    }
78}
79
80fn insert<'p, P: PathComponent<'p>, I: Iterator<Item = P>>(
81    v: &mut JsValue,
82    mut components: I,
83    insertee: JsValue,
84) -> Result<(), JsValue> {
85    if let Some(component) = components.next() {
86        match *v {
87            JsValue::Object(ref mut fields) => {
88                let child_key = component.as_str_slice();
89
90                if let Some(ref mut child) = fields.get_mut(child_key) {
91                    insert(child, components, insertee)
92                } else {
93                    let mut child = json!({});
94
95                    let () = insert(&mut child, components, insertee)
96                        .expect("Failed to insert into a newly created ObjectNode");
97
98                    fields.insert(child_key.to_owned(), child);
99                    Ok(())
100                }
101            }
102            _ => Err(insertee),
103        }
104    } else {
105        *v = insertee;
106        Ok(())
107    }
108}