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
use super::*;

#[derive(Default)]
pub struct HookTuple<T>(pub T);

crate::impl_hook![
    type For = HookTuple<()>;
    fn unmount() {}
    fn poll_next_update(self) {
        std::task::Poll::Ready(false)
    }
];

macro_rules! impl_tuple {
        // ignore zero length
        () => {};
        ($($v:ident ,)+) => {
            impl_tuple! {
                - $($v ,)+
            }

            impl<$($v : HookUnmount ,)+> HookUnmount for HookTuple<($($v,)+)> {
                fn unmount(self: std::pin::Pin<&mut Self>) {
                    #[allow(non_snake_case)]
                    // SAFETY: pin projection
                    let ($($v,)+) = unsafe {
                        #[allow(non_snake_case)]
                        let HookTuple(($($v,)+)) = self.get_unchecked_mut();
                        ($(
                            ::core::pin::Pin::new_unchecked($v)
                        ,)+)
                    };
                    $(
                        <$v as HookUnmount>::unmount($v);
                    )+
                }
            }

            impl<$($v : HookPollNextUpdate ,)+> HookPollNextUpdate for HookTuple<($($v,)+)> {
                fn poll_next_update(
                    self: std::pin::Pin<&mut Self>,
                    cx: &mut std::task::Context<'_>,
                ) -> std::task::Poll<bool> {
                    #[allow(non_snake_case)]
                    // SAFETY: pin projection
                    let ($($v,)+) = unsafe {
                        #[allow(non_snake_case)]
                        let HookTuple(($($v,)+)) = self.get_unchecked_mut();
                        ($(
                            ::core::pin::Pin::new_unchecked($v)
                        ,)+)
                    };

                    #[allow(non_snake_case)]
                    #[allow(unused_variables)]
                    match ($(
                        $v.poll_next_update(cx)
                    ,)+) {
                        ($($v @ std::task::Poll::Ready(false),)+) => std::task::Poll::Ready(false),
                        #[allow(unreachable_patterns)]
                        ($($v @ (std::task::Poll::Ready(false) | std::task::Poll::Pending),)+) => std::task::Poll::Pending,
                        _ => std::task::Poll::Ready(true),
                    }
                }
            }
        };
        (
            - $v0:ident,
            $($v:ident ,)*
        ) => {
            impl_tuple! {
                $($v ,)*
            }
        };
    }

impl_tuple!(T9, T8, T7, T6, T5, T4, T3, T2, T1, T0,);