graphddb_runtime/
relations.rs1use serde_json::Value as Json;
14
15use crate::errors::GraphDDBError;
16
17const ITEMS: &str = "items";
18
19pub fn parse_result_path(path: &str) -> Result<(Vec<String>, String, bool), GraphDDBError> {
21 if path == "$" || path.is_empty() {
22 return Err(GraphDDBError::new("root operation has no relation path"));
23 }
24 if !path.starts_with("$.") {
25 return Err(GraphDDBError::new(format!(
26 "unsupported resultPath '{path}'"
27 )));
28 }
29 let tokens: Vec<String> = path[2..].split('.').map(str::to_string).collect();
30 if tokens.last().map(String::as_str) == Some(ITEMS) {
31 if tokens.len() < 2 {
32 return Err(GraphDDBError::new(format!("malformed resultPath '{path}'")));
33 }
34 let write_key = tokens[tokens.len() - 2].clone();
35 let parent_tokens = tokens[..tokens.len() - 2].to_vec();
36 return Ok((parent_tokens, write_key, true));
37 }
38 let write_key = tokens[tokens.len() - 1].clone();
39 let parent_tokens = tokens[..tokens.len() - 1].to_vec();
40 Ok((parent_tokens, write_key, false))
41}
42
43pub fn collect_parents_mut<'a>(root: &'a mut Json, parent_tokens: &[String]) -> Vec<&'a mut Json> {
47 let mut nodes: Vec<&mut Json> = vec![root];
48 for token in parent_tokens {
49 let mut next: Vec<&mut Json> = Vec::new();
50 for node in nodes {
51 if token == ITEMS {
52 if let Some(items) = node.get_mut(ITEMS).and_then(Json::as_array_mut) {
53 for el in items.iter_mut() {
54 next.push(el);
55 }
56 }
57 } else if let Some(child) = node.get_mut(token) {
58 if !child.is_null() {
59 next.push(child);
60 }
61 }
62 }
63 nodes = next;
64 }
65 nodes.into_iter().filter(|n| n.is_object()).collect()
67}
68
69pub fn relation_path(op: &Json) -> Vec<String> {
72 let path = op.get("resultPath").and_then(Json::as_str).unwrap_or("$");
73 if path == "$" || path.is_empty() {
74 return vec![];
75 }
76 path[2..]
77 .split('.')
78 .filter(|t| *t != "items")
79 .map(str::to_string)
80 .collect()
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86 use serde_json::json;
87
88 #[test]
89 fn parse_connection_and_single() {
90 assert_eq!(
91 parse_result_path("$.members.items").unwrap(),
92 (vec![], "members".to_string(), true)
93 );
94 assert_eq!(
95 parse_result_path("$.groups.items.group").unwrap(),
96 (
97 vec!["groups".to_string(), "items".to_string()],
98 "group".to_string(),
99 false
100 )
101 );
102 }
103
104 #[test]
105 fn collect_from_connection() {
106 let mut root = json!({"groups": {"items": [{"a": 1}, {"a": 2}], "cursor": null}});
107 let parents = collect_parents_mut(&mut root, &["groups".to_string(), "items".to_string()]);
108 assert_eq!(parents.len(), 2);
109 }
110}