rquickjs_core/value/function/
into_func.rs1use 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);