use serde_json::Value;
use crate::{CompiledNode, ContextStack, DataLogic, Error, Result};
use std::collections::HashMap;
#[inline]
fn try_last_with_error_context(
arg: &CompiledNode,
last_error: &mut Option<Error>,
context: &mut ContextStack,
engine: &DataLogic,
) -> Result<Value> {
if let Some(Error::Thrown(error_obj)) = last_error.take() {
context.push(error_obj);
let result = engine.evaluate_node(arg, context);
context.pop();
result
} else {
engine.evaluate_node(arg, context)
}
}
#[inline]
pub fn evaluate_try(
args: &[CompiledNode],
context: &mut ContextStack,
engine: &DataLogic,
) -> Result<Value> {
if args.is_empty() {
return Err(Error::InvalidArguments(
"try requires at least one argument".to_string(),
));
}
if args.len() == 1 {
return engine.evaluate_node(&args[0], context);
}
if args.len() == 2 {
match engine.evaluate_node(&args[0], context) {
Ok(result) => return Ok(result),
Err(err) => {
let mut last_error = Some(err);
return try_last_with_error_context(&args[1], &mut last_error, context, engine);
}
}
}
let mut last_error: Option<Error> = None;
let last_idx = args.len() - 1;
for (i, arg) in args.iter().enumerate() {
if i == last_idx {
return try_last_with_error_context(arg, &mut last_error, context, engine);
}
match engine.evaluate_node(arg, context) {
Ok(result) => return Ok(result),
Err(err) => last_error = Some(err),
}
}
match last_error {
Some(err) => Err(err),
None => Err(Error::InvalidArguments(
"try: no arguments provided".to_string(),
)),
}
}
#[inline(never)]
pub fn evaluate_try_traced(
args: &[CompiledNode],
context: &mut ContextStack,
engine: &DataLogic,
collector: &mut crate::trace::TraceCollector,
node_id_map: &HashMap<usize, u32>,
) -> Result<Value> {
if args.is_empty() {
return Err(Error::InvalidArguments(
"try requires at least one argument".to_string(),
));
}
let mut last_error: Option<Error> = None;
for (i, arg) in args.iter().enumerate() {
if i == args.len() - 1 && i > 0 {
if let Some(Error::Thrown(error_obj)) = last_error.take() {
context.push(error_obj);
match engine.evaluate_node_traced(arg, context, collector, node_id_map) {
Ok(result) => {
context.pop();
return Ok(result);
}
Err(new_err) => {
context.pop();
last_error = Some(new_err);
}
}
} else {
match engine.evaluate_node_traced(arg, context, collector, node_id_map) {
Ok(result) => return Ok(result),
Err(err) => last_error = Some(err),
}
}
} else {
match engine.evaluate_node_traced(arg, context, collector, node_id_map) {
Ok(result) => return Ok(result),
Err(err) => last_error = Some(err),
}
}
}
match last_error {
Some(err) => Err(err),
None => Err(Error::InvalidArguments(
"try: no arguments provided".to_string(),
)),
}
}