Macro impl_hook

Source
macro_rules! impl_hook {
    (
        // this empty generic helps with rustfmt
        impl <$(__)?> $($rest:tt)*
    ) => { ... };
    (
        impl < $($generics_and_rest:tt)*
    ) => { ... };
    (
        impl $($rest:tt)*
    ) => { ... };
}
Expand description

Easily impl traits.

For example:

struct OutputOnce<T>(pub Option<T>);

impl_hook!(
    impl<T: Unpin> OutputOnce<T> {
        /// HookUnmount is implemented with default `fn unmount()`
        fn unmount() {}

        /// HookPollNextUpdate is implemented
        fn poll_next_update(self, _cx: _) {
            std::task::Poll::Ready(self.get_mut().0.is_some())
        }

        /// HookValue and Hook is implemented
        /// HookValue::Value is `&'hook mut Option<T>`
        #[inline]
        fn use_hook(self) -> &'hook mut Option<T> {
            &mut self.get_mut().0
        }
    }
);

§Just write the methods of the traits you want to impl in one impl block

impl_hook!(
    impl<__> MyType { // <__> helps rustfmt to format this macro.
        // write methods here
    }
);

Generics and where clause are supported.

impl_hook!(
    impl<'a, T: Clone + Default, F: FnMut(&T) -> T> MyType<'a, T, F>
    where
        T: Sized,
    {
        // write methods here
    }
);

§Supported traits

impl HookUnmount with unmount

With default implementation:

impl_hook!(
    impl<__> MyType {
        fn unmount() {}
    }
);

With custom implementation:

impl_hook!(
    impl<__> MyType {
        fn unmount(self) {
            self.do_something();
        }
    }
);

impl HookPollNextUpdate with poll_next_update

Argument cx is of type &mut std::task::Context<'_>. The return type is std::task::Poll<bool>

impl_hook!(
    impl<__> MyType {
        fn poll_next_update(self, cx: _) {
            self.project().inner.poll(cx)
        }
    }
);

impl HookValue and Hook with use_hook

Note that Hook requires HookUnmount + HookPollNextUpdate

impl_hook!(
    impl<__> MyType {
        fn unmount() {}
        fn poll_next_update(self, cx: _) { todo!() }
        fn use_hook(self) -> MyValueType {
            self.0
        }
    }
);

impl IntoHook with into_hook

impl_hook!(
    impl<__> UseMyHook {
        fn into_hook(self) -> MyHook {
            MyHook(self.0)
        }
    }
);

impl UpdateHook with update_hook

Note that UpdateHook requires IntoHook.

impl_hook!(
    impl<__> UseMyHook {
        fn into_hook(self) -> MyHook {
            MyHook(self.0)
        }
        fn update_hook(self, mut hook: _) {
            hook.0 = self.0
        }
    }
);

impl UpdateHookUninitialized with h

Note that UpdateHookUninitialized requires UpdateHook + IntoHook.

impl_hook!(
    impl<__> UseMyHook {
        fn into_hook(self) -> MyHook {
            MyHook(self.0)
        }
        fn update_hook(self, mut hook: _) {
            hook.0 = self.0
        }
        fn h(self, mut hook: MyHookUninitialized) {
            hook.0.get_or_insert(self.0);
        }
    }
);