Macro hooks_core::impl_hook

source ·
macro_rules! impl_hook {
    (
        type For $(<>)? = $($rest:tt)*
    ) => { ... };
    (
        type For < $($rest:tt)*
    ) => { ... };
}
Expand description

Easily impl traits.

For example:

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

impl_hook!(
    type For<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
    }
);

§Declare the type to impl for with type For = ...;

impl_hook!(
    type For = MyType;
);

You can declare generics and bounds.

impl_hook!(
    type For<'a, T: Clone + Default, F: FnMut(&T) -> T> = MyType<'a, T, F>;
);

Parsing with macro_rules is limited. For example, complex bounds are not supported.

impl_hook!(
    type For<F: for<'a> FnMut(&'a str) -> &'a str> = MyType<F>;
);

You can move complex bounds to a special where clause where __![...]: __

impl_hook!(
    type For<F> = MyType<F>
        where __![F: for<'a> FnMut(&'a str) -> &'a str]: __;
);

After declaring the type, you can easily impl traits for this type with methods.

§Supported traits

impl HookUnmount with unmount

With default implementation:

impl_hook!(
    type For = MyType;
    fn unmount() {}
);

With custom implementation:

impl_hook!(
    type For = 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!(
    type For = 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!(
    type For = MyType;
    fn unmount() {}
    fn poll_next_update(self, cx: _) { todo!() }
    fn use_hook(self) -> MyValueType {
        self.0
    }
);

impl IntoHook with into_hook

impl_hook!(
    type For = UseMyHook;
    fn into_hook(self) -> MyHook {
        MyHook(self.0)
    }
);

impl UpdateHook with update_hook

Note that UpdateHook requires IntoHook.

impl_hook!(
    type For = 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!(
    type For = 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);
    }
);