1use crate::Context;
2use crate::call_context::{ArmaContextManager, CallContext, CallContextStackTrace};
3use crate::ext_result::IntoExtResult;
4use crate::flags::FeatureFlags;
5use crate::value::{FromArma, Value};
6
7type HandlerFunc = Box<
8 dyn Fn(
9 Context,
10 &ArmaContextManager,
11 *mut libc::c_char,
12 libc::size_t,
13 Option<*mut *mut i8>,
14 Option<libc::c_int>,
15 ) -> libc::c_int,
16>;
17
18#[doc(hidden)]
19pub struct Handler {
21 pub handler: HandlerFunc,
23}
24
25#[doc(hidden)]
26pub fn fn_handler<C, I, R>(command: C) -> Handler
28where
29 C: Factory<I, R> + 'static,
30{
31 Handler {
32 handler: Box::new(
33 move |context: Context,
34 acm: &ArmaContextManager,
35 output: *mut libc::c_char,
36 size: libc::size_t,
37 args: Option<*mut *mut i8>,
38 count: Option<libc::c_int>|
39 -> libc::c_int {
40 unsafe { command.call(context, acm, output, size, args, count) }
41 },
42 ),
43 }
44}
45
46#[doc(hidden)]
47pub trait Executor: 'static {
49 unsafe fn call(
52 &self,
53 context: Context,
54 acm: &ArmaContextManager,
55 output: *mut libc::c_char,
56 size: libc::size_t,
57 args: Option<*mut *mut i8>,
58 count: Option<libc::c_int>,
59 );
60}
61
62#[doc(hidden)]
63pub trait Factory<A, R> {
68 unsafe fn call(
71 &self,
72 context: Context,
73 acm: &ArmaContextManager,
74 output: *mut libc::c_char,
75 size: libc::size_t,
76 args: Option<*mut *mut i8>,
77 count: Option<libc::c_int>,
78 ) -> libc::c_int;
79}
80
81macro_rules! execute {
82 ($s:ident, $c:expr, $count:expr, $output:expr, $size:expr, $args:expr, ($( $vars:ident )*), ($( $param:ident, )*)) => {{
83 let count = $count.unwrap_or_else(|| 0);
84 if count != $c {
85 return format!("2{}", count).parse::<libc::c_int>().unwrap();
86 }
87 if $c == 0 {
88 handle_output_and_return(
89 ($s)($( $vars, )* $($param::from_arma("".to_string()).unwrap(),)*),
90 $output,
91 $size
92 )
93 } else {
94 #[allow(unused_variables, unused_mut)]
95 let mut argv: Vec<String> = {
96 let argv: &[*mut libc::c_char; $c] = &*($args.unwrap() as *const [*mut i8; $c]);
97 let mut argv = argv
98 .to_vec()
99 .into_iter()
100 .map(|s| {
101 std::ffi::CStr::from_ptr(s).to_string_lossy().to_string()
102 })
103 .collect::<Vec<String>>();
104 argv.reverse();
105 argv
106 };
107 #[allow(unused_variables, unused_mut)] let mut c = 0;
109 #[allow(unused_assignments, clippy::mixed_read_write_in_expression)]
110 handle_output_and_return(
111 {
112 ($s)($( $vars, )* $(
113 if let Ok(val) = $param::from_arma(argv.pop().unwrap()) {
114 c += 1;
115 val
116 } else {
117 return format!("3{}", c).parse::<libc::c_int>().unwrap()
118 },
119 )*)
120 },
121 $output,
122 $size
123 )
124 }
125 }};
126}
127
128macro_rules! factory_tuple ({ $c: expr, $($param:ident)* } => {
129 impl<$($param,)* ER> Executor for dyn Factory<($($param,)*), ER>
130 where
131 ER: 'static,
132 $($param: FromArma + 'static,)*
133 {
134 unsafe fn call(
135 &self,
136 context: Context,
137 acm: &ArmaContextManager,
138 output: *mut libc::c_char,
139 size: libc::size_t,
140 args: Option<*mut *mut i8>,
141 count: Option<libc::c_int>,
142 ) {
143 self.call(context, acm, output, size, args, count);
144 }
145 }
146
147 impl<Func, $($param,)* ER> Factory<($($param,)*), ER> for Func
149 where
150 ER: IntoExtResult + 'static,
151 Func: Fn($($param),*) -> ER,
152 $($param: FromArma,)*
153 {
154 #[allow(non_snake_case)]
155 unsafe fn call(&self, _: Context, _: &ArmaContextManager, output: *mut libc::c_char, size: libc::size_t, args: Option<*mut *mut i8>, count: Option<libc::c_int>) -> libc::c_int {
156 let count = count.unwrap_or_else(|| 0);
157 if count != $c {
158 return format!("2{}", count).parse::<libc::c_int>().unwrap();
159 }
160 if $c == 0 {
161 handle_output_and_return(
162 (self)($($param::from_arma("".to_string()).unwrap(),)*),
163 output,
164 size
165 )
166 } else {
167 #[allow(unused_variables, unused_mut)]
168 let mut argv: Vec<String> = {
169 let argv: &[*mut libc::c_char; $c] = &*(args.unwrap() as *const [*mut i8; $c]);
170 let mut argv = argv
171 .to_vec()
172 .into_iter()
173 .map(|s| {
174 std::ffi::CStr::from_ptr(s).to_string_lossy().to_string()
175 })
176 .collect::<Vec<String>>();
177 argv.reverse();
178 argv
179 };
180 #[allow(unused_variables, unused_mut)] let mut c = 0;
182 #[allow(unused_assignments, clippy::mixed_read_write_in_expression)]
183 handle_output_and_return(
184 {
185 (self)($(
186 if let Ok(val) = $param::from_arma(argv.pop().unwrap()) {
187 c += 1;
188 val
189 } else {
190 return format!("3{}", c).parse::<libc::c_int>().unwrap()
191 },
192 )*)
193 },
194 output,
195 size
196 )
197 }
198 }
199 }
200
201 impl<Func, $($param,)* ER> Factory<(Context, $($param,)*), ER> for Func
203 where
204 ER: IntoExtResult + 'static,
205 Func: Fn(Context, $($param),*) -> ER,
206 $($param: FromArma,)*
207 {
208 #[allow(non_snake_case)]
209 unsafe fn call(&self, context: Context, _: &ArmaContextManager, output: *mut libc::c_char, size: libc::size_t, args: Option<*mut *mut i8>, count: Option<libc::c_int>) -> libc::c_int {
210 execute!(self, $c, count, output, size, args, (context), ($($param,)*))
211 }
212 }
213
214 impl<Func, $($param,)* ER> Factory<(CallContext, $($param,)*), ER> for Func
216 where
217 ER: IntoExtResult + 'static,
218 Func: Fn(CallContext, $($param),*) -> ER,
219 $($param: FromArma,)*
220 {
221 #[allow(non_snake_case)]
222 unsafe fn call(&self, _: Context, acm: &ArmaContextManager, output: *mut libc::c_char, size: libc::size_t, args: Option<*mut *mut i8>, count: Option<libc::c_int>) -> libc::c_int {
223 crate::RVExtensionFeatureFlags = FeatureFlags::default().with_context_stack_trace(false).as_bits();
224 let call_context = acm.request().into_without_stack();
225 execute!(self, $c, count, output, size, args, (call_context), ($($param,)*))
226 }
227 }
228
229 impl<Func, $($param,)* ER> Factory<(CallContextStackTrace, $($param,)*), ER> for Func
231 where
232 ER: IntoExtResult + 'static,
233 Func: Fn(CallContextStackTrace, $($param),*) -> ER,
234 $($param: FromArma,)*
235 {
236 #[allow(non_snake_case)]
237 unsafe fn call(&self, _: Context, acm: &ArmaContextManager, output: *mut libc::c_char, size: libc::size_t, args: Option<*mut *mut i8>, count: Option<libc::c_int>) -> libc::c_int {
238 crate::RVExtensionFeatureFlags = FeatureFlags::default().with_context_stack_trace(true).as_bits();
239 let call_context = acm.request();
240 execute!(self, $c, count, output, size, args, (call_context), ($($param,)*))
241 }
242 }
243
244 impl<Func, $($param,)* ER> Factory<(Context, CallContext, $($param,)*), ER> for Func
246 where
247 ER: IntoExtResult + 'static,
248 Func: Fn(Context, CallContext, $($param),*) -> ER,
249 $($param: FromArma,)*
250 {
251 #[allow(non_snake_case)]
252 unsafe fn call(&self, context: Context, acm: &ArmaContextManager, output: *mut libc::c_char, size: libc::size_t, args: Option<*mut *mut i8>, count: Option<libc::c_int>) -> libc::c_int {
253 crate::RVExtensionFeatureFlags = FeatureFlags::default().with_context_stack_trace(false).as_bits();
254 let call_context = acm.request().into_without_stack();
255 execute!(self, $c, count, output, size, args, (context call_context), ($($param,)*))
256 }
257 }
258
259 impl<Func, $($param,)* ER> Factory<(Context, CallContextStackTrace, $($param,)*), ER> for Func
261 where
262 ER: IntoExtResult + 'static,
263 Func: Fn(Context, CallContextStackTrace, $($param),*) -> ER,
264 $($param: FromArma,)*
265 {
266 #[allow(non_snake_case)]
267 unsafe fn call(&self, context: Context, acm: &ArmaContextManager, output: *mut libc::c_char, size: libc::size_t, args: Option<*mut *mut i8>, count: Option<libc::c_int>) -> libc::c_int {
268 crate::RVExtensionFeatureFlags = FeatureFlags::default().with_context_stack_trace(true).as_bits();
269 let call_context = acm.request();
270 execute!(self, $c, count, output, size, args, (context call_context), ($($param,)*))
271 }
272 }
273});
274
275unsafe fn handle_output_and_return<R>(
276 ret: R,
277 output: *mut libc::c_char,
278 size: libc::size_t,
279) -> libc::c_int
280where
281 R: IntoExtResult + 'static,
282{
283 let ret = ret.to_ext_result();
284 let ok = ret.is_ok();
285 if crate::write_cstr(
286 {
287 let value = match ret {
288 Ok(x) | Err(x) => x,
289 };
290 match value {
291 Value::String(s) => s,
292 v => v.to_string(),
293 }
294 },
295 output,
296 size,
297 )
298 .is_none()
299 {
300 4
301 } else if ok {
302 0
303 } else {
304 9
305 }
306}
307
308factory_tuple! { 0, }
309factory_tuple! { 1, A }
310factory_tuple! { 2, A B }
311factory_tuple! { 3, A B C }
312factory_tuple! { 4, A B C D }
313factory_tuple! { 5, A B C D E }
314factory_tuple! { 6, A B C D E F }
315factory_tuple! { 7, A B C D E F G }
316factory_tuple! { 8, A B C D E F G H }
317factory_tuple! { 9, A B C D E F G H I }
318factory_tuple! { 10, A B C D E F G H I J }
319factory_tuple! { 11, A B C D E F G H I J K }
320factory_tuple! { 12, A B C D E F G H I J K L }
321factory_tuple! { 13, A B C D E F G H I J K L M }
322factory_tuple! { 14, A B C D E F G H I J K L M N }
323factory_tuple! { 15, A B C D E F G H I J K L M N O }
324factory_tuple! { 16, A B C D E F G H I J K L M N O P }
325factory_tuple! { 17, A B C D E F G H I J K L M N O P Q }
326factory_tuple! { 18, A B C D E F G H I J K L M N O P Q R }
327factory_tuple! { 19, A B C D E F G H I J K L M N O P Q R S }
328factory_tuple! { 20, A B C D E F G H I J K L M N O P Q R S T }
329factory_tuple! { 21, A B C D E F G H I J K L M N O P Q R S T U }
330factory_tuple! { 22, A B C D E F G H I J K L M N O P Q R S T U V }
331factory_tuple! { 23, A B C D E F G H I J K L M N O P Q R S T U V W }
332factory_tuple! { 24, A B C D E F G H I J K L M N O P Q R S T U V W X }
333factory_tuple! { 25, A B C D E F G H I J K L M N O P Q R S T U V W X Y }
334factory_tuple! { 26, A B C D E F G H I J K L M N O P Q R S T U V W X Y Z }