1#![allow(clippy::too_many_arguments)]
8#![allow(clippy::type_complexity)]
9
10use alloc::vec::Vec;
11use core::cell::RefCell;
12use core::marker::PhantomData;
13
14use crate::batch::{force_flush, run_js_sync, with_runtime};
15use crate::encode::{BatchableResult, BinaryEncode, EncodeTypeDef, TYPE_CACHED, TYPE_FULL};
16use crate::ipc::DecodedData;
17use crate::ipc::EncodedData;
18
19pub const DROP_NATIVE_REF_FN_ID: u32 = 0xFFFFFFFF;
22
23pub const CALL_EXPORT_FN_ID: u32 = 0xFFFFFFFE;
26
27fn encode_function_types(encoder: &mut EncodedData, encode_types: impl FnOnce(&mut Vec<u8>)) {
31 let mut type_buf = Vec::new();
33 encode_types(&mut type_buf);
34
35 with_runtime(|state| {
36 let (id, is_cached) = state.get_or_create_type_id(type_buf.clone());
37 if is_cached {
38 encoder.push_u8(TYPE_CACHED);
40 encoder.push_u32(id);
41 } else {
42 encoder.push_u8(TYPE_FULL);
44 encoder.push_u32(id);
45
46 for byte in type_buf {
48 encoder.push_u8(byte);
49 }
50 }
51 });
52}
53
54pub struct JSFunction<T> {
59 id: u32,
60 function: PhantomData<T>,
61}
62
63impl<T> JSFunction<T> {
64 pub const fn new(id: u32) -> Self {
65 Self {
66 id,
67 function: PhantomData,
68 }
69 }
70
71 pub fn id(&self) -> u32 {
73 self.id
74 }
75}
76
77macro_rules! impl_js_function_call {
78 (0,) => {
80 impl<R: BatchableResult + EncodeTypeDef> JSFunction<fn() -> R> {
81 pub fn call(&self) -> R {
82 run_js_sync::<R>(self.id, |encoder| {
83 encode_function_types(encoder, |buf| {
84 buf.push(0);
85 R::encode_type_def(buf);
86 });
87 })
88 }
89 }
90 };
91 ($n:expr, $($T:ident $P:ident $arg:ident),+) => {
93 impl<$($T: EncodeTypeDef,)+ R: BatchableResult + EncodeTypeDef>
94 JSFunction<fn($($T),+) -> R>
95 {
96 pub fn call<$($P),+>(&self, $($arg: $T),+) -> R
97 where
98 $($T: BinaryEncode<$P>,)+
99 {
100 run_js_sync::<R>(self.id, |encoder| {
101 encode_function_types(encoder, |buf| {
102 buf.push($n);
103 $($T::encode_type_def(buf);)+
104 R::encode_type_def(buf);
105 });
106 $($arg.encode(encoder);)+
107 })
108 }
109 }
110 };
111}
112
113impl_js_function_call!(0,);
114impl_js_function_call!(1, T1 P1 arg1);
115impl_js_function_call!(2, T1 P1 arg1, T2 P2 arg2);
116impl_js_function_call!(3, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3);
117impl_js_function_call!(4, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4);
118impl_js_function_call!(5, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5);
119impl_js_function_call!(6, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6);
120impl_js_function_call!(7, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7);
121impl_js_function_call!(8, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8);
122impl_js_function_call!(9, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9);
123impl_js_function_call!(10, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10);
124impl_js_function_call!(11, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11);
125impl_js_function_call!(12, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12);
126impl_js_function_call!(13, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13);
127impl_js_function_call!(14, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14);
128impl_js_function_call!(15, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15);
129impl_js_function_call!(16, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16);
130impl_js_function_call!(17, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17);
131impl_js_function_call!(18, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18);
132impl_js_function_call!(19, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19);
133impl_js_function_call!(20, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20);
134impl_js_function_call!(21, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21);
135impl_js_function_call!(22, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22);
136impl_js_function_call!(23, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23);
137impl_js_function_call!(24, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24);
138impl_js_function_call!(25, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25);
139impl_js_function_call!(26, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25, T26 P26 arg26);
140impl_js_function_call!(27, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25, T26 P26 arg26, T27 P27 arg27);
141impl_js_function_call!(28, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25, T26 P26 arg26, T27 P27 arg27, T28 P28 arg28);
142impl_js_function_call!(29, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25, T26 P26 arg26, T27 P27 arg27, T28 P28 arg28, T29 P29 arg29);
143impl_js_function_call!(30, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25, T26 P26 arg26, T27 P27 arg27, T28 P28 arg28, T29 P29 arg29, T30 P30 arg30);
144impl_js_function_call!(31, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25, T26 P26 arg26, T27 P27 arg27, T28 P28 arg28, T29 P29 arg29, T30 P30 arg30, T31 P31 arg31);
145impl_js_function_call!(32, T1 P1 arg1, T2 P2 arg2, T3 P3 arg3, T4 P4 arg4, T5 P5 arg5, T6 P6 arg6, T7 P7 arg7, T8 P8 arg8, T9 P9 arg9, T10 P10 arg10, T11 P11 arg11, T12 P12 arg12, T13 P13 arg13, T14 P14 arg14, T15 P15 arg15, T16 P16 arg16, T17 P17 arg17, T18 P18 arg18, T19 P19 arg19, T20 P20 arg20, T21 P21 arg21, T22 P22 arg22, T23 P23 arg23, T24 P24 arg24, T25 P25 arg25, T26 P26 arg26, T27 P27 arg27, T28 P28 arg28, T29 P29 arg29, T30 P30 arg30, T31 P31 arg31, T32 P32 arg32);
146
147pub(crate) struct RustCallback {
152 f: alloc::rc::Rc<dyn Fn(&mut DecodedData, &mut EncodedData)>,
153}
154
155impl RustCallback {
156 pub fn new_fn<F>(f: F) -> Self
158 where
159 F: Fn(&mut DecodedData, &mut EncodedData) + 'static,
160 {
161 Self {
162 f: alloc::rc::Rc::new(move |data: &mut DecodedData, encoder: &mut EncodedData| {
163 f(data, encoder);
164 force_flush();
165 }),
166 }
167 }
168
169 pub fn new_fn_mut<F>(f: F) -> Self
171 where
172 F: FnMut(&mut DecodedData, &mut EncodedData) + 'static,
173 {
174 let cell = RefCell::new(f);
176 Self {
177 f: alloc::rc::Rc::new(move |data: &mut DecodedData, encoder: &mut EncodedData| {
178 {
179 let mut f = cell.borrow_mut();
180 f(data, encoder);
181 }
182 force_flush();
183 }),
184 }
185 }
186
187 pub fn clone_rc(&self) -> alloc::rc::Rc<dyn Fn(&mut DecodedData, &mut EncodedData)> {
189 self.f.clone()
190 }
191}