use serde_json::Value as Json;
use crate::errors::GraphDDBError;
const ITEMS: &str = "items";
pub fn parse_result_path(path: &str) -> Result<(Vec<String>, String, bool), GraphDDBError> {
if path == "$" || path.is_empty() {
return Err(GraphDDBError::new("root operation has no relation path"));
}
if !path.starts_with("$.") {
return Err(GraphDDBError::new(format!(
"unsupported resultPath '{path}'"
)));
}
let tokens: Vec<String> = path[2..].split('.').map(str::to_string).collect();
if tokens.last().map(String::as_str) == Some(ITEMS) {
if tokens.len() < 2 {
return Err(GraphDDBError::new(format!("malformed resultPath '{path}'")));
}
let write_key = tokens[tokens.len() - 2].clone();
let parent_tokens = tokens[..tokens.len() - 2].to_vec();
return Ok((parent_tokens, write_key, true));
}
let write_key = tokens[tokens.len() - 1].clone();
let parent_tokens = tokens[..tokens.len() - 1].to_vec();
Ok((parent_tokens, write_key, false))
}
pub fn collect_parents_mut<'a>(root: &'a mut Json, parent_tokens: &[String]) -> Vec<&'a mut Json> {
let mut nodes: Vec<&mut Json> = vec![root];
for token in parent_tokens {
let mut next: Vec<&mut Json> = Vec::new();
for node in nodes {
if token == ITEMS {
if let Some(items) = node.get_mut(ITEMS).and_then(Json::as_array_mut) {
for el in items.iter_mut() {
next.push(el);
}
}
} else if let Some(child) = node.get_mut(token) {
if !child.is_null() {
next.push(child);
}
}
}
nodes = next;
}
nodes.into_iter().filter(|n| n.is_object()).collect()
}
pub fn relation_path(op: &Json) -> Vec<String> {
let path = op.get("resultPath").and_then(Json::as_str).unwrap_or("$");
if path == "$" || path.is_empty() {
return vec![];
}
path[2..]
.split('.')
.filter(|t| *t != "items")
.map(str::to_string)
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn parse_connection_and_single() {
assert_eq!(
parse_result_path("$.members.items").unwrap(),
(vec![], "members".to_string(), true)
);
assert_eq!(
parse_result_path("$.groups.items.group").unwrap(),
(
vec!["groups".to_string(), "items".to_string()],
"group".to_string(),
false
)
);
}
#[test]
fn collect_from_connection() {
let mut root = json!({"groups": {"items": [{"a": 1}, {"a": 2}], "cursor": null}});
let parents = collect_parents_mut(&mut root, &["groups".to_string(), "items".to_string()]);
assert_eq!(parents.len(), 2);
}
}