use std::fmt;
use crate::{
error::EvalexprResultValue,
value::{
numeric_types::{default_numeric_types::DefaultNumericTypes, EvalexprNumericTypes},
Value,
},
};
pub(crate) mod builtin;
trait ClonableFn<NumericTypes: EvalexprNumericTypes = DefaultNumericTypes>
where
Self: Fn(&Value<NumericTypes>) -> EvalexprResultValue<NumericTypes>,
Self: Send + Sync + 'static,
{
fn dyn_clone(&self) -> Box<dyn ClonableFn<NumericTypes>>;
}
impl<F, NumericTypes: EvalexprNumericTypes> ClonableFn<NumericTypes> for F
where
F: Fn(&Value<NumericTypes>) -> EvalexprResultValue<NumericTypes>,
F: Send + Sync + 'static,
F: Clone,
{
fn dyn_clone(&self) -> Box<dyn ClonableFn<NumericTypes>> {
Box::new(self.clone()) as _
}
}
pub struct Function<NumericTypes: EvalexprNumericTypes> {
function: Box<dyn ClonableFn<NumericTypes>>,
}
impl<NumericTypes: EvalexprNumericTypes> Clone for Function<NumericTypes> {
fn clone(&self) -> Self {
Self {
function: self.function.dyn_clone(),
}
}
}
impl<NumericTypes: EvalexprNumericTypes> Function<NumericTypes> {
pub fn new<F>(function: F) -> Self
where
F: Fn(&Value<NumericTypes>) -> EvalexprResultValue<NumericTypes>,
F: Send + Sync + 'static,
F: Clone,
{
Self {
function: Box::new(function) as _,
}
}
pub(crate) fn call(&self, argument: &Value<NumericTypes>) -> EvalexprResultValue<NumericTypes> {
(self.function)(argument)
}
}
impl<NumericTypes: EvalexprNumericTypes> fmt::Debug for Function<NumericTypes> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "Function {{ [...] }}")
}
}
#[allow(dead_code)]
#[doc(hidden)]
trait IsSendAndSync: Send + Sync {}
impl<NumericTypes: EvalexprNumericTypes> IsSendAndSync for Function<NumericTypes> {}