1use core::marker::PhantomData;
4
5use crate::{
6 ActionItem, Behavior, InterpretationProgress, ItemSettlement, MessageProtocol, Never, Protocol,
7 finish_item, prepare_item,
8};
9
10pub trait Address: Copy + Eq {
17 type Nonce: Copy + Eq;
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
21pub struct MailAddr(pub u64);
22
23impl From<u64> for MailAddr {
24 fn from(value: u64) -> Self {
25 Self(value)
26 }
27}
28
29impl From<MailAddr> for u64 {
30 fn from(value: MailAddr) -> Self {
31 value.0
32 }
33}
34
35impl Address for MailAddr {
36 type Nonce = u64;
37}
38
39pub trait RecipientAddress: Address + Sized {
93 type Established<P>: Clone
94 where
95 P: Protocol<Addr = Self>;
96}
97
98pub trait EndpointAddress: Address + Sized {
105 type Established<P>: Clone
106 where
107 P: Protocol<Addr = Self>;
108
109 type Installed<B>: Clone
110 where
111 B: Behavior<Protocol: Protocol<Addr = Self>>;
112
113 fn recipient<B>(
115 installed: &Self::Installed<B>,
116 ) -> <Self as EndpointAddress>::Established<B::Protocol>
117 where
118 B: Behavior<Protocol: Protocol<Addr = Self>>;
119}
120
121impl<A: EndpointAddress> RecipientAddress for A {
122 type Established<P>
123 = <A as EndpointAddress>::Established<P>
124 where
125 P: Protocol<Addr = Self>;
126}
127
128pub struct Recipient<P: Protocol> {
136 address: P::Addr,
137 protocol: PhantomData<fn() -> P>,
138}
139
140impl<P: Protocol> Copy for Recipient<P> {}
141
142impl<P: Protocol> Clone for Recipient<P> {
143 fn clone(&self) -> Self {
144 *self
145 }
146}
147
148impl<P: Protocol> Recipient<P> {
149 #[must_use]
150 pub fn global(address: P::Addr) -> Self {
151 Self::new(address)
152 }
153
154 #[must_use]
156 pub const fn address(self) -> P::Addr {
157 self.address
158 }
159
160 const fn new(address: P::Addr) -> Self {
161 Self {
162 address,
163 protocol: PhantomData,
164 }
165 }
166}
167
168impl<A: Address, M> From<A> for Recipient<MessageProtocol<A, M>> {
169 fn from(address: A) -> Self {
170 Self::new(address)
171 }
172}
173
174pub struct EstablishedRecipient<P>
197where
198 P: Protocol,
199 P::Addr: RecipientAddress,
200{
201 pub(crate) endpoint: <P::Addr as RecipientAddress>::Established<P>,
202}
203
204impl<P> EstablishedRecipient<P>
205where
206 P: Protocol,
207 P::Addr: RecipientAddress,
208{
209 #[must_use]
216 pub const fn issued(endpoint: <P::Addr as RecipientAddress>::Established<P>) -> Self {
217 Self { endpoint }
218 }
219
220 pub fn interpret<I>(self, interpreter: &mut I) -> I::Output
222 where
223 I: InterpretEstablished<P>,
224 {
225 interpreter.interpret_established(self.endpoint)
226 }
227}
228
229pub trait InterpretEstablished<P>
231where
232 P: Protocol,
233 P::Addr: RecipientAddress,
234{
235 type Output;
236
237 fn interpret_established(
238 &mut self,
239 endpoint: <P::Addr as RecipientAddress>::Established<P>,
240 ) -> Self::Output;
241}
242
243impl<P> Clone for EstablishedRecipient<P>
244where
245 P: Protocol,
246 P::Addr: RecipientAddress,
247{
248 fn clone(&self) -> Self {
249 Self::issued(self.endpoint.clone())
250 }
251}
252
253impl<P> core::fmt::Debug for EstablishedRecipient<P>
254where
255 P: Protocol,
256 P::Addr: RecipientAddress,
257 <P::Addr as RecipientAddress>::Established<P>: core::fmt::Debug,
258{
259 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
260 formatter
261 .debug_tuple("EstablishedRecipient")
262 .field(&self.endpoint)
263 .finish()
264 }
265}
266
267impl<P> PartialEq for EstablishedRecipient<P>
268where
269 P: Protocol,
270 P::Addr: RecipientAddress,
271 <P::Addr as RecipientAddress>::Established<P>: PartialEq,
272{
273 fn eq(&self, other: &Self) -> bool {
274 self.endpoint == other.endpoint
275 }
276}
277
278impl<P> Eq for EstablishedRecipient<P>
279where
280 P: Protocol,
281 P::Addr: RecipientAddress,
282 <P::Addr as RecipientAddress>::Established<P>: Eq,
283{
284}
285
286pub struct EstablishedActor<B>
381where
382 B: Behavior,
383 <B::Protocol as Protocol>::Addr: EndpointAddress,
384{
385 installed: <<B::Protocol as Protocol>::Addr as EndpointAddress>::Installed<B>,
386}
387
388impl<B> EstablishedActor<B>
389where
390 B: Behavior,
391 <B::Protocol as Protocol>::Addr: EndpointAddress,
392{
393 #[must_use]
399 pub const fn issued(
400 installed: <<B::Protocol as Protocol>::Addr as EndpointAddress>::Installed<B>,
401 ) -> Self {
402 Self { installed }
403 }
404
405 #[must_use]
407 pub fn recipient(&self) -> EstablishedRecipient<B::Protocol> {
408 EstablishedRecipient::issued(
409 <<B::Protocol as Protocol>::Addr as EndpointAddress>::recipient(&self.installed),
410 )
411 }
412
413 #[must_use]
416 pub fn into_recipient(self) -> EstablishedRecipient<B::Protocol> {
417 EstablishedRecipient::issued(
418 <<B::Protocol as Protocol>::Addr as EndpointAddress>::recipient(&self.installed),
419 )
420 }
421
422 pub fn interpret_actor<I>(self, interpreter: &mut I) -> I::Output
424 where
425 I: InterpretInstalledActor<B>,
426 {
427 interpreter.interpret_actor(self.installed)
428 }
429}
430
431pub trait InterpretInstalledActor<B>
433where
434 B: Behavior,
435 <B::Protocol as Protocol>::Addr: EndpointAddress,
436{
437 type Output;
438
439 fn interpret_actor(
440 &mut self,
441 installed: <<B::Protocol as Protocol>::Addr as EndpointAddress>::Installed<B>,
442 ) -> Self::Output;
443}
444
445impl<B> Clone for EstablishedActor<B>
446where
447 B: Behavior,
448 <B::Protocol as Protocol>::Addr: EndpointAddress,
449{
450 fn clone(&self) -> Self {
451 Self::issued(self.installed.clone())
452 }
453}
454
455impl<B> core::fmt::Debug for EstablishedActor<B>
456where
457 B: Behavior,
458 <B::Protocol as Protocol>::Addr: EndpointAddress,
459 <<B::Protocol as Protocol>::Addr as EndpointAddress>::Installed<B>: core::fmt::Debug,
460{
461 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
462 formatter
463 .debug_tuple("EstablishedActor")
464 .field(&self.installed)
465 .finish()
466 }
467}
468
469impl<B> PartialEq for EstablishedActor<B>
470where
471 B: Behavior,
472 <B::Protocol as Protocol>::Addr: EndpointAddress,
473 <<B::Protocol as Protocol>::Addr as EndpointAddress>::Installed<B>: PartialEq,
474{
475 fn eq(&self, other: &Self) -> bool {
476 self.installed == other.installed
477 }
478}
479
480impl<B> Eq for EstablishedActor<B>
481where
482 B: Behavior,
483 <B::Protocol as Protocol>::Addr: EndpointAddress,
484 <<B::Protocol as Protocol>::Addr as EndpointAddress>::Installed<B>: Eq,
485{
486}
487
488impl<P: Protocol> PartialEq for Recipient<P> {
489 fn eq(&self, other: &Self) -> bool {
490 self.address == other.address
491 }
492}
493
494impl<P: Protocol> Eq for Recipient<P> {}
495
496impl<P: Protocol> core::fmt::Debug for Recipient<P>
497where
498 P::Addr: core::fmt::Debug,
499 <P::Addr as Address>::Nonce: core::fmt::Debug,
500{
501 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
502 self.address.fmt(f)
503 }
504}
505
506#[derive(Clone, Copy, Debug, Eq, PartialEq)]
555pub enum LogicalDeliveryReason {
556 UnknownAddress,
557 ClosedRecipient,
558}
559
560#[derive(Clone, Copy, Debug, Eq, PartialEq)]
562pub enum ExactDeliveryReason {
563 ClosedRecipient,
564}
565
566pub struct Delivery<P: Protocol> {
567 pub to: Recipient<P>,
568 pub message: P::Msg,
569}
570
571impl<P: Protocol> Delivery<P> {
572 #[must_use]
573 pub fn new(to: Recipient<P>, message: P::Msg) -> Self {
574 Self { to, message }
575 }
576}
577
578impl<P> Clone for Delivery<P>
579where
580 P: Protocol,
581 P::Msg: Clone,
582{
583 fn clone(&self) -> Self {
584 Self {
585 to: self.to,
586 message: self.message.clone(),
587 }
588 }
589}
590
591impl<P> PartialEq for Delivery<P>
592where
593 P: Protocol,
594 P::Msg: PartialEq,
595{
596 fn eq(&self, other: &Self) -> bool {
597 self.to == other.to && self.message == other.message
598 }
599}
600
601impl<P> Eq for Delivery<P>
602where
603 P: Protocol,
604 P::Msg: Eq,
605{
606}
607
608impl<P> ActionItem for Delivery<P>
609where
610 P: Protocol,
611 P::Addr: Send,
612 P::Msg: Send,
613{
614 type Custody = (Option<Self>, Option<Self::Reply>);
615 type Input<'a>
616 = &'a mut Option<Self>
617 where
618 Self: 'a;
619 type Reply = ItemSettlement<Self, Self::Accepted, Self::Rejection, Self::Prerequisite>;
620
621 fn prepare_interpretation(
622 progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
623 ) {
624 prepare_item::<Self>(progress);
625 }
626 fn interpretation_input<'a>(
627 custody: &'a mut Self::Custody,
628 ) -> Option<(Self::Input<'a>, &'a mut Option<Self::Reply>)>
629 where
630 Self: 'a,
631 {
632 let (input, received) = custody;
633 if input.is_some() && received.is_none() {
634 Some((input, received))
635 } else {
636 None
637 }
638 }
639 fn finish_interpretation(
640 progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
641 ) {
642 finish_item::<Self>(progress);
643 }
644
645 type Accepted = ();
646 type Rejection = LogicalDeliveryReason;
647 type Prerequisite = Never;
648}
649
650pub struct EstablishedDelivery<P>
680where
681 P: Protocol,
682 P::Addr: RecipientAddress,
683{
684 pub to: EstablishedRecipient<P>,
685 pub message: P::Msg,
686}
687
688impl<P> EstablishedDelivery<P>
689where
690 P: Protocol,
691 P::Addr: RecipientAddress,
692{
693 #[must_use]
694 pub const fn new(to: EstablishedRecipient<P>, message: P::Msg) -> Self {
695 Self { to, message }
696 }
697}
698
699impl<P> Clone for EstablishedDelivery<P>
700where
701 P: Protocol,
702 P::Addr: RecipientAddress,
703 P::Msg: Clone,
704{
705 fn clone(&self) -> Self {
706 Self::new(self.to.clone(), self.message.clone())
707 }
708}
709
710impl<P> core::fmt::Debug for EstablishedDelivery<P>
711where
712 P: Protocol,
713 P::Addr: RecipientAddress,
714 EstablishedRecipient<P>: core::fmt::Debug,
715 P::Msg: core::fmt::Debug,
716{
717 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
718 formatter
719 .debug_struct("EstablishedDelivery")
720 .field("to", &self.to)
721 .field("message", &self.message)
722 .finish()
723 }
724}
725
726impl<P> PartialEq for EstablishedDelivery<P>
727where
728 P: Protocol,
729 P::Addr: RecipientAddress,
730 EstablishedRecipient<P>: PartialEq,
731 P::Msg: PartialEq,
732{
733 fn eq(&self, other: &Self) -> bool {
734 self.to == other.to && self.message == other.message
735 }
736}
737
738impl<P> Eq for EstablishedDelivery<P>
739where
740 P: Protocol,
741 P::Addr: RecipientAddress,
742 EstablishedRecipient<P>: Eq,
743 P::Msg: Eq,
744{
745}
746
747impl<P> ActionItem for EstablishedDelivery<P>
748where
749 P: Protocol,
750 P::Addr: RecipientAddress,
751 <P::Addr as RecipientAddress>::Established<P>: Send,
752 P::Msg: Send,
753{
754 type Custody = (Option<Self>, Option<Self::Reply>);
755 type Input<'a>
756 = &'a mut Option<Self>
757 where
758 Self: 'a;
759 type Reply = ItemSettlement<Self, Self::Accepted, Self::Rejection, Self::Prerequisite>;
760
761 fn prepare_interpretation(
762 progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
763 ) {
764 prepare_item::<Self>(progress);
765 }
766 fn interpretation_input<'a>(
767 custody: &'a mut Self::Custody,
768 ) -> Option<(Self::Input<'a>, &'a mut Option<Self::Reply>)>
769 where
770 Self: 'a,
771 {
772 let (input, received) = custody;
773 if input.is_some() && received.is_none() {
774 Some((input, received))
775 } else {
776 None
777 }
778 }
779 fn finish_interpretation(
780 progress: &mut Option<InterpretationProgress<Self, Self::Custody, Self::Reply>>,
781 ) {
782 finish_item::<Self>(progress);
783 }
784
785 type Accepted = ();
786 type Rejection = ExactDeliveryReason;
787 type Prerequisite = Never;
788}
789
790#[cfg(test)]
791mod tests {
792 use super::*;
793 use crate::{Actions, Never, NoBirths, User};
794 use std::rc::Rc;
795
796 struct Inbox;
797
798 struct SignatureOnly;
799
800 #[derive(Clone, Copy, PartialEq, Eq)]
801 struct LocalAddr(u8);
802
803 impl Address for LocalAddr {
804 type Nonce = u8;
805 }
806
807 struct LocalProtocol;
808
809 impl Protocol for LocalProtocol {
810 type Addr = LocalAddr;
811 type Msg = u8;
812 }
813
814 struct LocalEndpoint<P> {
815 token: Rc<()>,
816 protocol: PhantomData<fn() -> P>,
817 }
818
819 impl<P> Clone for LocalEndpoint<P> {
820 fn clone(&self) -> Self {
821 Self {
822 token: self.token.clone(),
823 protocol: PhantomData,
824 }
825 }
826 }
827
828 impl<P> core::fmt::Debug for LocalEndpoint<P> {
829 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
830 formatter.write_str("LocalEndpoint")
831 }
832 }
833
834 impl<P> PartialEq for LocalEndpoint<P> {
835 fn eq(&self, other: &Self) -> bool {
836 Rc::ptr_eq(&self.token, &other.token)
837 }
838 }
839
840 impl<P> Eq for LocalEndpoint<P> {}
841
842 struct LocalInstalled<B: Behavior> {
843 endpoint: LocalEndpoint<B::Protocol>,
844 control: std::sync::mpsc::Sender<B::Event>,
845 incarnation: Rc<()>,
846 }
847
848 impl<B: Behavior> Clone for LocalInstalled<B> {
849 fn clone(&self) -> Self {
850 Self {
851 endpoint: self.endpoint.clone(),
852 control: self.control.clone(),
853 incarnation: self.incarnation.clone(),
854 }
855 }
856 }
857
858 impl<B: Behavior> core::fmt::Debug for LocalInstalled<B> {
859 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
860 formatter.write_str("LocalInstalled")
861 }
862 }
863
864 impl<B: Behavior> PartialEq for LocalInstalled<B> {
865 fn eq(&self, other: &Self) -> bool {
866 Rc::ptr_eq(&self.incarnation, &other.incarnation)
867 }
868 }
869
870 impl<B: Behavior> Eq for LocalInstalled<B> {}
871
872 impl EndpointAddress for LocalAddr {
873 type Established<P>
874 = LocalEndpoint<P>
875 where
876 P: Protocol<Addr = Self>;
877
878 type Installed<B>
879 = LocalInstalled<B>
880 where
881 B: Behavior<Protocol: Protocol<Addr = Self>>;
882
883 fn recipient<B>(installed: &Self::Installed<B>) -> Self::Established<B::Protocol>
884 where
885 B: Behavior<Protocol: Protocol<Addr = Self>>,
886 {
887 installed.endpoint.clone()
888 }
889 }
890
891 struct LocalTransfer;
892
893 impl InterpretEstablished<LocalProtocol> for LocalTransfer {
894 type Output = Rc<()>;
895
896 fn interpret_established(
897 &mut self,
898 endpoint: LocalEndpoint<LocalProtocol>,
899 ) -> Self::Output {
900 endpoint.token
901 }
902 }
903
904 struct LocalEndpointTransfer;
905
906 impl InterpretEstablished<LocalProtocol> for LocalEndpointTransfer {
907 type Output = LocalEndpoint<LocalProtocol>;
908
909 fn interpret_established(
910 &mut self,
911 endpoint: LocalEndpoint<LocalProtocol>,
912 ) -> Self::Output {
913 endpoint
914 }
915 }
916
917 struct LocalBehavior;
918
919 impl Behavior for LocalBehavior {
920 type Protocol = LocalProtocol;
921 type Event = User<LocalAddr, u8>;
922 type Sends = Vec<Never>;
923 type Ph = Never;
924 type Error = Never;
925 type Birth = NoBirths;
926
927 fn transition(
928 &mut self,
929 _: crate::ActiveTurn,
930 _: Self::Event,
931 ) -> crate::BehaviorActed<Self> {
932 Ok(Actions::cont())
933 }
934 }
935
936 impl crate::Protocol for SignatureOnly {
937 type Addr = MailAddr;
938 type Msg = u8;
939 }
940
941 impl behavior::Protocol for Inbox {
942 type Addr = MailAddr;
943 type Msg = u8;
944 }
945
946 impl Behavior for Inbox {
947 type Protocol = Self;
948 type Event = User<MailAddr, u8>;
949 type Sends = Vec<Never>;
950 type Ph = Never;
951 type Error = Never;
952 type Birth = NoBirths;
953
954 fn init(&mut self, _: crate::InitializationTurn) -> crate::BehaviorActed<Self> {
955 Ok(Actions::cont())
956 }
957
958 fn transition(
959 &mut self,
960 _: crate::ActiveTurn,
961 _: Self::Event,
962 ) -> crate::BehaviorActed<Self> {
963 Ok(Actions::cont())
964 }
965 }
966
967 #[test]
968 fn mail_address_conversion_preserves_nonzero_value() {
969 assert_eq!(u64::from(MailAddr(41)), 41);
970 }
971
972 #[test]
973 fn routing_requires_only_the_static_protocol_signature() {
974 let recipient = Recipient::<SignatureOnly>::global(MailAddr(7));
975 let delivery = Delivery::new(recipient, 11);
976
977 assert_eq!(delivery.to.address(), MailAddr(7));
978 assert_eq!(delivery.message, 11);
979 }
980
981 #[test]
982 fn recipient_value_contract_distinguishes_logical_addresses() {
983 let global = Recipient::<Inbox>::global(MailAddr(7));
984 let same_global = Recipient::<Inbox>::global(MailAddr(7));
985 let other_global = Recipient::<Inbox>::global(MailAddr(8));
986
987 assert_eq!(global, same_global);
988 assert_ne!(global, other_global);
989 assert_eq!(global.address(), MailAddr(7));
990 assert_eq!(format!("{global:?}"), "MailAddr(7)");
991 }
992
993 #[test]
994 fn established_capability_accepts_a_local_non_send_endpoint() {
995 let token = Rc::new(());
996 let recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
997 token: token.clone(),
998 protocol: PhantomData,
999 });
1000 let retained = recipient.clone();
1001 let extracted = retained.interpret(&mut LocalTransfer);
1002
1003 assert!(Rc::ptr_eq(&token, &extracted));
1004 drop(recipient);
1005 }
1006
1007 #[test]
1008 fn established_values_compare_complete_identity_and_expose_debug_shape() {
1009 let token = Rc::new(());
1010 let other_token = Rc::new(());
1011 let recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
1012 token: token.clone(),
1013 protocol: PhantomData,
1014 });
1015 let same_recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
1016 token,
1017 protocol: PhantomData,
1018 });
1019 let other_recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
1020 token: other_token,
1021 protocol: PhantomData,
1022 });
1023
1024 assert_eq!(recipient, same_recipient);
1025 assert_ne!(recipient, other_recipient);
1026 assert_eq!(
1027 format!("{recipient:?}"),
1028 "EstablishedRecipient(LocalEndpoint)"
1029 );
1030
1031 let (control, _consumer) = std::sync::mpsc::channel();
1032 let installed = LocalInstalled {
1033 endpoint: recipient.clone().interpret(&mut LocalEndpointTransfer),
1034 control,
1035 incarnation: Rc::new(()),
1036 };
1037 let actor = EstablishedActor::<LocalBehavior>::issued(installed.clone());
1038 let same_actor = EstablishedActor::<LocalBehavior>::issued(installed);
1039 let (other_control, _other_consumer) = std::sync::mpsc::channel();
1040 let other_actor = EstablishedActor::<LocalBehavior>::issued(LocalInstalled {
1041 endpoint: other_recipient
1042 .clone()
1043 .interpret(&mut LocalEndpointTransfer),
1044 control: other_control,
1045 incarnation: Rc::new(()),
1046 });
1047 assert_eq!(actor, same_actor);
1048 assert_ne!(actor, other_actor);
1049 assert_eq!(format!("{actor:?}"), "EstablishedActor(LocalInstalled)");
1050
1051 let delivery = EstablishedDelivery::new(recipient, 7);
1052 let same_delivery = EstablishedDelivery::new(same_recipient.clone(), 7);
1053 let other_destination = EstablishedDelivery::new(other_recipient.clone(), 7);
1054 let other_message = EstablishedDelivery::new(same_recipient, 9);
1055 let both_different = EstablishedDelivery::new(other_recipient, 9);
1056 assert_eq!(delivery, same_delivery);
1057 assert_ne!(delivery, other_destination);
1058 assert_ne!(delivery, other_message);
1059 assert_ne!(delivery, both_different);
1060 assert_eq!(
1061 format!("{delivery:?}"),
1062 "EstablishedDelivery { to: EstablishedRecipient(LocalEndpoint), message: 7 }"
1063 );
1064 }
1065
1066 #[test]
1067 fn delivery_equality_requires_both_destination_and_message() {
1068 let value = Delivery::<Inbox>::new(Recipient::global(MailAddr(1)), 5);
1069 let same = Delivery::<Inbox>::new(Recipient::global(MailAddr(1)), 5);
1070 let other_destination = Delivery::<Inbox>::new(Recipient::global(MailAddr(2)), 5);
1071 let other_message = Delivery::<Inbox>::new(Recipient::global(MailAddr(1)), 6);
1072 let both_different = Delivery::<Inbox>::new(Recipient::global(MailAddr(2)), 6);
1073
1074 assert!(value == same);
1075 assert!(value != other_destination);
1076 assert!(value != other_message);
1077 assert!(value != both_different);
1078 }
1079}