use super::path::Path;
use crate::{
haystack::val::{Dict, Value},
val::{List, Ref},
};
pub trait PathResolver {
fn resolve_for(&self, root: &Dict, path: &Path) -> Value;
fn resolve(&self, path: &Path) -> Value;
fn resolve_ref(&self, reference: &Ref) -> Option<Dict>;
fn resolve_ref_list(&self, ref_list: &List) -> Vec<Dict> {
ref_list
.iter()
.filter_map(|val| {
if let Value::Ref(id) = val {
self.resolve_ref(id)
} else {
None
}
})
.collect::<Vec<Dict>>()
}
}
impl PathResolver for Dict {
fn resolve_for(&self, root: &Dict, path: &Path) -> Value {
if path.is_empty() || root.is_empty() {
Value::Null
} else {
let mut cur_val = root.clone().into();
for segment in path.iter() {
cur_val = match cur_val {
Value::Dict(dict) => dict
.get(&segment.to_string())
.map_or(Value::Null, |v| v.clone()),
_ => Value::Null,
};
if cur_val.is_null() {
break;
}
}
cur_val
}
}
fn resolve(&self, path: &Path) -> Value {
self.resolve_for(self, path)
}
fn resolve_ref(&self, _reference: &Ref) -> Option<Dict> {
None
}
}