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