@@ -314,91 +314,6 @@ pub fn state(_attr: TokenStream, item: TokenStream) -> TokenStream {
314
314
quote ! ( #state) . into ( )
315
315
}
316
316
317
- struct ParsedHooks {
318
- hooks : ItemStruct ,
319
- }
320
-
321
- impl Parse for ParsedHooks {
322
- fn parse ( input : ParseStream ) -> Result < Self > {
323
- let hooks: ItemStruct = input. parse ( ) ?;
324
- Ok ( Self { hooks } )
325
- }
326
- }
327
-
328
- impl ToTokens for ParsedHooks {
329
- fn to_tokens ( & self , tokens : & mut proc_macro2:: TokenStream ) {
330
- let hooks = & self . hooks ;
331
- let name = & hooks. ident ;
332
-
333
- let status_vars = hooks. fields . iter ( ) . map ( |field| {
334
- let field_name = & field. ident ;
335
- quote ! { let #field_name = std:: pin:: Pin :: new( & mut self . #field_name) . poll_change( cx) ; }
336
- } ) ;
337
- let returns = hooks. fields . iter ( ) . map ( |field| {
338
- let field_name = & field. ident ;
339
- quote ! {
340
- if #field_name. is_ready( ) {
341
- return std:: task:: Poll :: Ready ( ( ) ) ;
342
- }
343
- }
344
- } ) ;
345
- let pre_component_updates = hooks. fields . iter ( ) . map ( |field| {
346
- let field_name = & field. ident ;
347
- quote ! {
348
- self . #field_name. pre_component_update( updater) ;
349
- }
350
- } ) ;
351
- let post_component_updates = hooks. fields . iter ( ) . map ( |field| {
352
- let field_name = & field. ident ;
353
- quote ! {
354
- self . #field_name. post_component_update( updater) ;
355
- }
356
- } ) ;
357
- let pre_component_draws = hooks. fields . iter ( ) . map ( |field| {
358
- let field_name = & field. ident ;
359
- quote ! {
360
- self . #field_name. pre_component_draw( drawer) ;
361
- }
362
- } ) ;
363
-
364
- tokens. extend ( quote ! {
365
- #[ derive( Default ) ]
366
- #hooks
367
-
368
- impl :: iocraft:: Hook for #name {
369
- fn poll_change( mut self : std:: pin:: Pin <& mut Self >, cx: & mut std:: task:: Context ) -> std:: task:: Poll <( ) > {
370
- use :: iocraft:: Hook ;
371
- #( #status_vars) *
372
- #( #returns) *
373
- std:: task:: Poll :: Pending
374
- }
375
-
376
- fn pre_component_update( & mut self , updater: & mut :: iocraft:: ComponentUpdater ) {
377
- use :: iocraft:: Hook ;
378
- #( #pre_component_updates) *
379
- }
380
-
381
- fn post_component_update( & mut self , updater: & mut :: iocraft:: ComponentUpdater ) {
382
- use :: iocraft:: Hook ;
383
- #( #post_component_updates) *
384
- }
385
-
386
- fn pre_component_draw( & mut self , drawer: & mut :: iocraft:: ComponentDrawer ) {
387
- use :: iocraft:: Hook ;
388
- #( #pre_component_draws) *
389
- }
390
- }
391
- } ) ;
392
- }
393
- }
394
-
395
- /// Defines a struct containing hooks to be made available to components.
396
- #[ proc_macro_attribute]
397
- pub fn hooks ( _attr : TokenStream , item : TokenStream ) -> TokenStream {
398
- let hooks = parse_macro_input ! ( item as ParsedHooks ) ;
399
- quote ! ( #hooks) . into ( )
400
- }
401
-
402
317
struct ParsedContext {
403
318
context : ItemStruct ,
404
319
}
@@ -486,7 +401,6 @@ struct ParsedComponent {
486
401
f : ItemFn ,
487
402
props_type : Option < Box < Type > > ,
488
403
state_type : Option < Box < Type > > ,
489
- hooks_type : Option < Box < Type > > ,
490
404
context_type : Option < Box < Type > > ,
491
405
impl_args : Vec < proc_macro2:: TokenStream > ,
492
406
}
@@ -497,7 +411,6 @@ impl Parse for ParsedComponent {
497
411
498
412
let mut props_type = None ;
499
413
let mut state_type = None ;
500
- let mut hooks_type = None ;
501
414
let mut context_type = None ;
502
415
let mut impl_args = Vec :: new ( ) ;
503
416
@@ -522,6 +435,15 @@ impl Parse for ParsedComponent {
522
435
_ => return Err ( Error :: new ( arg. ty . span ( ) , "invalid `props` type" ) ) ,
523
436
}
524
437
}
438
+ "hooks" | "_hooks" => match & * arg. ty {
439
+ Type :: Reference ( _) => {
440
+ impl_args. push ( quote ! ( & mut hooks) ) ;
441
+ }
442
+ Type :: Path ( _) => {
443
+ impl_args. push ( quote ! ( hooks) ) ;
444
+ }
445
+ _ => return Err ( Error :: new ( arg. ty . span ( ) , "invalid `hooks` type" ) ) ,
446
+ } ,
525
447
"state" | "_state" => {
526
448
if state_type. is_some ( ) {
527
449
return Err ( Error :: new ( arg. span ( ) , "duplicate `state` argument" ) ) ;
@@ -538,18 +460,6 @@ impl Parse for ParsedComponent {
538
460
_ => return Err ( Error :: new ( arg. ty . span ( ) , "invalid `state` type" ) ) ,
539
461
}
540
462
}
541
- "hooks" | "_hooks" => {
542
- if hooks_type. is_some ( ) {
543
- return Err ( Error :: new ( arg. span ( ) , "duplicate `hooks` argument" ) ) ;
544
- }
545
- match & * arg. ty {
546
- Type :: Reference ( r) => {
547
- hooks_type = Some ( r. elem . clone ( ) ) ;
548
- impl_args. push ( quote ! ( & mut self . hooks) ) ;
549
- }
550
- _ => return Err ( Error :: new ( arg. ty . span ( ) , "invalid `hooks` type" ) ) ,
551
- }
552
- }
553
463
"context" | "_context" => {
554
464
if context_type. is_some ( ) {
555
465
return Err ( Error :: new ( arg. span ( ) , "duplicate `context` argument" ) ) ;
@@ -578,7 +488,6 @@ impl Parse for ParsedComponent {
578
488
f,
579
489
props_type,
580
490
state_type,
581
- hooks_type,
582
491
context_type,
583
492
impl_args,
584
493
} )
@@ -601,36 +510,6 @@ impl ToTokens for ParsedComponent {
601
510
. as_ref ( )
602
511
. map ( |ty| quote ! ( state: #ty:: new( & mut signal_owner) , ) ) ;
603
512
604
- let hooks_decl = self . hooks_type . as_ref ( ) . map ( |ty| quote ! ( hooks: #ty, ) ) ;
605
- let hooks_init = self
606
- . hooks_type
607
- . as_ref ( )
608
- . map ( |ty| quote ! ( hooks: #ty:: default ( ) , ) ) ;
609
- let hooks_status_check = self . hooks_type . as_ref ( ) . map ( |_| {
610
- quote ! {
611
- let hooks_status = std:: pin:: Pin :: new( & mut self . hooks) . poll_change( cx) ;
612
- }
613
- } ) ;
614
- let hooks_status_return = self . hooks_type . as_ref ( ) . map ( |_| {
615
- quote ! {
616
- if hooks_status. is_ready( ) {
617
- return std:: task:: Poll :: Ready ( ( ) ) ;
618
- }
619
- }
620
- } ) ;
621
- let hooks_pre_component_update = self
622
- . hooks_type
623
- . as_ref ( )
624
- . map ( |_| quote ! { self . hooks. pre_component_update( updater) ; } ) ;
625
- let hooks_post_component_update = self
626
- . hooks_type
627
- . as_ref ( )
628
- . map ( |_| quote ! { self . hooks. post_component_update( updater) ; } ) ;
629
- let hooks_pre_component_draw = self
630
- . hooks_type
631
- . as_ref ( )
632
- . map ( |_| quote ! { self . hooks. pre_component_draw( drawer) ; } ) ;
633
-
634
513
let props_type_name = self
635
514
. props_type
636
515
. as_ref ( )
@@ -646,8 +525,9 @@ impl ToTokens for ParsedComponent {
646
525
tokens. extend ( quote ! {
647
526
#vis struct #name {
648
527
signal_owner: :: iocraft:: SignalOwner ,
528
+ hooks: Vec <std:: boxed:: Box <dyn :: iocraft:: AnyHook >>,
529
+ first_update: bool ,
649
530
#state_decl
650
- #hooks_decl
651
531
}
652
532
653
533
impl #name {
@@ -661,37 +541,43 @@ impl ToTokens for ParsedComponent {
661
541
let mut signal_owner = :: iocraft:: SignalOwner :: new( ) ;
662
542
Self {
663
543
#state_init
664
- #hooks_init
544
+ hooks: Vec :: new( ) ,
545
+ first_update: true ,
665
546
signal_owner,
666
547
}
667
548
}
668
549
669
550
fn update( & mut self , props: & mut Self :: Props <' _>, updater: & mut :: iocraft:: ComponentUpdater ) {
670
- #hooks_pre_component_update
551
+ use :: iocraft:: Hook ;
552
+ self . hooks. pre_component_update( updater) ;
671
553
{
554
+ let hooks = :: iocraft:: Hooks :: new( & mut self . hooks, self . first_update) ;
672
555
let mut e = {
673
556
#context_refs
674
557
Self :: implementation( #( #impl_args) , * ) . into( )
675
558
} ;
676
559
updater. update_children( [ & mut e] , None ) ;
677
560
}
678
- #hooks_post_component_update
561
+ self . hooks. post_component_update( updater) ;
562
+ self . first_update = false ;
679
563
}
680
564
681
565
fn draw( & mut self , drawer: & mut :: iocraft:: ComponentDrawer ) {
682
- #hooks_pre_component_draw
566
+ use :: iocraft:: Hook ;
567
+ self . hooks. pre_component_draw( drawer) ;
683
568
}
684
569
685
570
fn poll_change( mut self : std:: pin:: Pin <& mut Self >, cx: & mut std:: task:: Context <' _>) -> std:: task:: Poll <( ) > {
571
+ use :: iocraft:: Hook ;
572
+
686
573
let signals_status = std:: pin:: Pin :: new( & mut self . signal_owner) . poll_change( cx) ;
687
- #hooks_status_check
574
+ let hooks_status = std :: pin :: Pin :: new ( & mut self . hooks ) . poll_change ( cx ) ;
688
575
689
- if signals_status. is_ready( ) {
690
- return std:: task:: Poll :: Ready ( ( ) ) ;
576
+ if signals_status. is_ready( ) || hooks_status. is_ready( ) {
577
+ std:: task:: Poll :: Ready ( ( ) )
578
+ } else {
579
+ std:: task:: Poll :: Pending
691
580
}
692
- #hooks_status_return
693
-
694
- std:: task:: Poll :: Pending
695
581
}
696
582
}
697
583
} ) ;
0 commit comments