remote_settings/
jexl_filter.rs1use crate::RemoteSettingsContext;
6use firefox_versioning::compare::version_compare;
7use jexl_eval::Evaluator;
8use serde_json::{json, Value};
9use thiserror::Error;
10
11#[derive(Error, Debug)]
12pub(crate) enum ParseError {
13 #[error("Evaluation error: {0}")]
14 EvaluationError(String),
15 #[error("Invalid result type")]
16 InvalidResultType,
17}
18
19pub struct JexlFilter {
21 evaluator: Evaluator<'static>,
23 context: Value,
25}
26
27impl JexlFilter {
28 pub(crate) fn new(context: Option<RemoteSettingsContext>) -> Self {
31 let env_context = match context {
32 Some(ctx) => json!({ "env": ctx.into_env() }),
33 None => json!({ "env": {} }),
34 };
35
36 Self {
37 evaluator: Evaluator::new()
38 .with_transform("versionCompare", |args| Ok(version_compare(args)?)),
39 context: env_context,
40 }
41 }
42
43 pub(crate) fn evaluate(&self, filter_expr: &str) -> Result<bool, ParseError> {
46 if filter_expr.trim().is_empty() {
47 return Ok(true);
48 }
49
50 let result = self
51 .evaluator
52 .eval_in_context(filter_expr, &self.context)
53 .map_err(|e| {
54 ParseError::EvaluationError(format!("Failed to evaluate '{}': {}", filter_expr, e))
55 })?;
56
57 result.as_bool().ok_or(ParseError::InvalidResultType)
58 }
59}