Macro hooks_core::impl_hook
source · macro_rules! impl_hook { ( type For $(<$( $($lt:lifetime)? $($tp1:ident $($tp2:ident)?)? $( : $($bound_lt:lifetime)? $(+ $bounds_lt:lifetime)* $( $( + $({$plus_ignore:tt })? )? $( ? $([$relax_ignore:tt])? )? $bounds:path )* )? ),* >)? = $ty:ty $( where __![$($($where_clause:tt)+)?]: __ $(,)? )? ; $( $(#$fn_attr:tt)* fn $fn_name:ident $args:tt $(-> $fn_ret_ty:ty)? {$($impl_hook: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
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
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)
}
);
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_hook!(
type For = UseMyHook;
fn into_hook(self) -> MyHook {
MyHook(self.0)
}
);
impl UpdateHook
with update_hook
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
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);
}
);