1use core::future::Future;
4use core::marker::PhantomData;
5
6use super::addressing::{Address, ChildRecipient};
7use crate::next::Never;
8use crate::{Behavior, Protocol};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum CreationKind<N> {
13 Birth,
15 ReplacementIncarnation {
17 replaces: N,
19 },
20}
21
22impl<N> CreationKind<N> {
23 #[must_use]
24 pub const fn replacement_of(replaces: N) -> Self {
25 Self::ReplacementIncarnation { replaces }
26 }
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct Create<A: Address, New> {
38 pub nonce: A::Nonce,
39 pub child: New,
40 pub kind: CreationKind<A::Nonce>,
41}
42
43impl<A: Address, New> Create<A, New> {
44 #[must_use]
45 pub const fn new(nonce: A::Nonce, child: New, kind: CreationKind<A::Nonce>) -> Self {
46 Self { nonce, child, kind }
47 }
48
49 #[must_use]
50 pub const fn birth(nonce: A::Nonce, child: New) -> Self {
51 Self::new(nonce, child, CreationKind::Birth)
52 }
53
54 #[must_use]
55 pub const fn replacement_incarnation(nonce: A::Nonce, replaces: A::Nonce, child: New) -> Self {
56 Self::new(nonce, child, CreationKind::replacement_of(replaces))
57 }
58}
59
60pub struct ChildRoute<Child: Behavior, Role> {
67 recipient: ChildRecipient<Child::Protocol>,
68 child: PhantomData<fn() -> Child>,
69 role: PhantomData<fn() -> Role>,
70}
71
72pub trait ChildRole<Parent: Behavior> {
78 type Child: Behavior;
80
81 type Position: ChildPosition<<Parent::Birth as BirthMode>::Child, Self::Child>;
83}
84
85impl<Child: Behavior, Role> Copy for ChildRoute<Child, Role> {}
86
87impl<Child: Behavior, Role> Clone for ChildRoute<Child, Role> {
88 fn clone(&self) -> Self {
89 *self
90 }
91}
92
93impl<Child: Behavior, Role> PartialEq for ChildRoute<Child, Role> {
94 fn eq(&self, other: &Self) -> bool {
95 self.recipient == other.recipient
96 }
97}
98
99impl<Child: Behavior, Role> Eq for ChildRoute<Child, Role> {}
100
101impl<Child: Behavior, Role> core::fmt::Debug for ChildRoute<Child, Role>
102where
103 <<Child::Protocol as Protocol>::Addr as Address>::Nonce: core::fmt::Debug,
104{
105 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106 f.debug_struct("ChildRoute")
107 .field("nonce", &self.nonce())
108 .finish()
109 }
110}
111
112impl<Child: Behavior, Role> ChildRoute<Child, Role> {
113 #[must_use]
115 pub const fn new(nonce: <<Child::Protocol as Protocol>::Addr as Address>::Nonce) -> Self {
116 Self {
117 recipient: ChildRecipient::new(nonce),
118 child: PhantomData,
119 role: PhantomData,
120 }
121 }
122
123 #[must_use]
125 pub const fn recipient(self) -> ChildRecipient<Child::Protocol> {
126 self.recipient
127 }
128
129 #[must_use]
131 pub const fn nonce(self) -> <<Child::Protocol as Protocol>::Addr as Address>::Nonce {
132 self.recipient.nonce()
133 }
134
135 #[must_use]
137 pub const fn stage(
138 self,
139 child: Child,
140 kind: CreationKind<<<Child::Protocol as Protocol>::Addr as Address>::Nonce>,
141 ) -> Create<<Child::Protocol as Protocol>::Addr, Child> {
142 Create::new(self.nonce(), child, kind)
143 }
144
145 #[must_use]
147 pub const fn birth(self, child: Child) -> Create<<Child::Protocol as Protocol>::Addr, Child> {
148 self.stage(child, CreationKind::Birth)
149 }
150
151 #[must_use]
153 pub const fn replacement_incarnation(
154 self,
155 replaces: <<Child::Protocol as Protocol>::Addr as Address>::Nonce,
156 child: Child,
157 ) -> Create<<Child::Protocol as Protocol>::Addr, Child> {
158 self.stage(child, CreationKind::replacement_of(replaces))
159 }
160}
161
162pub trait InstallBirth<A: Address, C: Behavior, Output, Error>
175where
176 C::Protocol: Protocol<Addr = A>,
177{
178 fn install_birth(
184 &mut self,
185 creation: Create<A, C>,
186 ) -> impl Future<Output = Result<Output, Error>> + Send;
187}
188
189pub trait DispatchBirth<A: Address, Installer, Output, Error>: Sized {
198 fn dispatch_birth(
203 self,
204 nonce: A::Nonce,
205 kind: CreationKind<A::Nonce>,
206 installer: &mut Installer,
207 ) -> impl Future<Output = Result<Output, Error>> + Send;
208}
209
210#[derive(Debug, Clone, PartialEq, Eq)]
269pub enum ChildChoice<Head, Tail> {
270 Head(Head),
272 Tail(Tail),
274}
275
276#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
278pub struct ChildHead;
279
280#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
282pub struct ChildTail<Position>(PhantomData<fn() -> Position>);
283
284pub trait ChildPosition<Children, Child: Behavior>: sealed::ChildPosition {}
341
342impl sealed::ChildPosition for ChildHead {}
343
344impl<Head: Behavior, Tail> ChildPosition<ChildChoice<Head, Tail>, Head> for ChildHead {}
345
346impl<Position> sealed::ChildPosition for ChildTail<Position> {}
347
348impl<Head, Tail, Position, Child> ChildPosition<ChildChoice<Head, Tail>, Child>
349 for ChildTail<Position>
350where
351 Child: Behavior,
352 Position: ChildPosition<Tail, Child>,
353{
354}
355
356mod sealed {
357 pub trait ChildPosition {}
358 pub trait ChildProduct {}
359}
360
361#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
363pub struct NoChildren;
364
365impl sealed::ChildProduct for NoChildren {}
366
367pub struct ChildCons<A: Address, C, Earlier> {
369 creation: Create<A, C>,
370 earlier: Earlier,
371}
372
373impl<A: Address, C, Earlier> sealed::ChildProduct for ChildCons<A, C, Earlier> {}
374
375pub struct Children<A: Address, Product = NoChildren> {
382 product: Product,
383 address: PhantomData<fn() -> A>,
384}
385
386#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
388pub enum ChildrenError<N> {
389 #[error("duplicate creator-local child nonce")]
391 DuplicateNonce {
392 nonce: N,
394 },
395}
396
397pub trait ChildProduct<A: Address>: sealed::ChildProduct + Sized {
399 type Choice;
401
402 #[doc(hidden)]
403 fn stage(
404 self,
405 ) -> Result<(Vec<Create<A, Self::Choice>>, Vec<A::Nonce>), ChildrenError<A::Nonce>>;
406}
407
408impl<A: Address> ChildProduct<A> for NoChildren {
409 type Choice = Never;
410
411 fn stage(
412 self,
413 ) -> Result<(Vec<Create<A, Self::Choice>>, Vec<A::Nonce>), ChildrenError<A::Nonce>> {
414 Ok((Vec::new(), Vec::new()))
415 }
416}
417
418impl<A, C, Earlier> ChildProduct<A> for ChildCons<A, C, Earlier>
419where
420 A: Address,
421 C: Behavior,
422 C::Protocol: Protocol<Addr = A>,
423 Earlier: ChildProduct<A>,
424{
425 type Choice = ChildChoice<C, Earlier::Choice>;
426
427 fn stage(
428 self,
429 ) -> Result<(Vec<Create<A, Self::Choice>>, Vec<A::Nonce>), ChildrenError<A::Nonce>> {
430 let (earlier, mut nonces) = self.earlier.stage()?;
431 if nonces.contains(&self.creation.nonce) {
432 return Err(ChildrenError::DuplicateNonce {
433 nonce: self.creation.nonce,
434 });
435 }
436 let mut creates = earlier
437 .into_iter()
438 .map(|creation| {
439 Create::new(
440 creation.nonce,
441 ChildChoice::Tail(creation.child),
442 creation.kind,
443 )
444 })
445 .collect::<Vec<_>>();
446 nonces.push(self.creation.nonce);
447 creates.push(Create::new(
448 self.creation.nonce,
449 ChildChoice::Head(self.creation.child),
450 self.creation.kind,
451 ));
452 Ok((creates, nonces))
453 }
454}
455
456impl<A: Address> Children<A, NoChildren> {
457 #[must_use]
459 pub const fn new() -> Self {
460 Self {
461 product: NoChildren,
462 address: PhantomData,
463 }
464 }
465}
466
467impl<A: Address> Default for Children<A, NoChildren> {
468 fn default() -> Self {
469 Self::new()
470 }
471}
472
473impl<A: Address, Product> Children<A, Product> {
474 #[must_use]
476 pub fn create<C>(self, creation: Create<A, C>) -> Children<A, ChildCons<A, C, Product>>
477 where
478 C: Behavior,
479 C::Protocol: Protocol<Addr = A>,
480 {
481 Children {
482 product: ChildCons {
483 creation,
484 earlier: self.product,
485 },
486 address: PhantomData,
487 }
488 }
489
490 #[must_use]
492 pub fn child<C>(self, nonce: A::Nonce, child: C) -> Children<A, ChildCons<A, C, Product>>
493 where
494 C: Behavior,
495 C::Protocol: Protocol<Addr = A>,
496 {
497 self.create(Create::birth(nonce, child))
498 }
499
500 #[must_use]
502 pub fn child_at<C, Role>(
503 self,
504 route: ChildRoute<C, Role>,
505 child: C,
506 ) -> Children<A, ChildCons<A, C, Product>>
507 where
508 C: Behavior,
509 C::Protocol: Protocol<Addr = A>,
510 {
511 self.create(route.birth(child))
512 }
513}
514
515impl<A, Product> Children<A, Product>
516where
517 A: Address,
518 Product: ChildProduct<A>,
519{
520 pub fn into_creates(self) -> Result<Vec<Create<A, Product::Choice>>, ChildrenError<A::Nonce>> {
528 self.product.stage().map(|(creates, _)| creates)
529 }
530}
531
532impl<A, Head, Tail, Installer, Output, Error> DispatchBirth<A, Installer, Output, Error>
533 for ChildChoice<Head, Tail>
534where
535 A: Address,
536 A::Nonce: Send,
537 Head: Behavior + Send,
538 Head::Protocol: Protocol<Addr = A>,
539 Tail: DispatchBirth<A, Installer, Output, Error> + Send,
540 Installer: InstallBirth<A, Head, Output, Error> + Send,
541{
542 async fn dispatch_birth(
543 self,
544 nonce: A::Nonce,
545 kind: CreationKind<A::Nonce>,
546 installer: &mut Installer,
547 ) -> Result<Output, Error> {
548 match self {
549 Self::Head(child) => {
550 installer
551 .install_birth(Create::new(nonce, child, kind))
552 .await
553 }
554 Self::Tail(tail) => tail.dispatch_birth(nonce, kind, installer).await,
555 }
556 }
557}
558
559impl<A, Installer, Output, Error> DispatchBirth<A, Installer, Output, Error> for Never
560where
561 A: Address,
562{
563 fn dispatch_birth(
564 self,
565 _nonce: A::Nonce,
566 _kind: CreationKind<A::Nonce>,
567 _installer: &mut Installer,
568 ) -> impl Future<Output = Result<Output, Error>> + Send {
569 async move { match self {} }
570 }
571}
572
573impl<A, C, Installer, Output, Error> DispatchBirth<A, Installer, Output, Error> for C
574where
575 A: Address,
576 C: Behavior,
577 C::Protocol: Protocol<Addr = A>,
578 Installer: InstallBirth<A, C, Output, Error>,
579{
580 fn dispatch_birth(
581 self,
582 nonce: A::Nonce,
583 kind: CreationKind<A::Nonce>,
584 installer: &mut Installer,
585 ) -> impl Future<Output = Result<Output, Error>> + Send {
586 installer.install_birth(Create::new(nonce, self, kind))
587 }
588}
589
590pub trait BirthMode {
592 type Child;
593}
594
595pub struct NoBirthProtocols;
597
598pub struct BirthProtocol<P: Protocol, Tail> {
600 protocol: PhantomData<fn() -> P>,
601 tail: PhantomData<fn() -> Tail>,
602}
603
604pub struct BirthProtocolHead;
606
607pub struct BirthProtocolTail<Position>(PhantomData<fn() -> Position>);
609
610pub trait BirthProtocolAt<P: Protocol, Position> {}
612
613impl<P: Protocol, Tail> BirthProtocolAt<P, BirthProtocolHead> for BirthProtocol<P, Tail> {}
614
615impl<Head, Tail, P, Position> BirthProtocolAt<P, BirthProtocolTail<Position>>
616 for BirthProtocol<Head, Tail>
617where
618 Head: Protocol,
619 P: Protocol,
620 Tail: BirthProtocolAt<P, Position>,
621{
622}
623
624#[doc(hidden)]
626pub trait BirthProtocolProduct {
627 type Append<Tail: BirthProtocolProduct>: BirthProtocolProduct;
628}
629
630impl BirthProtocolProduct for NoBirthProtocols {
631 type Append<Tail: BirthProtocolProduct> = Tail;
632}
633
634impl<P, Rest> BirthProtocolProduct for BirthProtocol<P, Rest>
635where
636 P: Protocol,
637 Rest: BirthProtocolProduct,
638{
639 type Append<Tail: BirthProtocolProduct> = BirthProtocol<P, Rest::Append<Tail>>;
640}
641
642pub trait BirthProtocols: Behavior {
648 type Protocols: BirthProtocolProduct;
649}
650
651impl<B> BirthProtocols for B
652where
653 B: Behavior,
654 B::Birth: BirthModeProtocols,
655{
656 type Protocols = BirthProtocol<B::Protocol, <B::Birth as BirthModeProtocols>::Protocols>;
657}
658
659#[doc(hidden)]
660pub trait BirthModeProtocols {
661 type Protocols: BirthProtocolProduct;
662}
663
664impl<M> BirthModeProtocols for M
665where
666 M: BirthMode,
667 M::Child: BirthNodeProtocols,
668{
669 type Protocols = <M::Child as BirthNodeProtocols>::Protocols;
670}
671
672#[doc(hidden)]
673pub trait BirthNodeProtocols {
674 type Protocols: BirthProtocolProduct;
675}
676
677impl<B> BirthNodeProtocols for B
678where
679 B: BirthProtocols,
680{
681 type Protocols = B::Protocols;
682}
683
684impl<Head, Tail> BirthNodeProtocols for ChildChoice<Head, Tail>
685where
686 Head: BirthNodeProtocols,
687 Tail: BirthNodeProtocols,
688{
689 type Protocols = <Head::Protocols as BirthProtocolProduct>::Append<Tail::Protocols>;
690}
691
692impl BirthNodeProtocols for Never {
693 type Protocols = NoBirthProtocols;
694}
695
696#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
698pub struct NoBirths;
699
700impl BirthMode for NoBirths {
701 type Child = Never;
702}
703
704#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
706pub struct Births<C>(PhantomData<fn() -> C>);
707
708impl<C> BirthMode for Births<C> {
709 type Child = C;
710}
711
712#[cfg(test)]
713mod tests {
714 use super::*;
715 use crate::{Actions, BehaviorActed, MailAddr, NoBirths, User};
716
717 struct Child;
718
719 struct SharedProtocol;
720
721 impl behavior::Protocol for SharedProtocol {
722 type Addr = MailAddr;
723 type Msg = u8;
724 }
725
726 struct Primary;
727 struct Fallback;
728
729 macro_rules! shared_protocol_behavior {
730 ($behavior:ty, $birth:ty) => {
731 impl Behavior for $behavior {
732 type Protocol = SharedProtocol;
733 type Event = User<MailAddr, u8>;
734 type Sends = Vec<Never>;
735 type Ph = Never;
736 type Error = Never;
737 type Birth = $birth;
738
739 fn transition(
740 &mut self,
741 _: crate::ActiveTurn,
742 _: Self::Event,
743 ) -> BehaviorActed<Self> {
744 Ok(Actions::cont())
745 }
746 }
747 };
748 }
749
750 shared_protocol_behavior!(Primary, Births<Child>);
751 shared_protocol_behavior!(Fallback, NoBirths);
752
753 impl behavior::Protocol for Child {
754 type Addr = MailAddr;
755 type Msg = u8;
756 }
757
758 impl Behavior for Child {
759 type Protocol = Self;
760 type Event = User<MailAddr, u8>;
761 type Sends = Vec<Never>;
762 type Ph = Never;
763 type Error = Never;
764 type Birth = NoBirths;
765
766 fn transition(&mut self, _: crate::ActiveTurn, _: Self::Event) -> BehaviorActed<Self> {
767 Ok(Actions::cont())
768 }
769 }
770
771 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
772 enum InstallError {
773 Refused,
774 }
775
776 struct RecordingInstaller {
777 calls: usize,
778 observed: Vec<(u64, CreationKind<u64>)>,
779 result: Result<u32, InstallError>,
780 }
781
782 #[derive(Debug, PartialEq, Eq)]
783 enum SharedInstallation {
784 Primary(u64),
785 Fallback(u64),
786 }
787
788 #[derive(Default)]
789 struct SharedProtocolInstaller(Vec<SharedInstallation>);
790
791 impl InstallBirth<MailAddr, Primary, (), Never> for SharedProtocolInstaller {
792 async fn install_birth(
793 &mut self,
794 creation: Create<MailAddr, Primary>,
795 ) -> Result<(), Never> {
796 self.0.push(SharedInstallation::Primary(creation.nonce));
797 Ok(())
798 }
799 }
800
801 impl InstallBirth<MailAddr, Fallback, (), Never> for SharedProtocolInstaller {
802 async fn install_birth(
803 &mut self,
804 creation: Create<MailAddr, Fallback>,
805 ) -> Result<(), Never> {
806 self.0.push(SharedInstallation::Fallback(creation.nonce));
807 Ok(())
808 }
809 }
810
811 impl InstallBirth<MailAddr, Child, u32, InstallError> for RecordingInstaller {
812 async fn install_birth(
813 &mut self,
814 creation: Create<MailAddr, Child>,
815 ) -> Result<u32, InstallError> {
816 self.calls += 1;
817 self.observed.push((creation.nonce, creation.kind));
818 self.result
819 }
820 }
821
822 fn installer(result: Result<u32, InstallError>) -> RecordingInstaller {
823 RecordingInstaller {
824 calls: 0,
825 observed: Vec::new(),
826 result,
827 }
828 }
829
830 fn assert_send<T: Send>(_: &T) {}
831
832 enum WorkerRole {}
833
834 #[test]
835 fn child_route_preserves_one_nonce_across_routing_and_creation_provenance() {
836 let route = ChildRoute::<Child, WorkerRole>::new(17);
837
838 assert_eq!(route.nonce(), 17);
839 assert_eq!(route.recipient().nonce(), 17);
840 assert_eq!(route, ChildRoute::new(17));
841 assert_ne!(route, ChildRoute::new(19));
842 assert_eq!(format!("{route:?}"), "ChildRoute { nonce: 17 }");
843
844 let birth = route.birth(Child);
845 assert_eq!(birth.nonce, 17);
846 assert_eq!(birth.kind, CreationKind::Birth);
847
848 let replacement = route.replacement_incarnation(11, Child);
849 assert_eq!(replacement.nonce, 17);
850 assert_eq!(replacement.kind, CreationKind::replacement_of(11));
851 }
852
853 #[test]
854 fn empty_child_product_stages_no_creations_or_nonces() {
855 let (creations, nonces) = <NoChildren as ChildProduct<MailAddr>>::stage(NoChildren)
856 .expect("an empty child product is valid");
857 assert!(creations.is_empty());
858 assert!(nonces.is_empty());
859 }
860
861 #[tokio::test]
862 async fn concrete_child_dispatches_once_with_exact_nonce_provenance_and_output() {
863 let mut installer = installer(Ok(91));
864 let future = Child.dispatch_birth(
865 17,
866 CreationKind::ReplacementIncarnation { replaces: 8 },
867 &mut installer,
868 );
869 assert_send(&future);
870 let result = future.await;
871
872 assert_eq!(result, Ok(91));
873 assert_eq!(installer.calls, 1);
874 assert_eq!(
875 installer.observed,
876 [(17, CreationKind::ReplacementIncarnation { replaces: 8 })]
877 );
878 }
879
880 #[tokio::test]
881 async fn concrete_child_returns_the_exact_installer_error_without_retry() {
882 let mut installer = installer(Err(InstallError::Refused));
883 let future = Child.dispatch_birth(23, CreationKind::replacement_of(19), &mut installer);
884 assert_send(&future);
885 let result = future.await;
886
887 assert_eq!(result, Err(InstallError::Refused));
888 assert_eq!(installer.calls, 1);
889 assert_eq!(installer.observed, [(23, CreationKind::replacement_of(19))]);
890 }
891
892 #[tokio::test]
893 async fn distinct_child_alternatives_preserve_one_canonical_protocol_identity() {
894 type Alternatives = ChildChoice<Primary, ChildChoice<Fallback, Never>>;
895
896 fn requires_shared_protocol<C: Behavior<Protocol = SharedProtocol>>() {}
897 requires_shared_protocol::<Primary>();
898 requires_shared_protocol::<Fallback>();
899
900 let mut installer = SharedProtocolInstaller::default();
901 Alternatives::Head(Primary)
902 .dispatch_birth(11, CreationKind::Birth, &mut installer)
903 .await
904 .unwrap();
905 Alternatives::Tail(ChildChoice::Head(Fallback))
906 .dispatch_birth(17, CreationKind::Birth, &mut installer)
907 .await
908 .unwrap();
909
910 assert_eq!(
911 installer.0,
912 [
913 SharedInstallation::Primary(11),
914 SharedInstallation::Fallback(17),
915 ]
916 );
917 }
918
919 #[test]
920 fn birth_protocol_projection_recurses_without_inspecting_send_lanes() {
921 type Protocols = <Primary as BirthProtocols>::Protocols;
922 type Expected = BirthProtocol<SharedProtocol, BirthProtocol<Child, NoBirthProtocols>>;
923
924 trait Same<T> {}
925 impl<T> Same<T> for T {}
926 fn exact<T: Same<Expected>>() {}
927 exact::<Protocols>();
928 }
929}