1use alloc::boxed::Box;
4use alloc::vec::Vec;
5use core::marker::PhantomData;
6
7use crate::convert::RefFromBinaryDecode;
8use crate::ipc::{DecodeError, DecodedData, EncodedData};
9use crate::object_store::ObjectHandle;
10use crate::value::JsValue;
11use crate::{
12 Closure, IntoWasmClosure, IntoWasmClosureRef, IntoWasmClosureRefMut, WasmClosureFnOnce,
13 WasmClosureFnOnceAbort,
14};
15
16use super::{BinaryDecode, BinaryEncode, EncodeTypeDef, IntoClosure, TypeTag};
17
18#[derive(Clone, Copy)]
22pub(crate) enum CallbackPolicy {
23 RustOwned = 0,
24 JsOwned = 1,
25 JsOwnedOnce = 2,
26}
27
28pub struct CallbackKey<F: ?Sized>(ObjectHandle, CallbackPolicy, PhantomData<F>);
29
30impl<F: ?Sized> CallbackKey<F> {
31 pub(crate) fn new(handle: ObjectHandle) -> Self {
33 Self::new_with_policy(handle, CallbackPolicy::JsOwned)
34 }
35
36 pub(crate) fn new_with_policy(handle: ObjectHandle, policy: CallbackPolicy) -> Self {
37 CallbackKey(handle, policy, PhantomData)
38 }
39}
40
41impl<F: ?Sized> BinaryEncode for CallbackKey<F> {
42 fn encode(self, encoder: &mut EncodedData) {
43 self.0.encode(encoder);
44 (self.1 as u32).encode(encoder);
45 }
46}
47
48impl<T: ?Sized> EncodeTypeDef for crate::ScopedClosure<'_, T> {
50 fn encode_type_def(buf: &mut Vec<u8>) {
51 JsValue::encode_type_def(buf);
52 }
53}
54
55macro_rules! decode_args {
60 ($decoder:expr; [$first:ident, $($ty:ident,)*] => $body:expr) => {{
64 #[allow(non_snake_case)]
65 let $first = <$first as BinaryDecode>::decode($decoder)?;
66 decode_args!($decoder; [$($ty,)*] => $body);
67 }};
68 ($decoder:expr; [] => $body:expr) => {{
70 $body;
71 return Ok(());
72 }};
73}
74
75macro_rules! callback_type_def_body {
82 ($buf:expr; R = $R:ty; $($arg:ty),*) => {{
83 $buf.push(TypeTag::Callback as u8);
84 let mut count: u8 = 0;
86 $(
87 let _ = PhantomData::<$arg>;
88 count += 1;
89 )*
90 $buf.push(count);
91 $(<$arg as EncodeTypeDef>::encode_type_def($buf);)*
93 <$R as EncodeTypeDef>::encode_type_def($buf);
95 }};
96 ($buf:expr; R = $R:ty; borrow_first; $($rest:ty),*) => {{
99 $buf.push(TypeTag::Callback as u8);
100 let mut count: u8 = 1;
102 $(
103 let _ = PhantomData::<$rest>;
104 count += 1;
105 )*
106 $buf.push(count);
107 $buf.push(TypeTag::BorrowedRef as u8);
109 $(<$rest as EncodeTypeDef>::encode_type_def($buf);)*
110 <$R as EncodeTypeDef>::encode_type_def($buf);
112 }};
113}
114
115macro_rules! impl_fnmut_stub {
116 ($($arg:ident),*) => {
117 impl<R, $($arg,)*> EncodeTypeDef for CallbackKey<fn($($arg),*) -> R>
119 where
120 $($arg: EncodeTypeDef + 'static, )*
121 R: EncodeTypeDef + 'static,
122 {
123 #[allow(unused)]
124 fn encode_type_def(buf: &mut Vec<u8>) {
125 callback_type_def_body!(buf; R = R; $($arg),*);
126 }
127 }
128
129 impl<R, $($arg,)*> crate::WryWasmClosure<fn($($arg),*) -> R> for dyn FnMut($($arg),*) -> R
131 where
132 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
133 R: BinaryEncode + EncodeTypeDef + 'static,
134 {
135 #[allow(non_snake_case)]
136 #[allow(unused)]
137 fn into_js_closure(mut boxed: Box<Self>) -> crate::Closure<Self> {
138 crate::Closure::wrap_encode_decode_mut::<fn($($arg),*) -> R>(
139 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
140 decode_args!(decoder; [$($arg,)*] => {
142 let result = boxed($($arg),*);
143 result.encode(encoder);
144 });
145 },
146 )
147 }
148 }
149
150 impl<R, $($arg,)*> crate::WasmClosure for dyn FnMut($($arg),*) -> R
151 where
152 $($arg: 'static, )*
153 R: 'static,
154 {
155 type Static = dyn FnMut($($arg),*) -> R;
156 type AsMut = dyn FnMut($($arg),*) -> R;
157 }
158
159 impl<R, $($arg,)*> crate::WryWasmClosure<fn($($arg),*) -> R> for dyn Fn($($arg),*) -> R
162 where
163 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
164 R: BinaryEncode + EncodeTypeDef + 'static,
165 {
166 #[allow(non_snake_case)]
167 #[allow(unused)]
168 fn into_js_closure(boxed: Box<Self>) -> crate::Closure<Self> {
169 crate::Closure::wrap_encode_decode::<fn($($arg),*) -> R>(
170 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
171 decode_args!(decoder; [$($arg,)*] => {
173 let result = boxed($($arg),*);
174 result.encode(encoder);
175 });
176 }
177 )
178 }
179 }
180
181 impl<R, $($arg,)*> crate::WasmClosure for dyn Fn($($arg),*) -> R
182 where
183 $($arg: 'static, )*
184 R: 'static,
185 {
186 type Static = dyn Fn($($arg),*) -> R;
187 type AsMut = dyn FnMut($($arg),*) -> R;
188 }
189
190 impl<R, F, $($arg,)*> IntoClosure<fn($($arg),*) -> R, crate::Closure<dyn FnMut($($arg),*) -> R>> for F
192 where F: FnMut($($arg),*) -> R + 'static,
193 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
194 R: BinaryEncode + EncodeTypeDef + 'static,
195 {
196 #[allow(non_snake_case)]
197 #[allow(unused)]
198 fn into_closure(mut self) -> crate::Closure<dyn FnMut($($arg),*) -> R> {
199 crate::Closure::wrap_encode_decode_mut::<fn($($arg),*) -> R>(
200 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
201 decode_args!(decoder; [$($arg,)*] => {
203 let result = self($($arg),*);
204 result.encode(encoder);
205 });
206 },
207 )
208 }
209 }
210
211 impl<R, F, $($arg,)*> IntoClosure<fn($($arg),*) -> R, crate::Closure<dyn Fn($($arg),*) -> R>> for F
213 where F: Fn($($arg),*) -> R + 'static,
214 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
215 R: BinaryEncode + EncodeTypeDef + 'static,
216 {
217 #[allow(non_snake_case)]
218 #[allow(unused)]
219 fn into_closure(self) -> crate::Closure<dyn Fn($($arg),*) -> R> {
220 crate::Closure::wrap_encode_decode::<fn($($arg),*) -> R>(
221 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
222 decode_args!(decoder; [$($arg,)*] => {
224 let result = self($($arg),*);
225 result.encode(encoder);
226 });
227 },
228 )
229 }
230 }
231
232 impl<R, F, $($arg,)*> IntoWasmClosure<dyn FnMut($($arg),*) -> R> for F
233 where F: FnMut($($arg),*) -> R + 'static,
234 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
235 R: BinaryEncode + EncodeTypeDef + 'static,
236 {
237 fn into_closure(self) -> crate::Closure<dyn FnMut($($arg),*) -> R> {
238 <F as IntoClosure<fn($($arg),*) -> R, crate::Closure<dyn FnMut($($arg),*) -> R>>>::into_closure(self)
239 }
240
241 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn FnMut($($arg),*) -> R> {
242 <F as IntoWasmClosure<dyn FnMut($($arg),*) -> R>>::into_closure(*self)
243 }
244 }
245
246 impl<R, $($arg,)*> IntoWasmClosure<dyn FnMut($($arg),*) -> R> for dyn FnMut($($arg),*) -> R
247 where
248 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
249 R: BinaryEncode + EncodeTypeDef + 'static,
250 {
251 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn FnMut($($arg),*) -> R> {
252 <Self as crate::WryWasmClosure<fn($($arg),*) -> R>>::into_js_closure(self)
253 }
254 }
255
256 impl<R, F, $($arg,)*> IntoWasmClosure<dyn Fn($($arg),*) -> R> for F
257 where F: Fn($($arg),*) -> R + 'static,
258 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
259 R: BinaryEncode + EncodeTypeDef + 'static,
260 {
261 fn into_closure(self) -> crate::Closure<dyn Fn($($arg),*) -> R> {
262 <F as IntoClosure<fn($($arg),*) -> R, crate::Closure<dyn Fn($($arg),*) -> R>>>::into_closure(self)
263 }
264
265 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn Fn($($arg),*) -> R> {
266 <F as IntoWasmClosure<dyn Fn($($arg),*) -> R>>::into_closure(*self)
267 }
268 }
269
270 impl<R, $($arg,)*> IntoWasmClosure<dyn Fn($($arg),*) -> R> for dyn Fn($($arg),*) -> R
271 where
272 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
273 R: BinaryEncode + EncodeTypeDef + 'static,
274 {
275 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn Fn($($arg),*) -> R> {
276 <Self as crate::WryWasmClosure<fn($($arg),*) -> R>>::into_js_closure(self)
277 }
278 }
279
280 impl<R, F, $($arg,)*> IntoWasmClosureRef<dyn Fn($($arg),*) -> R> for F
281 where F: Fn($($arg),*) -> R,
282 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
283 R: BinaryEncode + EncodeTypeDef + 'static,
284 {
285 #[allow(non_snake_case)]
286 #[allow(unused)]
287 fn into_scoped_closure_ref<'a>(t: &'a Self) -> crate::ScopedClosure<'a, <dyn Fn($($arg),*) -> R as crate::WasmClosure>::Static> {
288 let t: &(dyn Fn($($arg),*) -> R) = t;
289 let ptr = t as *const dyn Fn($($arg),*) -> R;
290 let (data_ptr, vtable_ptr): (usize, usize) = unsafe { core::mem::transmute(ptr) };
291 let callback = crate::function::RustCallback::new_fn(
292 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
293 let ptr: *const dyn Fn($($arg),*) -> R = unsafe {
294 core::mem::transmute((data_ptr, vtable_ptr))
295 };
296 let f: &dyn Fn($($arg),*) -> R = unsafe { &*ptr };
297 decode_args!(decoder; [$($arg,)*] => {
298 let result = f($($arg),*);
299 result.encode(encoder);
300 });
301 },
302 );
303 let handle = crate::object_store::insert_object(callback);
304 let value = crate::__rt::wbg_cast::<CallbackKey<fn($($arg),*) -> R>, crate::JsValue>(
305 CallbackKey::new_with_policy(handle, CallbackPolicy::RustOwned),
306 );
307 crate::ScopedClosure {
308 _phantom: PhantomData,
309 callback: crate::closure::CallbackOwnership::Owned,
310 value,
311 }
312 }
313 }
314
315 impl<R, $($arg,)*> IntoWasmClosureRef<dyn Fn($($arg),*) -> R> for dyn Fn($($arg),*) -> R
316 where
317 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
318 R: BinaryEncode + EncodeTypeDef + 'static,
319 {
320 #[allow(non_snake_case)]
321 #[allow(unused)]
322 fn into_scoped_closure_ref<'a>(t: &'a Self) -> crate::ScopedClosure<'a, <dyn Fn($($arg),*) -> R as crate::WasmClosure>::Static> {
323 let ptr = t as *const dyn Fn($($arg),*) -> R;
324 let (data_ptr, vtable_ptr): (usize, usize) = unsafe { core::mem::transmute(ptr) };
325 let callback = crate::function::RustCallback::new_fn(
326 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
327 let ptr: *const dyn Fn($($arg),*) -> R = unsafe {
328 core::mem::transmute((data_ptr, vtable_ptr))
329 };
330 let f: &dyn Fn($($arg),*) -> R = unsafe { &*ptr };
331 decode_args!(decoder; [$($arg,)*] => {
332 let result = f($($arg),*);
333 result.encode(encoder);
334 });
335 },
336 );
337 let handle = crate::object_store::insert_object(callback);
338 let value = crate::__rt::wbg_cast::<CallbackKey<fn($($arg),*) -> R>, crate::JsValue>(
339 CallbackKey::new_with_policy(handle, CallbackPolicy::RustOwned),
340 );
341 crate::ScopedClosure {
342 _phantom: PhantomData,
343 callback: crate::closure::CallbackOwnership::Owned,
344 value,
345 }
346 }
347 }
348
349 impl<R, F, $($arg,)*> IntoWasmClosureRefMut<dyn FnMut($($arg),*) -> R> for F
350 where F: FnMut($($arg),*) -> R,
351 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
352 R: BinaryEncode + EncodeTypeDef + 'static,
353 {
354 #[allow(non_snake_case)]
355 #[allow(unused)]
356 fn into_scoped_closure_ref_mut<'a>(t: &'a mut Self) -> crate::ScopedClosure<'a, <dyn FnMut($($arg),*) -> R as crate::WasmClosure>::Static> {
357 let t: &mut dyn FnMut($($arg),*) -> R = t;
358 let ptr = t as *mut dyn FnMut($($arg),*) -> R;
359 let (data_ptr, vtable_ptr): (usize, usize) = unsafe { core::mem::transmute(ptr) };
360 let callback = crate::function::RustCallback::new_fn_mut(
361 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
362 let ptr: *mut dyn FnMut($($arg),*) -> R = unsafe {
363 core::mem::transmute((data_ptr, vtable_ptr))
364 };
365 let f: &mut dyn FnMut($($arg),*) -> R = unsafe { &mut *ptr };
366 decode_args!(decoder; [$($arg,)*] => {
367 let result = f($($arg),*);
368 result.encode(encoder);
369 });
370 },
371 );
372 let handle = crate::object_store::insert_object(callback);
373 let value = crate::__rt::wbg_cast::<CallbackKey<fn($($arg),*) -> R>, crate::JsValue>(
374 CallbackKey::new_with_policy(handle, CallbackPolicy::RustOwned),
375 );
376 crate::ScopedClosure {
377 _phantom: PhantomData,
378 callback: crate::closure::CallbackOwnership::Owned,
379 value,
380 }
381 }
382 }
383
384 impl<R, $($arg,)*> IntoWasmClosureRefMut<dyn FnMut($($arg),*) -> R> for dyn FnMut($($arg),*) -> R
385 where
386 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
387 R: BinaryEncode + EncodeTypeDef + 'static,
388 {
389 #[allow(non_snake_case)]
390 #[allow(unused)]
391 fn into_scoped_closure_ref_mut<'a>(t: &'a mut Self) -> crate::ScopedClosure<'a, <dyn FnMut($($arg),*) -> R as crate::WasmClosure>::Static> {
392 let ptr = t as *mut dyn FnMut($($arg),*) -> R;
393 let (data_ptr, vtable_ptr): (usize, usize) = unsafe { core::mem::transmute(ptr) };
394 let callback = crate::function::RustCallback::new_fn_mut(
395 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
396 let ptr: *mut dyn FnMut($($arg),*) -> R = unsafe {
397 core::mem::transmute((data_ptr, vtable_ptr))
398 };
399 let f: &mut dyn FnMut($($arg),*) -> R = unsafe { &mut *ptr };
400 decode_args!(decoder; [$($arg,)*] => {
401 let result = f($($arg),*);
402 result.encode(encoder);
403 });
404 },
405 );
406 let handle = crate::object_store::insert_object(callback);
407 let value = crate::__rt::wbg_cast::<CallbackKey<fn($($arg),*) -> R>, crate::JsValue>(
408 CallbackKey::new_with_policy(handle, CallbackPolicy::RustOwned),
409 );
410 crate::ScopedClosure {
411 _phantom: PhantomData,
412 callback: crate::closure::CallbackOwnership::Owned,
413 value,
414 }
415 }
416 }
417 };
418}
419
420macro_rules! impl_closure_ref_binary_encode {
431 (
432 impl ($($self_ty:tt)*) via *mut dyn FnMut, $ctor:ident;
433 $($arg:ident),*
434 ) => {
435 impl<R, $($arg,)*> BinaryEncode for $($self_ty)*
436 where
437 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
438 R: BinaryEncode + EncodeTypeDef + 'static,
439 {
440 #[allow(non_snake_case)]
441 #[allow(unused)]
442 fn encode(self, encoder: &mut EncodedData) {
443 encoder.mark_needs_flush();
444
445 let ptr = self as *mut dyn FnMut($($arg),*) -> R;
446 let (data_ptr, vtable_ptr): (usize, usize) = unsafe { core::mem::transmute(ptr) };
447
448 let callback = crate::function::RustCallback::$ctor(
449 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
450 let ptr: *mut dyn FnMut($($arg),*) -> R = unsafe {
451 core::mem::transmute((data_ptr, vtable_ptr))
452 };
453 let f: &mut dyn FnMut($($arg),*) -> R = unsafe { &mut *ptr };
454 $(let $arg = <$arg as BinaryDecode>::decode(decoder)?;)*
455 let result = f($($arg),*);
456 result.encode(encoder);
457 Ok(())
458 },
459 );
460 let handle = crate::object_store::insert_object(callback);
461 let key: CallbackKey<fn($($arg),*) -> R> =
462 CallbackKey::new_with_policy(handle, CallbackPolicy::RustOwned);
463 key.encode(encoder);
464 crate::batch::queue_rust_object_drop(handle);
465 }
466 }
467 };
468 (
469 impl ($($self_ty:tt)*) via *const dyn Fn, $ctor:ident;
470 $($arg:ident),*
471 ) => {
472 impl<R, $($arg,)*> BinaryEncode for $($self_ty)*
473 where
474 $($arg: BinaryDecode + EncodeTypeDef + 'static, )*
475 R: BinaryEncode + EncodeTypeDef + 'static,
476 {
477 #[allow(non_snake_case)]
478 #[allow(unused)]
479 fn encode(self, encoder: &mut EncodedData) {
480 encoder.mark_needs_flush();
481
482 let ptr = self as *const dyn Fn($($arg),*) -> R;
483 let (data_ptr, vtable_ptr): (usize, usize) = unsafe { core::mem::transmute(ptr) };
484
485 let callback = crate::function::RustCallback::$ctor(
486 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
487 let ptr: *const dyn Fn($($arg),*) -> R = unsafe {
488 core::mem::transmute((data_ptr, vtable_ptr))
489 };
490 let f: &dyn Fn($($arg),*) -> R = unsafe { &*ptr };
491 $(let $arg = <$arg as BinaryDecode>::decode(decoder)?;)*
492 let result = f($($arg),*);
493 result.encode(encoder);
494 Ok(())
495 },
496 );
497 let handle = crate::object_store::insert_object(callback);
498 let key: CallbackKey<fn($($arg),*) -> R> =
499 CallbackKey::new_with_policy(handle, CallbackPolicy::RustOwned);
500 key.encode(encoder);
501 crate::batch::queue_rust_object_drop(handle);
502 }
503 }
504 };
505}
506
507macro_rules! impl_closure_ref_encode {
511 ($($arg:ident),*) => {
512 impl<R, $($arg,)*> EncodeTypeDef for &mut dyn FnMut($($arg),*) -> R
514 where
515 $($arg: EncodeTypeDef + 'static, )*
516 R: EncodeTypeDef + 'static,
517 {
518 #[allow(unused)]
519 fn encode_type_def(buf: &mut Vec<u8>) {
520 callback_type_def_body!(buf; R = R; $($arg),*);
521 }
522 }
523
524 impl_closure_ref_binary_encode!(
526 impl (&mut dyn FnMut($($arg),*) -> R) via *mut dyn FnMut, new_fn_mut;
527 $($arg),*
528 );
529
530 impl<R, $($arg,)*> EncodeTypeDef for &dyn Fn($($arg),*) -> R
532 where
533 $($arg: EncodeTypeDef + 'static, )*
534 R: EncodeTypeDef + 'static,
535 {
536 #[allow(unused)]
537 fn encode_type_def(buf: &mut Vec<u8>) {
538 callback_type_def_body!(buf; R = R; $($arg),*);
539 }
540 }
541
542 impl_closure_ref_binary_encode!(
544 impl (&dyn Fn($($arg),*) -> R) via *const dyn Fn, new_fn;
545 $($arg),*
546 );
547
548 impl<R, $($arg,)*> EncodeTypeDef for &mut dyn Fn($($arg),*) -> R
550 where
551 $($arg: EncodeTypeDef + 'static, )*
552 R: EncodeTypeDef + 'static,
553 {
554 #[allow(unused)]
555 fn encode_type_def(buf: &mut Vec<u8>) {
556 callback_type_def_body!(buf; R = R; $($arg),*);
557 }
558 }
559
560 impl_closure_ref_binary_encode!(
563 impl (&mut dyn Fn($($arg),*) -> R) via *const dyn Fn, new_fn;
564 $($arg),*
565 );
566 };
567}
568
569impl_closure_ref_encode!();
570impl_closure_ref_encode!(A1);
571impl_closure_ref_encode!(A1, A2);
572impl_closure_ref_encode!(A1, A2, A3);
573impl_closure_ref_encode!(A1, A2, A3, A4);
574impl_closure_ref_encode!(A1, A2, A3, A4, A5);
575impl_closure_ref_encode!(A1, A2, A3, A4, A5, A6);
576impl_closure_ref_encode!(A1, A2, A3, A4, A5, A6, A7);
577
578impl_fnmut_stub!();
579impl_fnmut_stub!(A1);
580impl_fnmut_stub!(A1, A2);
581impl_fnmut_stub!(A1, A2, A3);
582impl_fnmut_stub!(A1, A2, A3, A4);
583impl_fnmut_stub!(A1, A2, A3, A4, A5);
584impl_fnmut_stub!(A1, A2, A3, A4, A5, A6);
585impl_fnmut_stub!(A1, A2, A3, A4, A5, A6, A7);
586impl_fnmut_stub!(A1, A2, A3, A4, A5, A6, A7, A8);
587
588pub struct BorrowedFirstArg;
590
591macro_rules! impl_fnmut_stub_ref {
594 ($first:ident $(, $rest:ident)*) => {
595 #[allow(coherence_leak_check)]
597 impl<R, $first, $($rest,)*> EncodeTypeDef for CallbackKey<fn(&$first, $($rest),*) -> R>
598 where
599 $first: EncodeTypeDef + 'static,
600 $($rest: EncodeTypeDef + 'static, )*
601 R: EncodeTypeDef + 'static,
602 {
603 #[allow(unused)]
604 fn encode_type_def(buf: &mut Vec<u8>) {
605 callback_type_def_body!(buf; R = R; borrow_first; $($rest),*);
606 }
607 }
608
609 impl<R, $first, $($rest,)*> crate::WryWasmClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R)> for dyn FnMut(&$first, $($rest),*) -> R
611 where
612 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
613 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
614 R: BinaryEncode + EncodeTypeDef + 'static,
615 {
616 #[allow(non_snake_case)]
617 #[allow(unused)]
618 fn into_js_closure(mut boxed: Box<Self>) -> crate::Closure<Self> {
619 crate::Closure::wrap_encode_decode_mut::<fn(&$first, $($rest),*) -> R>(
620 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
621 let anchor = <$first as RefFromBinaryDecode>::ref_decode(decoder)?;
622 $(let $rest = <$rest as BinaryDecode>::decode(decoder)?;)*
623 let result = boxed(&*anchor, $($rest),*);
624 result.encode(encoder);
625 Ok(())
626 },
627 )
628 }
629 }
630
631 #[allow(coherence_leak_check)]
634 impl<R, $first, $($rest,)*> crate::WasmClosure for dyn FnMut(&$first, $($rest),*) -> R
635 where
636 $first: 'static,
637 $($rest: 'static,)*
638 R: 'static,
639 {
640 type Static = dyn FnMut(&$first, $($rest),*) -> R;
641 type AsMut = dyn FnMut(&$first, $($rest),*) -> R;
642 }
643
644 impl<R, $first, $($rest,)*> crate::WryWasmClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R)> for dyn Fn(&$first, $($rest),*) -> R
646 where
647 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
648 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
649 R: BinaryEncode + EncodeTypeDef + 'static,
650 {
651 #[allow(non_snake_case)]
652 #[allow(unused)]
653 fn into_js_closure(boxed: Box<Self>) -> crate::Closure<Self> {
654 crate::Closure::wrap_encode_decode::<fn(&$first, $($rest),*) -> R>(
655 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
656 let anchor = <$first as RefFromBinaryDecode>::ref_decode(decoder)?;
657 $(let $rest = <$rest as BinaryDecode>::decode(decoder)?;)*
658 let result = boxed(&*anchor, $($rest),*);
659 result.encode(encoder);
660 Ok(())
661 },
662 )
663 }
664 }
665
666 #[allow(coherence_leak_check)]
667 impl<R, $first, $($rest,)*> crate::WasmClosure for dyn Fn(&$first, $($rest),*) -> R
668 where
669 $first: 'static,
670 $($rest: 'static,)*
671 R: 'static,
672 {
673 type Static = dyn Fn(&$first, $($rest),*) -> R;
674 type AsMut = dyn FnMut(&$first, $($rest),*) -> R;
675 }
676
677 impl<R, F, $first, $($rest,)*> IntoClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R), crate::Closure<dyn FnMut(&$first, $($rest),*) -> R>> for F
679 where F: FnMut(&$first, $($rest),*) -> R + 'static,
680 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
681 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
682 R: BinaryEncode + EncodeTypeDef + 'static,
683 {
684 #[allow(non_snake_case)]
685 #[allow(unused)]
686 fn into_closure(mut self) -> crate::Closure<dyn FnMut(&$first, $($rest),*) -> R> {
687 crate::Closure::wrap_encode_decode_mut::<fn(&$first, $($rest),*) -> R>(
688 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
689 let anchor = <$first as RefFromBinaryDecode>::ref_decode(decoder)?;
690 $(let $rest = <$rest as BinaryDecode>::decode(decoder)?;)*
691 let result = self(&*anchor, $($rest),*);
692 result.encode(encoder);
693 Ok(())
694 },
695 )
696 }
697 }
698
699 impl<R, F, $first, $($rest,)*> IntoClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R), crate::Closure<dyn Fn(&$first, $($rest),*) -> R>> for F
701 where F: Fn(&$first, $($rest),*) -> R + 'static,
702 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
703 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
704 R: BinaryEncode + EncodeTypeDef + 'static,
705 {
706 #[allow(non_snake_case)]
707 #[allow(unused)]
708 fn into_closure(self) -> crate::Closure<dyn Fn(&$first, $($rest),*) -> R> {
709 crate::Closure::wrap_encode_decode::<fn(&$first, $($rest),*) -> R>(
710 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
711 let anchor = <$first as RefFromBinaryDecode>::ref_decode(decoder)?;
712 $(let $rest = <$rest as BinaryDecode>::decode(decoder)?;)*
713 let result = self(&*anchor, $($rest),*);
714 result.encode(encoder);
715 Ok(())
716 },
717 )
718 }
719 }
720
721 #[allow(coherence_leak_check)]
722 impl<R, F, $first, $($rest,)*> IntoWasmClosure<dyn FnMut(&$first, $($rest),*) -> R> for F
723 where F: FnMut(&$first, $($rest),*) -> R + 'static,
724 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
725 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
726 R: BinaryEncode + EncodeTypeDef + 'static,
727 {
728 fn into_closure(self) -> crate::Closure<dyn FnMut(&$first, $($rest),*) -> R> {
729 <F as IntoClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R), crate::Closure<dyn FnMut(&$first, $($rest),*) -> R>>>::into_closure(self)
730 }
731
732 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn FnMut(&$first, $($rest),*) -> R> {
733 <F as IntoWasmClosure<dyn FnMut(&$first, $($rest),*) -> R>>::into_closure(*self)
734 }
735 }
736
737 #[allow(coherence_leak_check)]
738 impl<R, $first, $($rest,)*> IntoWasmClosure<dyn FnMut(&$first, $($rest),*) -> R> for dyn FnMut(&$first, $($rest),*) -> R
739 where
740 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
741 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
742 R: BinaryEncode + EncodeTypeDef + 'static,
743 {
744 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn FnMut(&$first, $($rest),*) -> R> {
745 <Self as crate::WryWasmClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R)>>::into_js_closure(self)
746 }
747 }
748
749 #[allow(coherence_leak_check)]
750 impl<R, F, $first, $($rest,)*> IntoWasmClosure<dyn Fn(&$first, $($rest),*) -> R> for F
751 where F: Fn(&$first, $($rest),*) -> R + 'static,
752 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
753 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
754 R: BinaryEncode + EncodeTypeDef + 'static,
755 {
756 fn into_closure(self) -> crate::Closure<dyn Fn(&$first, $($rest),*) -> R> {
757 <F as IntoClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R), crate::Closure<dyn Fn(&$first, $($rest),*) -> R>>>::into_closure(self)
758 }
759
760 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn Fn(&$first, $($rest),*) -> R> {
761 <F as IntoWasmClosure<dyn Fn(&$first, $($rest),*) -> R>>::into_closure(*self)
762 }
763 }
764
765 #[allow(coherence_leak_check)]
766 impl<R, $first, $($rest,)*> IntoWasmClosure<dyn Fn(&$first, $($rest),*) -> R> for dyn Fn(&$first, $($rest),*) -> R
767 where
768 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
769 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
770 R: BinaryEncode + EncodeTypeDef + 'static,
771 {
772 fn into_closure_box(self: Box<Self>) -> crate::Closure<dyn Fn(&$first, $($rest),*) -> R> {
773 <Self as crate::WryWasmClosure<(BorrowedFirstArg, fn(&$first, $($rest),*) -> R)>>::into_js_closure(self)
774 }
775 }
776 };
777}
778
779impl_fnmut_stub_ref!(A1);
780impl_fnmut_stub_ref!(A1, A2);
781impl_fnmut_stub_ref!(A1, A2, A3);
782impl_fnmut_stub_ref!(A1, A2, A3, A4);
783impl_fnmut_stub_ref!(A1, A2, A3, A4, A5);
784impl_fnmut_stub_ref!(A1, A2, A3, A4, A5, A6);
785impl_fnmut_stub_ref!(A1, A2, A3, A4, A5, A6, A7);
786impl_fnmut_stub_ref!(A1, A2, A3, A4, A5, A6, A7, A8);
787
788macro_rules! impl_fn_once {
791 ($($arg:ident),*) => {
792 impl<R, F, $($arg,)*> WasmClosureFnOnce<dyn FnMut($($arg),*) -> R, fn($($arg),*) -> R, R> for F
793 where
794 F: FnOnce($($arg),*) -> R + 'static,
795 $($arg: BinaryDecode + EncodeTypeDef + 'static,)*
796 R: BinaryEncode + EncodeTypeDef + 'static,
797 {
798 #[allow(non_snake_case)]
799 #[allow(unused_variables)]
800 fn into_closure(self) -> Closure<dyn FnMut($($arg),*) -> R> {
801 let mut me = Some(self);
803 crate::Closure::wrap_once_encode_decode_mut::<fn($($arg),*) -> R>(
805 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
806 let f = me.take().expect("FnOnce closure called more than once");
807 decode_args!(decoder; [$($arg,)*] => {
808 let result = f($($arg),*);
809 result.encode(encoder);
810 });
811 },
812 )
813 }
814 }
815
816 impl<R, F, $($arg,)*> WasmClosureFnOnceAbort<dyn FnMut($($arg),*) -> R, fn($($arg),*) -> R, R> for F
817 where
818 F: FnOnce($($arg),*) -> R + 'static,
819 $($arg: BinaryDecode + EncodeTypeDef + 'static,)*
820 R: BinaryEncode + EncodeTypeDef + 'static,
821 {
822 #[allow(non_snake_case)]
823 #[allow(unused_variables)]
824 fn into_closure(self) -> Closure<dyn FnMut($($arg),*) -> R> {
825 <F as WasmClosureFnOnce<dyn FnMut($($arg),*) -> R, fn($($arg),*) -> R, R>>::into_closure(self)
826 }
827 }
828 };
829}
830
831impl_fn_once!();
832impl_fn_once!(A1);
833impl_fn_once!(A1, A2);
834impl_fn_once!(A1, A2, A3);
835impl_fn_once!(A1, A2, A3, A4);
836impl_fn_once!(A1, A2, A3, A4, A5);
837impl_fn_once!(A1, A2, A3, A4, A5, A6);
838impl_fn_once!(A1, A2, A3, A4, A5, A6, A7);
839impl_fn_once!(A1, A2, A3, A4, A5, A6, A7, A8);
840
841macro_rules! impl_fn_once_ref {
844 ($first:ident $(, $rest:ident)*) => {
845 impl<R, F, $first, $($rest,)*> WasmClosureFnOnce<dyn FnMut(&$first, $($rest),*) -> R, (BorrowedFirstArg, fn(&$first, $($rest),*) -> R), R> for F
846 where
847 F: FnOnce(&$first, $($rest),*) -> R + 'static,
848 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
849 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
850 R: BinaryEncode + EncodeTypeDef + 'static,
851 {
852 #[allow(non_snake_case)]
853 #[allow(unused_variables)]
854 fn into_closure(self) -> Closure<dyn FnMut(&$first, $($rest),*) -> R> {
855 let mut me = Some(self);
856 crate::Closure::wrap_once_encode_decode_mut::<fn(&$first, $($rest),*) -> R>(
857 move |decoder: &mut DecodedData, encoder: &mut EncodedData| {
858 let f = me.take().expect("FnOnce closure called more than once");
859 let anchor = <$first as RefFromBinaryDecode>::ref_decode(decoder)?;
860 $(let $rest = <$rest as BinaryDecode>::decode(decoder)?;)*
861 let result = f(&*anchor, $($rest),*);
862 result.encode(encoder);
863 Ok(())
864 },
865 )
866 }
867 }
868
869 impl<R, F, $first, $($rest,)*> WasmClosureFnOnceAbort<dyn FnMut(&$first, $($rest),*) -> R, (BorrowedFirstArg, fn(&$first, $($rest),*) -> R), R> for F
870 where
871 F: FnOnce(&$first, $($rest),*) -> R + 'static,
872 $first: RefFromBinaryDecode + EncodeTypeDef + 'static,
873 $($rest: BinaryDecode + EncodeTypeDef + 'static,)*
874 R: BinaryEncode + EncodeTypeDef + 'static,
875 {
876 #[allow(non_snake_case)]
877 #[allow(unused_variables)]
878 fn into_closure(self) -> Closure<dyn FnMut(&$first, $($rest),*) -> R> {
879 <F as WasmClosureFnOnce<dyn FnMut(&$first, $($rest),*) -> R, (BorrowedFirstArg, fn(&$first, $($rest),*) -> R), R>>::into_closure(self)
880 }
881 }
882 };
883}
884
885impl_fn_once_ref!(A1);
886impl_fn_once_ref!(A1, A2);
887impl_fn_once_ref!(A1, A2, A3);
888impl_fn_once_ref!(A1, A2, A3, A4);
889impl_fn_once_ref!(A1, A2, A3, A4, A5);
890impl_fn_once_ref!(A1, A2, A3, A4, A5, A6);
891impl_fn_once_ref!(A1, A2, A3, A4, A5, A6, A7);
892impl_fn_once_ref!(A1, A2, A3, A4, A5, A6, A7, A8);
893
894impl<F: ?Sized> BinaryDecode for crate::Closure<F> {
895 fn decode(decoder: &mut DecodedData) -> Result<Self, DecodeError> {
896 let value = <crate::JsValue as BinaryDecode>::decode(decoder)?;
898 Ok(Self {
899 _phantom: PhantomData,
900 callback: crate::closure::CallbackOwnership::None,
901 value,
902 })
903 }
904}
905
906impl<F: ?Sized> BinaryEncode for crate::Closure<F> {
907 fn encode(mut self, encoder: &mut EncodedData) {
908 if self.callback.needs_flush() {
909 encoder.mark_needs_flush();
910 }
911 self.callback.detach();
914 (&self.value).encode(encoder);
915 }
916}
917
918impl<F: ?Sized> BinaryEncode for &crate::ScopedClosure<'_, F> {
919 fn encode(self, encoder: &mut EncodedData) {
920 if self.callback.needs_flush() {
921 encoder.mark_needs_flush();
922 }
923 (&self.value).encode(encoder);
925 }
926}