mod ast;
pub mod builtins;
mod eval;
mod parser;
use rayon::prelude::*;
use simd_json::OwnedValue as Value;
use crate::error::{EvalError, FilterError, ParseError};
pub fn parse_check(filter_text: &str) -> Result<(), ParseError> {
if filter_text.trim().is_empty() {
return Err(ParseError {
message: "expected filter expression".to_string(),
position: 0,
});
}
parser::parse(filter_text).map(|_| ())
}
const PARALLEL_THRESHOLD: usize = 10_000;
pub fn evaluate_all(filter_text: &str, inputs: &[Value]) -> Result<Vec<Value>, FilterError> {
if filter_text.trim().is_empty() {
return Err(FilterError::Parse(ParseError {
message: "expected filter expression".to_string(),
position: 0,
}));
}
let filter = parser::parse(filter_text)?;
if inputs.len() >= PARALLEL_THRESHOLD {
let results: Result<Vec<Vec<Value>>, EvalError> = inputs
.par_iter()
.map(|input| eval::eval(&filter, input))
.collect();
match results {
Ok(value_vecs) => Ok(value_vecs.into_iter().flatten().collect()),
Err(e) => Err(FilterError::Eval(e)),
}
} else {
let mut all_results = Vec::new();
for input in inputs {
match eval::eval(&filter, input) {
Ok(values) => all_results.extend(values),
Err(e) => {
return Err(FilterError::Eval(e));
}
}
}
Ok(all_results)
}
}
#[allow(dead_code)]
pub fn evaluate(filter_text: &str, input: &Value) -> Result<Vec<Value>, FilterError> {
evaluate_all(filter_text, std::slice::from_ref(input))
}
#[cfg(test)]
mod error_position_tests {
use super::*;
use simd_json::json;
#[test]
fn test_sort_by_error_position() {
let filter_text = "[.[].name] | .[] | {name: .} | sort_by(.name)";
let input = json!([{"name": "alice"}, {"name": "bob"}]);
let result = evaluate_all(filter_text, &[input]);
match result {
Err(FilterError::Eval(e)) => {
let pos = e.position();
println!("Error position: {}", pos);
println!("Filter text from position: '{}'", &filter_text[pos..]);
assert!(pos >= 31, "Expected position >= 31, got {}", pos);
}
Err(FilterError::Parse(e)) => {
panic!("Unexpected parse error: {:?}", e);
}
Ok(_) => {
panic!("Expected error but got success");
}
}
}
}