1use std::marker::PhantomData;23use jrsonnet_gcmodule::Trace;4use jrsonnet_types::{ComplexValType, ValType};56use super::PreparedFuncVal;7use crate::{8 CallLocation, Result, Val,9 function::FuncVal,10 typed::{FromUntyped, IntoUntyped, Typed},11};1213#[derive(Debug, Trace, Clone)]14pub struct NativeFn<D: 'static>(pub(crate) PreparedFuncVal, PhantomData<D>);15macro_rules! impl_native_desc {16 ($i:expr; $($gen:ident)*) => {17 impl<$($gen,)* O> NativeFn<($($gen,)* O,)>18 where19 $($gen: Typed + IntoUntyped,)*20 O: Typed + FromUntyped,21 {22 #[allow(non_snake_case, clippy::too_many_arguments)]23 pub fn call(24 &self,25 $($gen: $gen,)*26 ) -> Result<O> {27 let val = self.0.call(28 CallLocation::native(),29 &[$(IntoUntyped::into_lazy_untyped($gen),)*],30 &[],31 )?;32 O::from_untyped(val)33 }34 }35 impl<$($gen,)* O> Typed for NativeFn<($($gen,)* O,)> {36 const TYPE: &'static ComplexValType = &ComplexValType::Simple(ValType::Func);37 }3839 impl<$($gen,)* O> FromUntyped for NativeFn<($($gen,)* O,)> {40 fn from_untyped(untyped: Val) -> Result<Self> {41 let func = FuncVal::from_untyped(untyped)?;42 Self::try_from(func)43 }44 }45 impl<$($gen,)* O> TryFrom<FuncVal> for NativeFn<($($gen,)* O,)> {46 type Error = crate::Error;47 fn try_from(v: FuncVal) -> Result<Self> {48 Ok(Self(49 PreparedFuncVal::new(v, $i, &[])?,50 PhantomData,51 ))52 }53 }5455 };56 ($i:expr; $($cur:ident)* @ $c:ident $($rest:ident)*) => {57 impl_native_desc!($i; $($cur)*);58 impl_native_desc!($i + 1; $($cur)* $c @ $($rest)*);59 };60 ($i:expr; $($cur:ident)* @) => {61 impl_native_desc!($i; $($cur)*);62 }63}6465impl_native_desc! {66 0; @ A B C D E F G H I J K L67}6869mod native_macro {70 #[macro_export]71 macro_rules! NativeFn {72 (($($t:ty),* $(,)?) -> $res:ty) => {73 NativeFn<($($t,)* $res)>74 }75 }76}77pub use crate::NativeFn;