1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#![warn(missing_docs)]
use crate::abitype;
use crate::boxed;
use crate::task::Task;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Callback<F>
where
F: Copy,
{
captures: boxed::Captures,
entry_point: F,
}
impl<F> Callback<F>
where
F: Copy,
{
pub fn captures(&self) -> boxed::Captures {
self.captures
}
}
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct EntryPointAbiType {
pub params: &'static [abitype::AbiType],
pub ret: abitype::RetAbiType,
}
pub trait EncodeEntryPointAbiType: Copy {
const ENTRY_POINT_ABI_TYPE: EntryPointAbiType;
}
macro_rules! define_generic_entry_point {
( $( $generic_param:ident ),* ) => {
impl<R, $( $generic_param ),*> EncodeEntryPointAbiType for for<'s> extern "C" fn(&'s mut Task, captures: boxed::Captures, $( $generic_param ),* ) -> R
where
R: abitype::EncodeRetAbiType,
$( $generic_param: abitype::EncodeAbiType ),*
{
const ENTRY_POINT_ABI_TYPE: EntryPointAbiType = EntryPointAbiType {
params: &[$( $generic_param::ABI_TYPE ),*],
ret: R::RET_ABI_TYPE,
};
}
impl<R, $( $generic_param ),*> Callback<for<'s> extern "C" fn(&'s mut Task, captures: boxed::Captures, $( $generic_param ),* ) -> R>
where
R: abitype::EncodeRetAbiType,
$( $generic_param: abitype::EncodeAbiType ),*
{
#[allow(unused)]
#[allow(non_snake_case)]
#[allow(clippy::too_many_arguments)]
pub fn apply(&self, task: &mut Task, $( $generic_param: $generic_param ),*) -> R {
(self.entry_point)(task, self.captures, $( $generic_param ),*)
}
}
}
}
define_generic_entry_point!();
define_generic_entry_point!(A);
define_generic_entry_point!(A, B);
define_generic_entry_point!(A, B, C);
define_generic_entry_point!(A, B, C, D);
define_generic_entry_point!(A, B, C, D, E);
define_generic_entry_point!(A, B, C, D, E, F);
define_generic_entry_point!(A, B, C, D, E, F, G);
define_generic_entry_point!(A, B, C, D, E, F, G, H);
#[cfg(test)]
mod test {
use super::*;
use crate::boxed::refs::*;
#[test]
fn encode_entry_point_abi_type() {
let empty_abi_type = <extern "C" fn(&mut Task, boxed::Captures) as EncodeEntryPointAbiType>::ENTRY_POINT_ABI_TYPE;
assert_eq!(abitype::RetAbiType::Void, empty_abi_type.ret);
assert!(empty_abi_type.params.is_empty());
let two_param_abi_type = <extern "C" fn(
&mut Task,
boxed::Captures,
i64,
Gc<boxed::Int>,
) -> bool as EncodeEntryPointAbiType>::ENTRY_POINT_ABI_TYPE;
assert_eq!(
abitype::AbiType::Bool.into_ret_abi_type(),
two_param_abi_type.ret
);
assert_eq!(
&[abitype::AbiType::Int, boxed::TypeTag::Int.into()],
two_param_abi_type.params
);
}
}