expression_engine 0.7.0

An expression engine written in pure rust
Documentation
use crate::define::Result;
use crate::error::Error;
use crate::value::Value;
use once_cell::sync::OnceCell;
use rust_decimal::Decimal;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

pub type InnerFunction = dyn Fn(Vec<Value>) -> Result<Value> + Send + Sync + 'static;

pub struct InnerFunctionManager {
    pub store: &'static Mutex<HashMap<String, Arc<InnerFunction>>>,
}

impl InnerFunctionManager {
    pub fn new() -> Self {
        static STORE: OnceCell<Mutex<HashMap<String, Arc<InnerFunction>>>> = OnceCell::new();
        let store = STORE.get_or_init(|| Mutex::new(HashMap::new()));
        InnerFunctionManager { store: store }
    }

    pub fn init(&mut self) {
        self.register(
            "min",
            Arc::new(|params| {
                let mut min = None;
                for param in params.into_iter() {
                    let num = param.decimal()?;
                    if min.is_none() || num < min.unwrap() {
                        min = Some(num);
                    }
                }
                Ok(Value::Number(min.unwrap()))
            }),
        );

        self.register(
            "max",
            Arc::new(|params| {
                let mut max = None;
                for param in params.into_iter() {
                    let num = param.decimal()?;
                    if max.is_none() || num > max.unwrap() {
                        max = Some(num);
                    }
                }
                Ok(Value::Number(max.unwrap()))
            }),
        );

        self.register(
            "sum",
            Arc::new(|params| {
                let mut ans = Decimal::ZERO;
                for param in params.into_iter() {
                    ans += param.decimal()?;
                }
                Ok(Value::Number(ans))
            }),
        );

        self.register(
            "mul",
            Arc::new(|params| {
                let mut ans = Decimal::ONE;
                for param in params.into_iter() {
                    ans *= param.decimal()?;
                }
                Ok(Value::Number(ans))
            }),
        );
    }

    pub fn register(&mut self, name: &str, f: Arc<InnerFunction>) {
        self.store.lock().unwrap().insert(name.to_string(), f);
    }

    pub fn get(&self, name: &str) -> Result<Arc<InnerFunction>> {
        let binding = self.store.lock().unwrap();
        let ans = binding.get(name);
        if ans.is_none() {
            return Err(Error::InnerFunctionNotRegistered(String::from(name)));
        }
        Ok(ans.unwrap().clone())
    }
}