hooks_core/
macro_impl.rs

1#[doc(hidden)]
2#[macro_export]
3macro_rules! __impl_unexpected_token {
4    () => {};
5}
6
7#[doc(hidden)]
8#[macro_export]
9macro_rules! __expand_or {
10    ([]$($defaults:tt)*) => {
11        $($defaults)*
12    };
13    ([$($t:tt)+]$($defaults:tt)*) => {
14        $($t)*
15    };
16}
17
18#[doc(hidden)]
19#[macro_export]
20macro_rules! __impl_fn_hook_body_finish_as_closure {
21    (
22        // options
23        [
24            $(append_args_pat! { $($append_args_pat:tt)+ })?
25        ]
26        [$($args_pat:tt)*]
27        $body:tt
28    ) => {
29        move |
30            $($args_pat)*
31            $(, $($append_args_pat)+ )?
32        | $body
33    };
34}
35
36#[doc(hidden)]
37#[macro_export]
38macro_rules! __impl_fn_hook_body_finish {
39    (
40        [
41            $options:tt
42            $rest_ids:tt
43        ]
44        [] // used_ids
45        [$($transformed_code:tt)*]
46    ) => {
47        $crate::__impl_fn_hook_body_finish_as_closure! {
48            $options
49            [_: ::core::pin::Pin<&mut $crate::HookTuple<()>>]
50            { $($transformed_code)* }
51        }
52    };
53    (
54        [
55            $options:tt
56            $rest_ids:tt
57        ]
58        [$used_id:ident] // used_ids
59        [$($transformed_code:tt)*]
60    ) => {
61        $crate::__impl_fn_hook_body_finish_as_closure! {
62            $options
63            [$used_id : ::core::pin::Pin<&mut _>]
64            { $($transformed_code)* }
65        }
66    };
67    (
68        [
69            $options:tt
70            $rest_ids:tt
71        ]
72        [$($used_id:ident)+] // used_ids
73        [$($transformed_code:tt)*]
74    ) => {
75        $crate::__impl_fn_hook_body_finish_as_closure! {
76            $options
77            [__hooks_hook_data: ::core::pin::Pin<&mut _>]
78            {
79            // The following statement could be changed to:
80            // $crate::__impl_pin_project_hook_tuple!(__hooks_hook_data, $($used_id,)+);
81            // But this would reduce max tokens and might cause recursion limit to user code.
82
83            // SAFETY: pin projection
84            let ($($used_id,)+) = unsafe {
85                let $crate::HookTuple(($($used_id,)+)) = ::core::pin::Pin::get_unchecked_mut(__hooks_hook_data);
86                ($(
87                    ::core::pin::Pin::new_unchecked($used_id),
88                )+)
89            };
90
91            $($transformed_code)*
92            }
93        }
94    };
95}
96
97#[doc(hidden)]
98#[macro_export]
99macro_rules! __impl_fn_hook_body_hook_resolved {
100    (
101        [$id:ident = $($e:tt)+]
102        $state:tt
103        [$($used_ids:ident)*]
104        $hook_ident:ident
105        [$($transformed_code:tt)*]
106        $code:tt
107    ) => {
108        $crate::__impl_fn_hook_body! {
109            $state
110            [$($used_ids)* $id]
111            [
112                $($transformed_code)*
113                $crate::UpdateHookUninitialized::$hook_ident(
114                    $($e)+,
115                    $id
116                )
117            ]
118            $code
119            $code
120        }
121    };
122    (
123        [$($e:tt)+]
124        [
125            $options:tt
126            [$id:ident $($rest_ids:ident)*]
127        ]
128        [$($used_ids:ident)*]
129        $hook_ident:ident
130        [$($transformed_code:tt)*]
131        $code:tt
132    ) => {
133        $crate::__impl_fn_hook_body! {
134            [
135                $options
136                [$($rest_ids)*]
137            ]
138            [$($used_ids)* $id]
139            [
140                $($transformed_code)*
141                $crate::UpdateHookUninitialized::$hook_ident(
142                    $($e)+,
143                    $id
144                )
145            ]
146            $code
147            $code
148        }
149    };
150    ( ($($e:tt)*) $($other:tt)* ) => {
151        $crate::__impl_fn_hook_body_hook_resolved! { [$($e)*] $($other)* }
152    };
153    ( {$($e:tt)*} $($other:tt)* ) => {
154        $crate::__impl_fn_hook_body_hook_resolved! { [$($e)*] $($other)* }
155    };
156}
157
158#[doc(hidden)]
159#[macro_export]
160macro_rules! __impl_fn_hook_body {
161    (
162        $state:tt
163        $used_ids:tt
164        $transformed_code:tt
165        {}{} // code is empty
166    ) => {
167        $crate::__impl_fn_hook_body_finish! {
168            $state
169            $used_ids
170            $transformed_code
171        }
172    };
173    (
174        $state:tt $used_ids:tt $transformed_code:tt
175        {h ! $e:tt $($code:tt)*} { $hook_ident:ident ! $_e:tt $($_code:tt)* } // code
176    ) => {
177        $crate::__impl_fn_hook_body_hook_resolved! {
178            $e
179            $state
180            $used_ids
181            $hook_ident
182            $transformed_code
183            {$($code)*} // code
184        }
185    };
186    // + h![]
187    (
188        $state:tt $used_ids:tt [$($transformed_code:tt)*]
189        {$t0:tt h ! $e:tt $($code:tt)*} {$_t0:tt $hook_ident:ident ! $_e:tt $($_code:tt)* } // code
190    ) => {
191        $crate::__impl_fn_hook_body_hook_resolved! {
192            $e
193            $state
194            $used_ids
195            $hook_ident
196            [$($transformed_code)* $t0]
197            {$($code)*} // code
198        }
199    };
200    // 1 + h![]
201    (
202        $state:tt $used_ids:tt [$($transformed_code:tt)*]
203        {$t0:tt $t1:tt h ! $e:tt $($code:tt)*} {$_t0:tt $_t1:tt $hook_ident:ident ! $_e:tt $($_code:tt)* } // code
204    ) => {
205        $crate::__impl_fn_hook_body_hook_resolved! {
206            $e
207            $state
208            $used_ids
209            $hook_ident
210            [$($transformed_code)* $t0 $t1]
211            {$($code)*} // code
212        }
213    };
214    // + 1 + h![]
215    (
216        $state:tt $used_ids:tt [$($transformed_code:tt)*]
217        {$t0:tt $t1:tt $t2:tt h ! $e:tt $($code:tt)*} {$_t0:tt $_t1:tt $_t2:tt $hook_ident:ident ! $_e:tt $($_code:tt)* } // code
218    ) => {
219        $crate::__impl_fn_hook_body_hook_resolved! {
220            $e
221            $state
222            $used_ids
223            $hook_ident
224            [$($transformed_code)* $t0 $t1 $t2]
225            {$($code)*} // code
226        }
227    };
228    // 4
229    (
230        $state:tt $used_ids:tt
231        [$($transformed_code:tt)*]
232        {$t0:tt $t1:tt $t2:tt $t3:tt $($code:tt)*} $_code:tt // code
233    ) => {
234        $crate::__impl_fn_hook_body! {
235            $state $used_ids
236            [$($transformed_code)* $t0 $t1 $t2 $t3]
237            {$($code)*} {$($code)*}
238        }
239    };
240    // 3
241    (
242        $state:tt $used_ids:tt
243        [$($transformed_code:tt)*]
244        {$t0:tt $t1:tt $t2:tt $($code:tt)*} $_code:tt // code
245    ) => {
246        $crate::__impl_fn_hook_body! {
247            $state $used_ids
248            [$($transformed_code)* $t0 $t1 $t2]
249            {$($code)*} {$($code)*}
250        }
251    };
252    // 2
253    (
254        $state:tt $used_ids:tt
255        [$($transformed_code:tt)*]
256        {$t0:tt $t1:tt $($code:tt)*} $_code:tt // code
257    ) => {
258        $crate::__impl_fn_hook_body! {
259            $state $used_ids
260            [$($transformed_code)* $t0 $t1]
261            {$($code)*} {$($code)*}
262        }
263    };
264    (
265        $state:tt $used_ids:tt
266        [$($transformed_code:tt)*]
267        {$t0:tt $($code:tt)*} $_code:tt // code
268    ) => {
269        $crate::__impl_fn_hook_body! {
270            $state $used_ids
271            [$($transformed_code)* $t0]
272            {$($code)*} {$($code)*}
273        }
274    };
275}
276
277#[doc(hidden)]
278#[macro_export]
279macro_rules! __impl_hook_fn_bounds_resolved {
280    ($hook_bounds:tt #[hook $(($($options:tt)*))? ] $($rest:tt)*) => {
281        $crate::__private::parse_item_fn! {
282            on_finish { $crate::__impl_hook_fn_item_fn_parsed! }
283            prepend { $hook_bounds ($($($options)*)?) }
284            input {$($rest)*}
285        }
286    };
287    ($hook_bounds:tt $($rest:tt)*) => {
288        $crate::__private::parse_item_fn! {
289            on_finish { $crate::__impl_hook_fn_item_fn_parsed! }
290            prepend {$hook_bounds ()}
291            input {$($rest)*}
292        }
293    };
294}
295
296#[doc(hidden)]
297#[macro_export]
298macro_rules! __impl_capture_lifetimes {
299    (
300        [$($prepend:tt)*]
301        {}
302    ) => {
303        $($prepend)*
304    };
305    (
306        [$($prepend:tt)*]
307        { $hook_bound:lifetime $(+)? }
308    ) => {
309        $($prepend)*
310        + $crate::Captures<
311            & $hook_bound ()
312        >
313    };
314    (
315        [$($prepend:tt)*]
316        { $hook_bound:lifetime $(+ $hook_bounds:lifetime)+ $(+)? }
317    ) => {
318        $($prepend)*
319        + $crate::Captures<(
320            & $hook_bound (),
321            $(& $hook_bounds (),)+
322        )>
323    };
324}
325
326#[doc(hidden)]
327#[macro_export]
328macro_rules! __impl_hook_fn_item_fn_parsed {
329    (
330        $hook_bounds:tt
331        $method_path:tt
332        item_fn {
333            $(outer_attrs $outer_attrs:tt)?
334            vis $vis:tt
335            sig $sig:tt
336            block { $fn_body:tt }
337        }
338        rest {}
339    ) => {
340        $crate::__private::consume_inner_attrs! {
341            on_finish {$crate::__impl_hook_fn_item_fn_body_parsed!}
342            prepend {
343                $hook_bounds
344                $method_path
345                item_fn {
346                    $(outer_attrs $outer_attrs)?
347                    vis $vis
348                    sig $sig
349                }
350            }
351            input $fn_body
352        }
353    };
354}
355
356#[doc(hidden)]
357#[macro_export]
358macro_rules! __impl_hook_fn_item_fn_body_parsed {
359    (
360        { $($hook_bounds:tt)* } // { 'a + 'b }
361        ($($method_path:ident),* $(,)?)
362        item_fn {
363            $(outer_attrs { $($outer_attrs:tt)* })?
364            vis { $vis:vis }
365            sig {
366                fn { $fn:tt }
367                ident { $name:ident }
368                $(
369                    lt {<}
370                    parsed_generics {
371                        generics      { $($generic_params:tt)* }
372                        impl_generics $impl_generics:tt
373                        type_generics { $($type_generics:tt)* }
374                        generics_info $generics_info:tt
375                    }
376                    gt {>}
377                )?
378                paren_inputs { $paren_inputs:tt }
379                output { $(-> $ret_ty:ty)? }
380                $(where_clause { $($where_clause:tt)* })?
381            }
382        }
383        inner_attrs { $($inner_attrs:tt)* }
384        rest { $($stmts:tt)* }
385    ) => {
386        $($($outer_attrs)*)?
387        $vis fn $name
388        <$($($generic_params)*)?>
389        $paren_inputs
390        -> $crate::UpdateHookUninitialized![
391            @ extract_lifetimes_from_generics {
392                value! { $crate::__private::expand_or![[$($ret_ty)?]()] }
393                $(generics_info! $generics_info)?
394                bounds! { $($hook_bounds)* }
395            }
396        ]
397        $($where_clause)*
398        {
399            $($inner_attrs)*
400
401            #[allow(unused_imports)]
402            use $crate::prelude_h::*;
403
404            enum __HooksImplNever {}
405
406            struct __HooksValueOfThisHook <$($($generic_params)*)?>
407            $($where_clause)*
408            {
409                __: (__HooksImplNever, $($crate::__impl_phantoms! $generics_info)?)
410            }
411
412            impl<
413                'hook,
414                $($($generic_params)*)?
415            > $crate::HookValue<'hook> for __HooksValueOfThisHook <$($($type_generics)*)?>
416            $($where_clause)*
417            {
418                type Value = $crate::__private::expand_or![[$($ret_ty)?]()];
419            }
420
421            $crate::fn_hook::use_fn_hook $(::$method_path)*
422            ::<
423                __HooksValueOfThisHook <$($($type_generics)*)?>
424                , _, _
425            >
426            (
427                $crate::transform_hook_fn_body_as_closure!(
428                    []
429                    {$($stmts)*}
430                )
431            )
432        }
433    };
434}
435
436#[doc(hidden)]
437#[macro_export]
438macro_rules! __impl_hook_method_poll_next_update {
439    (
440        $(#$fn_attr:tt)*
441        $fn_name:ident () $fn_body:tt
442    ) => {
443        $crate::__impl_hook_method_poll_next_update! {
444            $(#$fn_attr)*
445            $fn_name (self, _: _) $fn_body
446        }
447    };
448    (
449        $(#$fn_attr:tt)*
450        $fn_name:ident (
451            $self0:ident
452            $($self1:ident)?
453            $(,)?
454        ) $fn_body:tt
455    ) => {
456        $crate::__impl_hook_method_poll_next_update! {
457            $(#$fn_attr)*
458            $fn_name ($self0 $($self1)?, _: _) $fn_body
459        }
460    };
461    (
462        $(#$fn_attr:tt)*
463        $fn_name:ident (
464            $self0:ident
465            $($self1:ident)?,
466            $cx_pat:tt : _ $(,)?
467        ) $fn_body:tt
468    ) => {
469        $(#$fn_attr)*
470        fn $fn_name(
471            $self0 $($self1)? : ::core::pin::Pin<&mut Self>,
472            $cx_pat: &mut ::core::task::Context<'_>,
473        ) -> ::core::task::Poll<bool> $fn_body
474    };
475}
476
477#[doc(hidden)]
478#[macro_export]
479macro_rules! __impl_trait_hook_unmount {
480    (
481        ([$($generics:tt)*][$ty:ty][$( $($where_clause:tt)+ )?])[
482            $(#$fn_attr:tt)*
483            $fn_name:ident
484            ($($args:tt)*)
485            {}
486        ]
487    ) => {
488        $crate::__impl_unexpected_token! { $($args)* }
489
490        $(#$fn_attr)*
491        impl<$($generics)*> $crate::HookUnmount for $ty $(where $($where_clause)*)? {}
492    };
493    (
494        ([$($generics:tt)*][$ty:ty][$( $($where_clause:tt)+ )?])[
495            $(#$fn_attr:tt)*
496            $fn_name:ident
497            ( $($self_arg:ident)+ $(,)? )
498            $fn_body:tt
499        ]
500    ) => {
501        impl<$($generics)*> $crate::HookUnmount for $ty $(where $($where_clause)*)? {
502            $(#$fn_attr)*
503            fn $fn_name(
504                $($self_arg)+ : ::core::pin::Pin<&mut Self>
505            ) $fn_body
506        }
507    };
508}
509
510#[doc(hidden)]
511#[macro_export]
512macro_rules! __impl_hook_with_method {
513    (
514        poll_next_update([$($generics:tt)*][$ty:ty][$( $($where_clause:tt)+ )?]) $fn_data:tt
515    ) => {
516        impl<$($generics)*> $crate::HookPollNextUpdate for $ty $(where $($where_clause)*)? {
517            $crate::__impl_hook_method_poll_next_update! $fn_data ;
518        }
519    };
520    (
521        unmount $types:tt $fn_data:tt
522    ) => {
523        $crate::__impl_trait_hook_unmount! {
524            $types $fn_data
525        }
526    };
527    (
528        use_hook([$($generics:tt)*][$ty:ty][$( $($where_clause:tt)+ )?])[
529            $(#$fn_attr:tt)*
530            $fn_name:ident
531            ($self0:ident $($self1:ident)? $(,)?)
532            $(-> $ret_ty:ty)?
533            {
534                $($fn_body:tt)*
535            }
536        ]
537    ) => {
538        impl<'hook, $($generics)*> $crate::HookValue<'hook> for $ty $(where $($where_clause)*)? {
539            type Value = $crate::__expand_or![
540                [$($ret_ty)?]
541                ()
542            ];
543        }
544
545        impl<$($generics)*> $crate::Hook for $ty $(where $($where_clause)*)? {
546            $(#$fn_attr)*
547            fn $fn_name(
548                $self0 $($self1)? : ::core::pin::Pin<&mut Self>
549            ) -> <Self as $crate::HookValue<'_>>::Value
550            {$($fn_body)*}
551        }
552    };
553    (
554        into_hook([$($generics:tt)*][$ty:ty][$( $($where_clause:tt)+ )?])[
555            $(#$fn_attr:tt)*
556            $fn_name:ident
557            ($self0:ident $($self1:ident)?)
558            -> $hook_ty:ty
559            {$($fn_body:tt)*}
560        ]
561    ) => {
562        impl<$($generics)*> $crate::IntoHook for $ty $(where $($where_clause)*)? {
563            type Hook = $hook_ty;
564            $(#$fn_attr)*
565            fn $fn_name(
566                $self0 $($self1)?
567            ) -> Self::Hook
568            {$($fn_body)*}
569        }
570    };
571    (
572        update_hook([$($generics:tt)*][$ty:ty][$( $($where_clause:tt)+ )?])[
573            $(#$fn_attr:tt)*
574            $fn_name:ident
575            ($self0:ident $($self1:ident)?, $hook0:ident $($hook1:ident)? : _ $(,)?)
576            $fn_body:tt
577        ]
578    ) => {
579        impl<$($generics)*> $crate::UpdateHook for $ty $(where $($where_clause)*)? {
580            $(#$fn_attr)*
581            fn $fn_name(
582                $self0 $($self1)?,
583                $hook0 $($hook1)? : ::core::pin::Pin<&mut Self::Hook>,
584            ) $fn_body
585        }
586    };
587    (
588        h([$($generics:tt)*][$ty:ty][$( $($where_clause:tt)+ )?])[
589            $(#$fn_attr:tt)*
590            $fn_name:ident
591            ($self0:ident $($self1:ident)?, $hook0:ident $($hook1:ident)? : $ty_uninitialized:ty)
592            $(-> $explicit_value:ty)?
593            {$($fn_body:tt)*}
594        ]
595    ) => {
596        impl<$($generics)*> $crate::UpdateHookUninitialized for $ty $(where $($where_clause)*)? {
597            type Uninitialized = $ty_uninitialized;
598            $(#$fn_attr)*
599            fn $fn_name(
600                $self0 $($self1)?,
601                $hook0 $($hook1)? : ::core::pin::Pin<&mut Self::Uninitialized>,
602            ) -> $crate::__expand_or![
603                [$($explicit_value)?]
604                <Self::Hook as $crate::HookValue<'_>>::Value
605            ]
606            {$($fn_body)*}
607        }
608    };
609}
610
611#[doc(hidden)]
612#[macro_export]
613macro_rules! __impl_hook_methods {
614    (
615        $data:tt
616        $(
617            $fn_name:ident
618            $fn_data:tt
619        )*
620    ) => {$(
621        $crate::__impl_hook_with_method! {
622            $fn_name
623            $data
624            $fn_data
625        }
626    )*};
627}
628
629#[doc(hidden)]
630#[macro_export]
631macro_rules! __impl_phantoms {
632    (
633        $($generics_info:tt)*
634    ) => {
635        ($(
636            $crate::__impl_phantom! $generics_info,
637        )*)
638    };
639}
640
641#[doc(hidden)]
642#[macro_export]
643macro_rules! __impl_phantom {
644    (
645        $(lifetime_attrs $attrs:tt)?
646        lifetime {$lt:lifetime}
647        $($rest:tt)*
648    ) => {
649        ::core::marker::PhantomData::<&$lt()>
650    };
651    (
652        $(const_attrs $attrs:tt)?
653        const {const}
654        name {$name:ident}
655        $($rest:tt)*
656    ) => {
657        ()
658    };
659    (
660        $(type_attrs $attrs:tt)?
661        name {$tp:ident}
662        $($rest:tt)*
663    ) => {
664        ::core::marker::PhantomData::<$tp>
665    };
666}
667
668#[doc(hidden)]
669#[macro_export]
670macro_rules! __impl_impl_hook {
671    (
672        generic_params $generic_params:tt
673        for_ty $for_ty:tt
674        $(where_clause $where_clause:tt)?
675        rest { $body:tt }
676    ) => {
677        $crate::__impl_impl_hook! {
678            generic_params $generic_params
679            for_ty $for_ty
680            $(where_clause $where_clause)?
681            body $body
682        }
683    };
684    (
685        generic_params { $($generic_params:tt)* }
686        for_ty { $ty:ty }
687        $(where_clause { $( where $($where_clause:tt)*)? })?
688        body {
689            $(
690                $(#$fn_attr:tt)*
691                fn $fn_name:ident $args:tt $(-> $fn_ret_ty:ty)?
692                {$($impl_hook:tt)*}
693            )*
694        }
695    ) => {
696        $crate::__impl_hook_methods! {
697            (
698                [$($generic_params)*]
699                [$ty]
700                [$($($($where_clause)*)?)?]
701            )
702            $(
703                $fn_name [
704                    $(#$fn_attr)*
705                    $fn_name $args $(-> $fn_ret_ty)?
706                    {$($impl_hook)*}
707                ]
708            )*
709        }
710    };
711}
712
713#[doc(hidden)]
714#[macro_export]
715macro_rules! __impl_impl_hook_generics_consumed {
716    (
717        before_gt $before_gt:tt
718        gt_and_rest {
719            > $ty:ty {
720                $($rest:tt)*
721            }
722        }
723    ) => {
724        $crate::__impl_impl_hook! {
725            generic_params $before_gt
726            for_ty { $ty }
727            body { $($rest)* }
728        }
729    };
730    (
731        before_gt $before_gt:tt
732        gt_and_rest {
733            > $ty:ty
734            where $($rest:tt)*
735        }
736    ) => {
737        $crate::__private::consume_optional_where_clause! {
738            on_finish {$crate::__impl_impl_hook!}
739            prepend {
740                generic_params $before_gt
741                for_ty { $ty }
742            }
743            input { where $($rest)* }
744        }
745    };
746}
747
748#[doc(hidden)]
749#[macro_export]
750macro_rules! __impl_pin_project_hook_tuple {
751    ($hook_tuple:ident, $($used_id:ident),+ $(,)?) => {
752        // SAFETY: pin projection
753        let ($($used_id,)+) = unsafe {
754            let $crate::HookTuple(($($used_id,)+)) = ::core::pin::Pin::get_unchecked_mut($hook_tuple);
755            ($(
756                ::core::pin::Pin::new_unchecked($used_id),
757            )+)
758        };
759    };
760}