use serde_json::Value;
use crate::value_helpers::access_path_ref;
use crate::{CompiledNode, ContextStack, DataLogic, Result};
#[inline]
pub fn evaluate_missing(
args: &[CompiledNode],
context: &mut ContextStack,
engine: &DataLogic,
) -> Result<Value> {
let mut missing = Vec::new();
for arg in args {
let path_val = engine.evaluate_node_cow(arg, context)?;
match path_val.as_ref() {
Value::Array(arr) => {
for v in arr {
if let Some(path) = v.as_str()
&& access_path_ref(context.current().data(), path).is_none()
{
missing.push(Value::String(path.to_string()));
}
}
}
Value::String(s) => {
if access_path_ref(context.current().data(), s).is_none() {
missing.push(Value::String(s.clone()));
}
}
_ => {}
}
}
Ok(Value::Array(missing))
}
#[inline]
pub fn evaluate_missing_some(
args: &[CompiledNode],
context: &mut ContextStack,
engine: &DataLogic,
) -> Result<Value> {
if args.len() < 2 {
return Ok(Value::Array(vec![]));
}
let min_present_val = engine.evaluate_node_cow(&args[0], context)?;
let min_present = min_present_val.as_u64().unwrap_or(1) as usize;
let paths_val = engine.evaluate_node_cow(&args[1], context)?;
let mut missing = Vec::new();
let mut present_count = 0;
if let Value::Array(arr) = paths_val.as_ref() {
for v in arr {
if let Some(path) = v.as_str() {
if access_path_ref(context.current().data(), path).is_none() {
missing.push(Value::String(path.to_string()));
} else {
present_count += 1;
if present_count >= min_present {
return Ok(Value::Array(vec![]));
}
}
}
}
}
if present_count >= min_present {
Ok(Value::Array(vec![]))
} else {
Ok(Value::Array(missing))
}
}