mod args;
mod impls;
use crate::render::FunctionState;
use crate::types::span::Span;
use crate::value::ValueCow;
use crate::{Error, Result, Value};
pub(crate) type DynFunction =
dyn Fn(FunctionState<'_, '_>) -> Result<Value> + Send + Sync + 'static;
pub(crate) fn new<F, R, A>(f: F) -> Box<DynFunction>
where
F: Function<R, A> + Send + Sync + 'static,
R: FunctionReturn,
A: FunctionArgs,
{
Box::new(move |state: FunctionState<'_, '_>| -> Result<Value> {
let args = A::from_state(state)?;
let result = Function::call(&f, args);
FunctionReturn::to_value(result)
})
}
#[cfg_attr(docsrs, doc(cfg(feature = "functions")))]
pub trait Function<R, A>
where
A: FunctionArgs,
{
#[doc(hidden)]
fn call(&self, args: <A as FunctionArgs>::Output<'_>) -> R;
}
#[cfg_attr(docsrs, doc(cfg(feature = "functions")))]
pub trait FunctionArgs {
#[doc(hidden)]
type Output<'args>;
#[doc(hidden)]
fn from_state<'args>(state: FunctionState<'_, 'args>) -> Result<Self::Output<'args>>;
}
#[cfg_attr(docsrs, doc(cfg(feature = "functions")))]
pub trait FunctionArg {
#[doc(hidden)]
type Output<'arg>;
#[doc(hidden)]
fn from_value<'stack, 'arg>(v: &'arg mut ValueCow<'stack>) -> args::Result<Self::Output<'arg>>
where
'stack: 'arg;
}
#[cfg_attr(docsrs, doc(cfg(feature = "functions")))]
pub trait FunctionReturn {
#[doc(hidden)]
fn to_value(self) -> Result<Value>;
}
pub trait FunctionError {
#[doc(hidden)]
fn to_error(self) -> Error;
}
impl<Func, R> Function<R, ()> for Func
where
Func: Fn() -> R,
R: FunctionReturn,
{
#[doc(hidden)]
fn call<'a>(&self, (): ()) -> R {
self()
}
}
impl<Func, R, A> Function<R, (A,)> for Func
where
Func: Fn(A) -> R,
R: FunctionReturn,
A: for<'a> FunctionArg<Output<'a> = A>,
(A,): for<'a> FunctionArgs<Output<'a> = (A,)>,
{
#[doc(hidden)]
fn call<'a>(&self, (a,): (A,)) -> R {
self(a)
}
}
impl<Func, R, A, B> Function<R, (A, B)> for Func
where
Func: Fn(A, B) -> R,
R: FunctionReturn,
A: for<'a> FunctionArg<Output<'a> = A>,
B: for<'a> FunctionArg<Output<'a> = B>,
(A, B): for<'a> FunctionArgs<Output<'a> = (A, B)>,
{
#[doc(hidden)]
fn call<'a>(&self, (a, b): (A, B)) -> R {
self(a, b)
}
}
impl<Func, R, A, B, C> Function<R, (A, B, C)> for Func
where
Func: Fn(A, B, C) -> R,
R: FunctionReturn,
A: for<'a> FunctionArg<Output<'a> = A>,
B: for<'a> FunctionArg<Output<'a> = B>,
C: for<'a> FunctionArg<Output<'a> = C>,
(A, B, C): for<'a> FunctionArgs<Output<'a> = (A, B, C)>,
{
#[doc(hidden)]
fn call<'a>(&self, (a, b, c): (A, B, C)) -> R {
self(a, b, c)
}
}
impl<Func, R, A, B, C, D> Function<R, (A, B, C, D)> for Func
where
Func: Fn(A, B, C, D) -> R,
R: FunctionReturn,
A: for<'a> FunctionArg<Output<'a> = A>,
B: for<'a> FunctionArg<Output<'a> = B>,
C: for<'a> FunctionArg<Output<'a> = C>,
D: for<'a> FunctionArg<Output<'a> = D>,
(A, B, C, D): for<'a> FunctionArgs<Output<'a> = (A, B, C, D)>,
{
#[doc(hidden)]
fn call<'a>(&self, (a, b, c, d): (A, B, C, D)) -> R {
self(a, b, c, d)
}
}
impl<Func, R, A, B, C, D, E> Function<R, (A, B, C, D, E)> for Func
where
Func: Fn(A, B, C, D, E) -> R,
R: FunctionReturn,
A: for<'a> FunctionArg<Output<'a> = A>,
B: for<'a> FunctionArg<Output<'a> = B>,
C: for<'a> FunctionArg<Output<'a> = C>,
D: for<'a> FunctionArg<Output<'a> = D>,
E: for<'a> FunctionArg<Output<'a> = E>,
(A, B, C, D, E): for<'a> FunctionArgs<Output<'a> = (A, B, C, D, E)>,
{
#[doc(hidden)]
fn call<'a>(&self, (a, b, c, d, e): (A, B, C, D, E)) -> R {
self(a, b, c, d, e)
}
}
impl FunctionArgs for () {
type Output<'a> = ();
fn from_state<'args>(state: FunctionState<'_, 'args>) -> Result<Self::Output<'args>> {
let [] = get_args::<0>(state.args)?;
Ok(())
}
}
impl<A> FunctionArgs for (A,)
where
A: FunctionArg,
{
type Output<'a> = (A::Output<'a>,);
fn from_state<'args>(state: FunctionState<'_, 'args>) -> Result<Self::Output<'args>> {
let err = |e, sp| err_expected_arg(e, state.source, state.fname, sp);
let [(a, sa)] = get_args(state.args)?;
let a = A::from_value(a).map_err(|e| err(e, *sa))?;
Ok((a,))
}
}
impl<A, B> FunctionArgs for (A, B)
where
A: FunctionArg,
B: FunctionArg,
{
type Output<'a> = (A::Output<'a>, B::Output<'a>);
fn from_state<'args>(state: FunctionState<'_, 'args>) -> Result<Self::Output<'args>> {
let err = |e, sp| err_expected_arg(e, state.source, state.fname, sp);
let [(a, sa), (b, sb)] = get_args(state.args)?;
let a = A::from_value(a).map_err(|e| err(e, *sa))?;
let b = B::from_value(b).map_err(|e| err(e, *sb))?;
Ok((a, b))
}
}
impl<A, B, C> FunctionArgs for (A, B, C)
where
A: FunctionArg,
B: FunctionArg,
C: FunctionArg,
{
type Output<'a> = (A::Output<'a>, B::Output<'a>, C::Output<'a>);
fn from_state<'args>(state: FunctionState<'_, 'args>) -> Result<Self::Output<'args>> {
let err = |e, sp| err_expected_arg(e, state.source, state.fname, sp);
let [(a, sa), (b, sb), (c, sc)] = get_args(state.args)?;
let a = A::from_value(a).map_err(|e| err(e, *sa))?;
let b = B::from_value(b).map_err(|e| err(e, *sb))?;
let c = C::from_value(c).map_err(|e| err(e, *sc))?;
Ok((a, b, c))
}
}
impl<A, B, C, D> FunctionArgs for (A, B, C, D)
where
A: FunctionArg,
B: FunctionArg,
C: FunctionArg,
D: FunctionArg,
{
type Output<'a> = (A::Output<'a>, B::Output<'a>, C::Output<'a>, D::Output<'a>);
fn from_state<'args>(state: FunctionState<'_, 'args>) -> Result<Self::Output<'args>> {
let err = |e, sp| err_expected_arg(e, state.source, state.fname, sp);
let [(a, sa), (b, sb), (c, sc), (d, sd)] = get_args(state.args)?;
let a = A::from_value(a).map_err(|e| err(e, *sa))?;
let b = B::from_value(b).map_err(|e| err(e, *sb))?;
let c = C::from_value(c).map_err(|e| err(e, *sc))?;
let d = D::from_value(d).map_err(|e| err(e, *sd))?;
Ok((a, b, c, d))
}
}
impl<A, B, C, D, E> FunctionArgs for (A, B, C, D, E)
where
A: FunctionArg,
B: FunctionArg,
C: FunctionArg,
D: FunctionArg,
E: FunctionArg,
{
type Output<'a> = (
A::Output<'a>,
B::Output<'a>,
C::Output<'a>,
D::Output<'a>,
E::Output<'a>,
);
fn from_state<'args>(state: FunctionState<'_, 'args>) -> Result<Self::Output<'args>> {
let err = |e, sp| err_expected_arg(e, state.source, state.fname, sp);
let [(a, sa), (b, sb), (c, sc), (d, sd), (e, se)] = get_args(state.args)?;
let a = A::from_value(a).map_err(|e| err(e, *sa))?;
let b = B::from_value(b).map_err(|e| err(e, *sb))?;
let c = C::from_value(c).map_err(|e| err(e, *sc))?;
let d = D::from_value(d).map_err(|e| err(e, *sd))?;
let e = E::from_value(e).map_err(|e| err(e, *se))?;
Ok((a, b, c, d, e))
}
}
fn get_args<'stack, 'args, const N: usize>(
args: &'args mut [(ValueCow<'stack>, Span)],
) -> Result<&'args mut [(ValueCow<'stack>, Span); N]> {
let n = args.len();
args.try_into()
.map_err(|_| Error::render_plain(format!("function expects {N} arguments, {n} provided")))
}
fn err_expected_arg(err: args::Error, source: &str, fname: &str, span: Span) -> Error {
let msg = match err {
args::Error::Type(exp, got) => {
format!("function `{fname}` expects {exp} argument, found {got}")
}
args::Error::TryFromInt(want, value) => {
format!("function `{fname}` expects {want} argument, but `{value}` is out of range",)
}
};
Error::render(msg, source, span)
}
impl<T> FunctionReturn for T
where
T: Into<Value>,
{
fn to_value(self) -> Result<Value> {
Ok(self.into())
}
}
impl<T, E> FunctionReturn for std::result::Result<T, E>
where
T: Into<Value>,
E: FunctionError,
{
fn to_value(self) -> Result<Value> {
self.map(Into::into).map_err(FunctionError::to_error)
}
}
impl FunctionError for String {
fn to_error(self) -> Error {
Error::function(self)
}
}
impl FunctionError for &str {
fn to_error(self) -> Error {
Error::function(self)
}
}