use crate::error::{CoreError, Result};
use crate::value::Value;
pub(crate) fn compile_path(field: &str) -> Result<Vec<String>> {
let segments: Vec<String> = field.split('.').map(str::to_owned).collect();
for segment in &segments {
if segment.starts_with('_') {
return Err(CoreError::Filter {
message: format!("Field path segment '{segment}' must not start with '_'"),
});
}
}
Ok(segments)
}
pub(crate) fn resolve<'a>(item: &'a Value, path: &[String]) -> Result<&'a Value> {
let mut current = item;
for segment in path {
current = match current {
Value::Map(map) => map.get(segment).ok_or_else(|| CoreError::FieldNotFound {
field: segment.clone(),
})?,
_ => {
return Err(CoreError::FieldNotFound {
field: segment.clone(),
})
}
};
}
Ok(current)
}
#[must_use]
pub(crate) fn resolve_opt<'a>(item: &'a Value, path: &[String]) -> Option<&'a Value> {
let mut current = item;
for segment in path {
match current {
Value::Map(map) => current = map.get(segment)?,
_ => return None,
}
}
if current.is_null() {
None
} else {
Some(current)
}
}
#[must_use]
pub(crate) fn resolve_present<'a>(item: &'a Value, path: &[String]) -> Option<&'a Value> {
let mut current = item;
for segment in path {
match current {
Value::Map(map) => current = map.get(segment)?,
_ => return None,
}
}
Some(current)
}