Skip to main content

std_traits/
fun.rs

1use crate::{
2    num::Integer,
3    primitive::Primitive,
4    ptr::{Pointer, cast_ptr},
5    tuple::Tuple,
6    util::cast_int,
7};
8
9pub trait FunctionPointer: Primitive + Copy + Sized {
10    type Args: Tuple;
11    type Return;
12
13    fn call(self, args: Self::Args) -> Self::Return;
14
15    fn cast_ptr<T: Sized, P: Pointer<T>>(self) -> P;
16
17    fn cast_int<T: Integer>(self) -> T;
18}
19
20impl<R> Primitive for fn() -> R {}
21impl<R> FunctionPointer for fn() -> R {
22    type Args = ();
23    type Return = R;
24
25    fn call(self, _args: Self::Args) -> Self::Return {
26        self()
27    }
28
29    fn cast_ptr<T: Sized, P: Pointer<T>>(self) -> P {
30        cast_ptr!(T, P, self)
31    }
32
33    fn cast_int<T: Integer>(self) -> T {
34        cast_int!(self => T)
35    }
36}
37
38#[cfg_attr(docsrs, doc(fake_variadic))]
39#[cfg_attr(
40    docsrs,
41    doc = "This trait is implemented for function pointers with up to 12 arguments."
42)]
43impl<A1, R> Primitive for fn(A1) -> R {}
44
45#[cfg_attr(docsrs, doc(fake_variadic))]
46#[cfg_attr(
47    docsrs,
48    doc = "This trait is implemented for function pointers with up to 12 arguments."
49)]
50impl<A1, R> FunctionPointer for fn(A1) -> R {
51    type Args = (A1,);
52    type Return = R;
53
54    fn call(self, args: Self::Args) -> Self::Return {
55        self(args.0)
56    }
57
58    fn cast_ptr<T: Sized, P: Pointer<T>>(self) -> P {
59        cast_ptr!(T, P, self)
60    }
61
62    fn cast_int<T: Integer>(self) -> T {
63        cast_int!(self => T)
64    }
65}
66
67macro_rules! impl_fn {
68    ($($args:tt $n:tt),*) => {
69        #[cfg_attr(docsrs, doc(hidden))]
70        impl<$($args,)* R> Primitive for fn($($args,)*) -> R {}
71        #[cfg_attr(docsrs, doc(hidden))]
72        impl<$($args,)* R> FunctionPointer for fn($($args,)*) -> R {
73            type Args = ($($args,)*);
74            type Return = R;
75
76            fn call(self, args: Self::Args) -> Self::Return {
77                self($(args.$n),*)
78            }
79
80            fn cast_ptr<T: Sized, P: Pointer<T>>(self) -> P {
81                cast_ptr!(T, P, self)
82            }
83
84            fn cast_int<T: Integer>(self) -> T {
85                cast_int!(self => T)
86            }
87        }
88    }
89}
90
91/*
92for n in range(2, 13):
93    print(f"impl_fn!({', '.join(f'A{i + 1} {i}' for i in range(n))});")
94*/
95impl_fn!(A1 0, A2 1);
96impl_fn!(A1 0, A2 1, A3 2);
97impl_fn!(A1 0, A2 1, A3 2, A4 3);
98impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4);
99impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4, A6 5);
100impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4, A6 5, A7 6);
101impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4, A6 5, A7 6, A8 7);
102impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4, A6 5, A7 6, A8 7, A9 8);
103impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4, A6 5, A7 6, A8 7, A9 8, A10 9);
104impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4, A6 5, A7 6, A8 7, A9 8, A10 9, A11 10);
105impl_fn!(A1 0, A2 1, A3 2, A4 3, A5 4, A6 5, A7 6, A8 7, A9 8, A10 9, A11 10, A12 11);
106
107#[cfg(test)]
108mod test {
109    use super::FunctionPointer;
110
111    fn f0() {}
112    fn f1<T>(a: T) -> T {
113        a
114    }
115    fn f2<T1, T2>(a: T1, b: T2) -> (T1, T2) {
116        (a, b)
117    }
118    fn f3<T1, T2, T3>(a: T1, b: T2, c: T3) -> (T1, T2, T3) {
119        (a, b, c)
120    }
121
122    #[test]
123    fn test_call_0_args() {
124        (f0 as fn() -> _).call(());
125    }
126
127    #[test]
128    fn test_call_1_arg() {
129        assert_eq!((f1 as fn(usize) -> _).call((1337,)), (1337usize));
130    }
131
132    #[test]
133    fn test_call_2_args() {
134        assert_eq!(
135            (f2 as fn(char, [u8; 2]) -> _).call(('x', [2, 3])),
136            ('x', [2u8, 3u8])
137        );
138    }
139
140    #[test]
141    fn test_call_3_args() {
142        assert_eq!(
143            (f3 as fn(usize, &'static str, bool) -> _).call((1, "b", false)),
144            (1usize, "b", false)
145        );
146    }
147}