Skip to main content

expr/functions/
mod.rs

1pub mod array;
2pub mod bitwise;
3pub mod collection;
4pub mod convert;
5pub mod json;
6pub mod misc;
7pub mod number;
8pub mod string;
9#[cfg(feature = "temporal")]
10pub mod temporal;
11
12use crate::Result;
13
14use crate::ast::program::Program;
15use crate::{bail, ContextProvider, Environment, Value};
16
17/// Register builtins that report the feature they need instead of not existing.
18///
19/// A builtin whose feature is off is still a builtin the language has: `Unknown function:
20/// fromJSON` sends an author hunting for a typo, when what is missing is a Cargo feature and
21/// only the person who chose the features can fix it. Same contract as the `matches` operator
22/// and method dispatch, which report their own features.
23#[cfg(not(all(feature = "base64", feature = "json", feature = "temporal")))]
24pub(crate) fn add_disabled_functions(
25    env: &mut Environment,
26    feature: &'static str,
27    names: &[&'static str],
28) {
29    for name in names {
30        env.add_function(name, move |call| {
31            bail!(
32                "{}() requires expr-lang's `{feature}` feature",
33                call.ident
34            )
35        });
36    }
37}
38
39pub type Function<'a> = Box<dyn Fn(ExprCall) -> Result<Value> + 'a + Sync + Send>;
40
41pub struct ExprCall<'a, 'b> {
42    pub ident: String,
43    pub args: Vec<Value>,
44    pub predicate: Option<&'a Program>,
45    pub ctx: &'a dyn ContextProvider,
46    pub env: &'a Environment<'b>,
47}
48
49impl Environment<'_> {
50    pub fn eval_func(
51        &self,
52        ctx: &dyn ContextProvider,
53        ident: &str,
54        args: Vec<Value>,
55        predicate: Option<&Program>,
56    ) -> Result<Value> {
57        let call = ExprCall {
58            ident: ident.to_string(),
59            args,
60            predicate,
61            ctx,
62            env: self,
63        };
64        if let Some(f) = self.functions.get(&call.ident) {
65            f(call)
66        } else {
67            bail!("Unknown function: {}", call.ident)
68        }
69    }
70}