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