rquickjs_core/value/function/
into_func.rs

1use super::{FromParams, IntoJsFunc, ParamRequirement, Params};
2use crate::{
3    function::types::{MutFn, OnceFn},
4    result::{BorrowError, Error},
5    IntoJs, Result, Value,
6};
7
8#[cfg(feature = "futures")]
9use crate::{function::types::Async, promise::Promised};
10#[cfg(feature = "futures")]
11use std::future::Future;
12
13macro_rules! impl_to_js_function {
14    ($($t:ident),*$(,)?) => {
15        impl<'js, R, Fun $(,$t)*> IntoJsFunc<'js, ($($t,)*)> for Fun
16        where
17            Fun: Fn($($t),*) -> R + 'js,
18            ($($t,)*): FromParams<'js> + 'js,
19            R: IntoJs<'js> + 'js,
20        {
21
22            fn param_requirements() -> ParamRequirement {
23                <($($t,)*)>::param_requirements()
24            }
25
26            #[allow(non_snake_case)]
27            fn call(&self, params: Params<'_, 'js>) -> Result<Value<'js>> {
28                let ctx = params.ctx().clone();
29                let ($($t,)*) = <($($t,)*)>::from_params(&mut params.access())?;
30                let r = (self)($($t),*);
31                r.into_js(&ctx)
32            }
33        }
34
35        #[cfg(feature = "futures")]
36        impl<'js, R, Fun, Fut $(,$t)*> IntoJsFunc<'js, ($($t,)*)> for Async<Fun>
37        where
38            Fun: Fn($($t),*) -> Fut + 'js,
39            ($($t,)*): FromParams<'js> + 'js,
40            Fut: Future<Output = R> + 'js,
41            R: IntoJs<'js> + 'js,
42        {
43
44            fn param_requirements() -> ParamRequirement {
45                <($($t,)*)>::param_requirements()
46            }
47
48            #[allow(non_snake_case)]
49            fn call(&self, params: Params<'_, 'js>) -> Result<Value<'js>> {
50                let ctx = params.ctx().clone();
51                let ($($t,)*) = <($($t,)*)>::from_params(&mut params.access())?;
52                let fut = (self.0)($($t),*);
53                Promised(fut).into_js(&ctx)
54            }
55        }
56
57
58        impl<'js, R, Fun $(,$t)*> IntoJsFunc<'js, ($($t,)*)> for MutFn<Fun>
59        where
60            Fun: FnMut($($t),*) -> R + 'js,
61            ($($t,)*): FromParams<'js> + 'js,
62            R: IntoJs<'js> + 'js,
63        {
64
65            fn param_requirements() -> ParamRequirement {
66                <($($t,)*)>::param_requirements()
67            }
68
69            #[allow(non_snake_case)]
70            fn call(&self, params: Params<'_, 'js>) -> Result<Value<'js>> {
71                let ctx = params.ctx().clone();
72                let ($($t,)*) = <($($t,)*)>::from_params(&mut params.access())?;
73                let mut lock = self.0.try_borrow_mut().map_err(|_| Error::FunctionBorrow(BorrowError::AlreadyBorrowed))?;
74                let r = (lock)($($t),*);
75                r.into_js(&ctx)
76            }
77        }
78
79        #[cfg(feature = "futures")]
80        impl<'js, R, Fun, Fut $(,$t)*> IntoJsFunc<'js, ($($t,)*)> for Async<MutFn<Fun>>
81        where
82            Fun: FnMut($($t),*) -> Fut + 'js,
83            ($($t,)*): FromParams<'js> + 'js,
84            Fut: Future<Output = R> + 'js,
85            R: IntoJs<'js> + 'js,
86        {
87
88            fn param_requirements() -> ParamRequirement {
89                <($($t,)*)>::param_requirements()
90            }
91
92            #[allow(non_snake_case)]
93            fn call(&self, params: Params<'_, 'js>) -> Result<Value<'js>> {
94                let ctx = params.ctx().clone();
95                let ($($t,)*) = <($($t,)*)>::from_params(&mut params.access())?;
96                let mut lock = self.0.0.try_borrow_mut().map_err(|_| Error::FunctionBorrow(BorrowError::AlreadyBorrowed))?;
97                let fut = (lock)($($t),*);
98                Promised(fut).into_js(&ctx)
99            }
100        }
101
102        impl<'js, R, Fun $(,$t)*> IntoJsFunc<'js, ($($t,)*)> for OnceFn<Fun>
103        where
104            Fun: FnOnce($($t),*) -> R + 'js,
105            ($($t,)*): FromParams<'js> + 'js,
106            R: IntoJs<'js> + 'js,
107        {
108
109            fn param_requirements() -> ParamRequirement {
110                <($($t,)*)>::param_requirements()
111            }
112
113            #[allow(non_snake_case)]
114            fn call(&self, params: Params<'_, 'js>) -> Result<Value<'js>> {
115                let ctx = params.ctx().clone();
116                let ($($t,)*) = <($($t,)*)>::from_params(&mut params.access())?;
117                let lock = self.0.take().ok_or(Error::FunctionBorrow(BorrowError::AlreadyUsed))?;
118                let r = (lock)($($t),*);
119                r.into_js(&ctx)
120            }
121        }
122
123        #[cfg(feature = "futures")]
124        impl<'js, R, Fun, Fut $(,$t)*> IntoJsFunc<'js, ($($t,)*)> for Async<OnceFn<Fun>>
125        where
126            Fun: FnOnce($($t),*) -> Fut + 'js,
127            ($($t,)*): FromParams<'js> + 'js,
128            Fut: Future<Output = R> + 'js,
129            R: IntoJs<'js> + 'js,
130        {
131
132            fn param_requirements() -> ParamRequirement {
133                <($($t,)*)>::param_requirements()
134            }
135
136            #[allow(non_snake_case)]
137            fn call(&self, params: Params<'_, 'js>) -> Result<Value<'js>> {
138                let ctx = params.ctx().clone();
139                let ($($t,)*) = <($($t,)*)>::from_params(&mut params.access())?;
140                let lock = self.0.0.take().ok_or(Error::FunctionBorrow(BorrowError::AlreadyUsed))?;
141                let fut = (lock)($($t),*);
142                Promised(fut).into_js(&ctx)
143            }
144        }
145    };
146}
147
148impl_to_js_function!();
149impl_to_js_function!(A);
150impl_to_js_function!(A, B);
151impl_to_js_function!(A, B, C);
152impl_to_js_function!(A, B, C, D);
153impl_to_js_function!(A, B, C, D, E);
154impl_to_js_function!(A, B, C, D, E, F);
155impl_to_js_function!(A, B, C, D, E, F, G);
156impl_to_js_function!(A, B, C, D, E, F, G, H);