1#![cfg_attr(docsrs, feature(doc_auto_cfg))]
220#![forbid(unsafe_code)]
221#![no_std]
222extern crate self as magic_args;
223
224#[cfg(feature = "derive")]
225#[doc(inline)]
251pub use magic_args_derive::MagicArgs;
252
253pub trait Args<T> {
257 fn get(&self) -> T;
263}
264
265impl<T, U> Args<T> for &U
266where
267 U: Args<T>,
268{
269 fn get(&self) -> T {
270 U::get(*self)
271 }
272}
273
274#[doc(hidden)]
275pub mod __private {
276 #[derive(Clone)]
277 pub struct Tagged<T, const N: usize>(pub T);
278}
279
280use self::__private::*;
281
282macro_rules! impl_args_tuple {
283 ($($idx:tt: $t:ident),*) => {
284 impl_args_tuple!(@impl [$($idx: $t),*]: $(($idx, $t))*);
285 };
286 (@impl [$($_idx:tt: $_t:ident),*]:) => {};
287 (@impl [$($_idx:tt: $_t:ident),*]: ($idx:tt, $t:ident) $($tail:tt)*) => {
288 impl<$($_t,)*> Args<Tagged<$t, $idx>> for ($($_t,)*)
289 where
290 $t: Clone
291 {
292 fn get(&self) -> Tagged<$t, $idx> {
293 Tagged(self.$idx.clone())
294 }
295 }
296
297 impl_args_tuple!(@impl [$($_idx: $_t),*]: $($tail)*);
298 };
299}
300
301impl_args_tuple! {}
302impl_args_tuple! { 0: T0 }
303impl_args_tuple! { 0: T0, 1: T1 }
304impl_args_tuple! { 0: T0, 1: T1, 2: T2 }
305impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3 }
306impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4 }
307impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5 }
308impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6 }
309impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7 }
310impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8 }
311impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9 }
312impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10 }
313impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11 }
314impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12 }
315impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13 }
316impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14 }
317impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15 }
318impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16 }
319impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17 }
320impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18 }
321impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19 }
322impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20 }
323impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21 }
324impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22 }
325impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23 }
326impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24 }
327impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24, 25: T25 }
328impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24, 25: T25, 26: T26 }
329impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24, 25: T25, 26: T26, 27: T27 }
330impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24, 25: T25, 26: T26, 27: T27, 28: T28 }
331impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24, 25: T25, 26: T26, 27: T27, 28: T28, 29: T29 }
332impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24, 25: T25, 26: T26, 27: T27, 28: T28, 29: T29, 30: T30 }
333impl_args_tuple! { 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11, 12: T12, 13: T13, 14: T14, 15: T15, 16: T16, 17: T17, 18: T18, 19: T19, 20: T20, 21: T21, 22: T22, 23: T23, 24: T24, 25: T25, 26: T26, 27: T27, 28: T28, 29: T29, 30: T30, 31: T31 }
334
335pub trait Callable<A, T> {
342 type Output;
343
344 fn call(self, args: A) -> Self::Output;
345}
346
347macro_rules! impl_callable_fnonce {
348 ($($t:ident: $n:ident),*) => {
349 impl<F, O, A, $($t,)* $(const $n: usize,)*> Callable<A, ($(Tagged<$t, $n>,)*)> for F
350 where
351 F: FnOnce($($t),*) -> O,
352 $(A: Args<Tagged<$t, $n>>,)*
353 {
354 type Output = O;
355
356 #[allow(non_snake_case)]
357 fn call(self, _args: A) -> Self::Output {
358 $(let $t = <A as Args<Tagged<$t, $n>>>::get(&_args);)*
359 (self)($($t.0,)*)
360 }
361 }
362 };
363}
364
365impl_callable_fnonce! {}
366impl_callable_fnonce! { T0: N0 }
367impl_callable_fnonce! { T0: N0, T1: N1 }
368impl_callable_fnonce! { T0: N0, T1: N1, T2: N2 }
369impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3 }
370impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4 }
371impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5 }
372impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6 }
373impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7 }
374impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8 }
375impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9 }
376impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10 }
377impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11 }
378impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12 }
379impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13 }
380impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14 }
381impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15 }
382impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16 }
383impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17 }
384impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18 }
385impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19 }
386impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20 }
387impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21 }
388impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22 }
389impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23 }
390impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24 }
391impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24, T25: N25 }
392impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24, T25: N25, T26: N26 }
393impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24, T25: N25, T26: N26, T27: N27 }
394impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24, T25: N25, T26: N26, T27: N27, T28: N28 }
395impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24, T25: N25, T26: N26, T27: N27, T28: N28, T29: N29 }
396impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24, T25: N25, T26: N26, T27: N27, T28: N28, T29: N29, T30: N30 }
397impl_callable_fnonce! { T0: N0, T1: N1, T2: N2, T3: N3, T4: N4, T5: N5, T6: N6, T7: N7, T8: N8, T9: N9, T10: N10, T11: N11, T12: N12, T13: N13, T14: N14, T15: N15, T16: N16, T17: N17, T18: N18, T19: N19, T20: N20, T21: N21, T22: N22, T23: N23, T24: N24, T25: N25, T26: N26, T27: N27, T28: N28, T29: N29, T30: N30, T31: N31 }
398
399pub trait MagicArgs {
403 fn apply<C, T>(self, f: C) -> C::Output
419 where
420 C: Callable<Self, T>,
421 Self: Sized;
422}
423
424impl<U> MagicArgs for U {
425 #[inline]
426 fn apply<C, T>(self, f: C) -> C::Output
427 where
428 C: Callable<Self, T>,
429 Self: Sized,
430 {
431 apply(f, self)
432 }
433}
434
435#[inline]
451pub fn apply<C, A, T>(f: C, args: A) -> C::Output
452where
453 C: Callable<A, T>,
454{
455 f.call(args)
456}
457
458#[cfg(test)]
459mod tests {
460 use super::*;
461
462 #[test]
463 fn test_sync_functions() {
464 let args = (42u32, 31i32);
465
466 fn f0() -> i32 {
467 42
468 }
469
470 fn f1(x: u32) -> i32 {
471 x as i32
472 }
473
474 fn f2(y: i32, x: u32) -> i32 {
475 y + x as i32
476 }
477
478 fn f3(x: u32, y: u32) -> u32 {
479 x + y
480 }
481
482 assert_eq!(args.apply(f0), 42);
483 assert_eq!(args.apply(f1), 42);
484 assert_eq!(args.apply(f2), 73);
485 assert_eq!(args.apply(f3), 84);
486 }
487
488 #[test]
489 fn test_sync_closures() {
490 let args = (42u32, 31i32);
491
492 let data = &[1_i32, 2, 3, 4, 5];
493
494 assert_eq!(args.apply(|| { data.iter().sum::<i32>() }), 15);
495 assert_eq!(
496 args.apply(|x: u32| { data.iter().sum::<i32>() + x as i32 }),
497 57
498 );
499 assert_eq!(
500 args.apply(|y: i32, x: u32| { data.iter().sum::<i32>() + y + x as i32 }),
501 88
502 );
503 assert_eq!(
504 args.apply(|x: u32, y: u32| { data.iter().sum::<i32>() as u32 + x + y }),
505 99
506 );
507 }
508
509 #[test]
510 fn test_async() {
511 fn assert_future<F: Future>(_f: F) {}
512
513 let args = (42u32, 31i32);
514
515 async fn f0() -> i32 {
516 42
517 }
518
519 async fn f1(x: u32) -> i32 {
520 x as i32
521 }
522
523 async fn f2(y: i32, x: u32) -> i32 {
524 y + x as i32
525 }
526
527 async fn f3(x: u32, y: u32) -> u32 {
528 x + y
529 }
530
531 assert_future(args.apply(f0));
532 assert_future(args.apply(f1));
533 assert_future(args.apply(f2));
534 assert_future(args.apply(f3));
535 }
536
537 #[cfg(feature = "derive")]
538 mod derive {
539 use super::*;
540
541 #[test]
542 fn test_derive_tuple() {
543 #[derive(MagicArgs)]
544 struct MyArgs(i32, u32);
545
546 let args = MyArgs(42, 31);
547 assert_eq!(args.apply(|x: u32, _y: i32| x as i32), 31);
548 }
549
550 #[test]
551 fn test_derive_struct() {
552 #[derive(MagicArgs)]
553 struct MyArgs {
554 x: i32,
555 y: u32,
556 }
557
558 let args = MyArgs { x: 42, y: 31 };
559 assert_eq!(args.apply(|x: u32, _y: i32| x as i32), 31);
560 }
561
562 #[test]
563 fn test_derive_struct_lifetime() {
564 #[derive(MagicArgs)]
565 struct MyArgs<'a>(&'a str);
566
567 let args = MyArgs("Hello, World!");
568 assert_eq!(args.apply(|x: &str| x.len()), 13);
569 }
570 }
571}