remote_settings/
jexl_filter.rsuse crate::RemoteSettingsContext;
use firefox_versioning::compare::version_compare;
use jexl_eval::Evaluator;
use serde_json::{json, Value};
use thiserror::Error;
#[derive(Error, Debug)]
pub(crate) enum ParseError {
#[error("Evaluation error: {0}")]
EvaluationError(String),
#[error("Invalid result type")]
InvalidResultType,
}
pub struct JexlFilter {
evaluator: Evaluator<'static>,
context: Value,
}
impl JexlFilter {
pub(crate) fn new(context: Option<RemoteSettingsContext>) -> Self {
let env_context = match context {
Some(ctx) => {
let serialized_context =
serde_json::to_value(ctx).expect("Failed to serialize RemoteSettingsContext");
json!({ "env": serialized_context })
}
None => json!({ "env": {} }),
};
Self {
evaluator: Evaluator::new()
.with_transform("versionCompare", |args| Ok(version_compare(args)?)),
context: env_context,
}
}
pub(crate) fn evaluate(&self, filter_expr: &str) -> Result<bool, ParseError> {
if filter_expr.trim().is_empty() {
return Ok(true);
}
let result = self
.evaluator
.eval_in_context(filter_expr, &self.context)
.map_err(|e| {
ParseError::EvaluationError(format!("Failed to evaluate '{}': {}", filter_expr, e))
})?;
result.as_bool().ok_or(ParseError::InvalidResultType)
}
}