use crate::value::Value;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PropertyPath {
root: String,
sub_path: Vec<String>,
}
impl PropertyPath {
pub fn from_path(path: &ankql::ast::PathExpr) -> Self {
let steps = &path.steps;
Self { root: steps[0].clone(), sub_path: steps[1..].to_vec() }
}
pub fn root(&self) -> &str { &self.root }
pub fn is_simple(&self) -> bool { self.sub_path.is_empty() }
pub fn extract_value<E: super::AbstractEntity>(&self, entity: &E) -> Option<Value> {
let root_value = E::value(entity, &self.root)?;
if self.sub_path.is_empty() {
Some(root_value)
} else {
match root_value {
Value::Json(json) => {
let mut current = &json;
for key in &self.sub_path {
current = current.get(key)?;
}
Some(Value::Json(current.clone()))
}
Value::Binary(bytes) => {
let json: serde_json::Value = serde_json::from_slice(&bytes).ok()?;
let mut current = &json;
for key in &self.sub_path {
current = current.get(key)?;
}
Some(Value::Json(current.clone()))
}
_ => None, }
}
}
}
impl From<&str> for PropertyPath {
fn from(val: &str) -> Self { PropertyPath { root: val.to_string(), sub_path: Vec::new() } }
}