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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
use std::fmt; use crate::query::Path; use crate::query::PathComponent; use crate::query::Query; use super::SchemaNode; use super::ValidNode; #[derive(Debug, Clone, PartialEq)] pub struct QueryNode<T: fmt::Debug + Clone + PartialEq> { pub schema: T, pub is_required: bool, } impl<'v> Query<'v> for SchemaNode { type Item = QueryNode<SchemaNode>; type ItemRef = QueryNode<&'v SchemaNode>; fn lookup<'p, P>(&'v self, path: P) -> Option<Self::ItemRef> where P: Path<'p>, { lookup(self, true, path.path()) } fn take<'p, P>(self, path: P) -> (Option<Self>, Option<Self::Item>) where P: Path<'p>, { take(self, true, 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 SchemaNode, is_required: bool, mut components: I, ) -> Option<QueryNode<&'v SchemaNode>> { if let Some(component) = components.next() { if let SchemaNode::ValidNode(ValidNode::ObjectNode(ref object_node)) = *v { let child_key = component.as_str_slice(); let child_is_required = object_node.required.contains(child_key); object_node .properties .get(child_key) .and_then(move |ref child| lookup(child, child_is_required, components)) } else { None } } else { let qn = QueryNode { is_required, schema: v, }; Some(qn) } } fn take<'v, 'p, P: PathComponent<'p>, I: Iterator<Item = P>>( v: SchemaNode, is_required: bool, mut components: I, ) -> (Option<SchemaNode>, Option<QueryNode<SchemaNode>>) { if let Some(component) = components.next() { match v { SchemaNode::ValidNode(ValidNode::ObjectNode(mut object_node)) => { let child_key = component.as_str_slice(); if let Some(child) = object_node.properties.remove(child_key) { let child_is_required = object_node.required.contains(child_key); let (child_opt, taken_opt) = take(child, child_is_required, components); if let Some(child) = child_opt { object_node.properties.insert(child_key.to_owned(), child); }; (Some(object_node.into()), taken_opt) } else { (Some(object_node.into()), None) } } as_is => (Some(as_is), None), } } else { let qn = QueryNode { is_required, schema: v, }; (None, Some(qn)) } } fn insert<'v, 'p, P: PathComponent<'p>, I: Iterator<Item = P>>( v: &'v mut SchemaNode, mut components: I, insertee: QueryNode<SchemaNode>, ) -> Result<(), QueryNode<SchemaNode>> { if let Some(component) = components.next() { match *v { SchemaNode::ValidNode(ValidNode::ObjectNode(ref mut object_node)) => { let child_key = component.as_str_slice(); if let Some(ref mut child) = object_node.properties.get_mut(child_key) { insert(child, components, insertee) } else { let mut child = SchemaNode::object().into(); let () = insert(&mut child, components, insertee) .expect("Failed to insert into a newly created node"); object_node.properties.insert(child_key.to_owned(), child); Ok(()) } } _ => Err(insertee), } } else { *v = insertee.schema; Ok(()) } }