1use core::marker::PhantomData;
4
5use crate::{ActionItem, Behavior, MessageProtocol, Never, Protocol};
6
7pub trait Address: Copy + Eq {
14 type Nonce: Copy + Eq;
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub struct MailAddr(pub u64);
19
20impl From<u64> for MailAddr {
21 fn from(value: u64) -> Self {
22 Self(value)
23 }
24}
25
26impl From<MailAddr> for u64 {
27 fn from(value: MailAddr) -> Self {
28 value.0
29 }
30}
31
32impl Address for MailAddr {
33 type Nonce = u64;
34}
35
36pub 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 Accepted = ();
615 type Rejection = LogicalDeliveryReason;
616 type Prerequisite = Never;
617}
618
619pub struct EstablishedDelivery<P>
649where
650 P: Protocol,
651 P::Addr: RecipientAddress,
652{
653 pub to: EstablishedRecipient<P>,
654 pub message: P::Msg,
655}
656
657impl<P> EstablishedDelivery<P>
658where
659 P: Protocol,
660 P::Addr: RecipientAddress,
661{
662 #[must_use]
663 pub const fn new(to: EstablishedRecipient<P>, message: P::Msg) -> Self {
664 Self { to, message }
665 }
666}
667
668impl<P> Clone for EstablishedDelivery<P>
669where
670 P: Protocol,
671 P::Addr: RecipientAddress,
672 P::Msg: Clone,
673{
674 fn clone(&self) -> Self {
675 Self::new(self.to.clone(), self.message.clone())
676 }
677}
678
679impl<P> core::fmt::Debug for EstablishedDelivery<P>
680where
681 P: Protocol,
682 P::Addr: RecipientAddress,
683 EstablishedRecipient<P>: core::fmt::Debug,
684 P::Msg: core::fmt::Debug,
685{
686 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
687 formatter
688 .debug_struct("EstablishedDelivery")
689 .field("to", &self.to)
690 .field("message", &self.message)
691 .finish()
692 }
693}
694
695impl<P> PartialEq for EstablishedDelivery<P>
696where
697 P: Protocol,
698 P::Addr: RecipientAddress,
699 EstablishedRecipient<P>: PartialEq,
700 P::Msg: PartialEq,
701{
702 fn eq(&self, other: &Self) -> bool {
703 self.to == other.to && self.message == other.message
704 }
705}
706
707impl<P> Eq for EstablishedDelivery<P>
708where
709 P: Protocol,
710 P::Addr: RecipientAddress,
711 EstablishedRecipient<P>: Eq,
712 P::Msg: Eq,
713{
714}
715
716impl<P> ActionItem for EstablishedDelivery<P>
717where
718 P: Protocol,
719 P::Addr: RecipientAddress,
720 <P::Addr as RecipientAddress>::Established<P>: Send,
721 P::Msg: Send,
722{
723 type Accepted = ();
724 type Rejection = ExactDeliveryReason;
725 type Prerequisite = Never;
726}
727
728#[cfg(test)]
729mod tests {
730 use super::*;
731 use crate::{Actions, Never, NoBirths, User};
732 use std::rc::Rc;
733
734 struct Inbox;
735
736 struct SignatureOnly;
737
738 #[derive(Clone, Copy, PartialEq, Eq)]
739 struct LocalAddr(u8);
740
741 impl Address for LocalAddr {
742 type Nonce = u8;
743 }
744
745 struct LocalProtocol;
746
747 impl Protocol for LocalProtocol {
748 type Addr = LocalAddr;
749 type Msg = u8;
750 }
751
752 struct LocalEndpoint<P> {
753 token: Rc<()>,
754 protocol: PhantomData<fn() -> P>,
755 }
756
757 impl<P> Clone for LocalEndpoint<P> {
758 fn clone(&self) -> Self {
759 Self {
760 token: self.token.clone(),
761 protocol: PhantomData,
762 }
763 }
764 }
765
766 impl<P> core::fmt::Debug for LocalEndpoint<P> {
767 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
768 formatter.write_str("LocalEndpoint")
769 }
770 }
771
772 impl<P> PartialEq for LocalEndpoint<P> {
773 fn eq(&self, other: &Self) -> bool {
774 Rc::ptr_eq(&self.token, &other.token)
775 }
776 }
777
778 impl<P> Eq for LocalEndpoint<P> {}
779
780 struct LocalInstalled<B: Behavior> {
781 endpoint: LocalEndpoint<B::Protocol>,
782 control: std::sync::mpsc::Sender<B::Event>,
783 incarnation: Rc<()>,
784 }
785
786 impl<B: Behavior> Clone for LocalInstalled<B> {
787 fn clone(&self) -> Self {
788 Self {
789 endpoint: self.endpoint.clone(),
790 control: self.control.clone(),
791 incarnation: self.incarnation.clone(),
792 }
793 }
794 }
795
796 impl<B: Behavior> core::fmt::Debug for LocalInstalled<B> {
797 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
798 formatter.write_str("LocalInstalled")
799 }
800 }
801
802 impl<B: Behavior> PartialEq for LocalInstalled<B> {
803 fn eq(&self, other: &Self) -> bool {
804 Rc::ptr_eq(&self.incarnation, &other.incarnation)
805 }
806 }
807
808 impl<B: Behavior> Eq for LocalInstalled<B> {}
809
810 impl EndpointAddress for LocalAddr {
811 type Established<P>
812 = LocalEndpoint<P>
813 where
814 P: Protocol<Addr = Self>;
815
816 type Installed<B>
817 = LocalInstalled<B>
818 where
819 B: Behavior<Protocol: Protocol<Addr = Self>>;
820
821 fn recipient<B>(installed: &Self::Installed<B>) -> Self::Established<B::Protocol>
822 where
823 B: Behavior<Protocol: Protocol<Addr = Self>>,
824 {
825 installed.endpoint.clone()
826 }
827 }
828
829 struct LocalTransfer;
830
831 impl InterpretEstablished<LocalProtocol> for LocalTransfer {
832 type Output = Rc<()>;
833
834 fn interpret_established(
835 &mut self,
836 endpoint: LocalEndpoint<LocalProtocol>,
837 ) -> Self::Output {
838 endpoint.token
839 }
840 }
841
842 struct LocalEndpointTransfer;
843
844 impl InterpretEstablished<LocalProtocol> for LocalEndpointTransfer {
845 type Output = LocalEndpoint<LocalProtocol>;
846
847 fn interpret_established(
848 &mut self,
849 endpoint: LocalEndpoint<LocalProtocol>,
850 ) -> Self::Output {
851 endpoint
852 }
853 }
854
855 struct LocalBehavior;
856
857 impl Behavior for LocalBehavior {
858 type Protocol = LocalProtocol;
859 type Event = User<LocalAddr, u8>;
860 type Sends = Vec<Never>;
861 type Ph = Never;
862 type Error = Never;
863 type Birth = NoBirths;
864
865 fn transition(
866 &mut self,
867 _: crate::ActiveTurn,
868 _: Self::Event,
869 ) -> crate::BehaviorActed<Self> {
870 Ok(Actions::cont())
871 }
872 }
873
874 impl crate::Protocol for SignatureOnly {
875 type Addr = MailAddr;
876 type Msg = u8;
877 }
878
879 impl behavior::Protocol for Inbox {
880 type Addr = MailAddr;
881 type Msg = u8;
882 }
883
884 impl Behavior for Inbox {
885 type Protocol = Self;
886 type Event = User<MailAddr, u8>;
887 type Sends = Vec<Never>;
888 type Ph = Never;
889 type Error = Never;
890 type Birth = NoBirths;
891
892 fn init(&mut self, _: crate::InitializationTurn) -> crate::BehaviorActed<Self> {
893 Ok(Actions::cont())
894 }
895
896 fn transition(
897 &mut self,
898 _: crate::ActiveTurn,
899 _: Self::Event,
900 ) -> crate::BehaviorActed<Self> {
901 Ok(Actions::cont())
902 }
903 }
904
905 #[test]
906 fn mail_address_conversion_preserves_nonzero_value() {
907 assert_eq!(u64::from(MailAddr(41)), 41);
908 }
909
910 #[test]
911 fn routing_requires_only_the_static_protocol_signature() {
912 let recipient = Recipient::<SignatureOnly>::global(MailAddr(7));
913 let delivery = Delivery::new(recipient, 11);
914
915 assert_eq!(delivery.to.address(), MailAddr(7));
916 assert_eq!(delivery.message, 11);
917 }
918
919 #[test]
920 fn recipient_value_contract_distinguishes_logical_addresses() {
921 let global = Recipient::<Inbox>::global(MailAddr(7));
922 let same_global = Recipient::<Inbox>::global(MailAddr(7));
923 let other_global = Recipient::<Inbox>::global(MailAddr(8));
924
925 assert_eq!(global, same_global);
926 assert_ne!(global, other_global);
927 assert_eq!(global.address(), MailAddr(7));
928 assert_eq!(format!("{global:?}"), "MailAddr(7)");
929 }
930
931 #[test]
932 fn established_capability_accepts_a_local_non_send_endpoint() {
933 let token = Rc::new(());
934 let recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
935 token: token.clone(),
936 protocol: PhantomData,
937 });
938 let retained = recipient.clone();
939 let extracted = retained.interpret(&mut LocalTransfer);
940
941 assert!(Rc::ptr_eq(&token, &extracted));
942 drop(recipient);
943 }
944
945 #[test]
946 fn established_values_compare_complete_identity_and_expose_debug_shape() {
947 let token = Rc::new(());
948 let other_token = Rc::new(());
949 let recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
950 token: token.clone(),
951 protocol: PhantomData,
952 });
953 let same_recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
954 token,
955 protocol: PhantomData,
956 });
957 let other_recipient = EstablishedRecipient::<LocalProtocol>::issued(LocalEndpoint {
958 token: other_token,
959 protocol: PhantomData,
960 });
961
962 assert_eq!(recipient, same_recipient);
963 assert_ne!(recipient, other_recipient);
964 assert_eq!(
965 format!("{recipient:?}"),
966 "EstablishedRecipient(LocalEndpoint)"
967 );
968
969 let (control, _consumer) = std::sync::mpsc::channel();
970 let installed = LocalInstalled {
971 endpoint: recipient.clone().interpret(&mut LocalEndpointTransfer),
972 control,
973 incarnation: Rc::new(()),
974 };
975 let actor = EstablishedActor::<LocalBehavior>::issued(installed.clone());
976 let same_actor = EstablishedActor::<LocalBehavior>::issued(installed);
977 let (other_control, _other_consumer) = std::sync::mpsc::channel();
978 let other_actor = EstablishedActor::<LocalBehavior>::issued(LocalInstalled {
979 endpoint: other_recipient
980 .clone()
981 .interpret(&mut LocalEndpointTransfer),
982 control: other_control,
983 incarnation: Rc::new(()),
984 });
985 assert_eq!(actor, same_actor);
986 assert_ne!(actor, other_actor);
987 assert_eq!(format!("{actor:?}"), "EstablishedActor(LocalInstalled)");
988
989 let delivery = EstablishedDelivery::new(recipient, 7);
990 let same_delivery = EstablishedDelivery::new(same_recipient.clone(), 7);
991 let other_destination = EstablishedDelivery::new(other_recipient.clone(), 7);
992 let other_message = EstablishedDelivery::new(same_recipient, 9);
993 let both_different = EstablishedDelivery::new(other_recipient, 9);
994 assert_eq!(delivery, same_delivery);
995 assert_ne!(delivery, other_destination);
996 assert_ne!(delivery, other_message);
997 assert_ne!(delivery, both_different);
998 assert_eq!(
999 format!("{delivery:?}"),
1000 "EstablishedDelivery { to: EstablishedRecipient(LocalEndpoint), message: 7 }"
1001 );
1002 }
1003
1004 #[test]
1005 fn delivery_equality_requires_both_destination_and_message() {
1006 let value = Delivery::<Inbox>::new(Recipient::global(MailAddr(1)), 5);
1007 let same = Delivery::<Inbox>::new(Recipient::global(MailAddr(1)), 5);
1008 let other_destination = Delivery::<Inbox>::new(Recipient::global(MailAddr(2)), 5);
1009 let other_message = Delivery::<Inbox>::new(Recipient::global(MailAddr(1)), 6);
1010 let both_different = Delivery::<Inbox>::new(Recipient::global(MailAddr(2)), 6);
1011
1012 assert!(value == same);
1013 assert!(value != other_destination);
1014 assert!(value != other_message);
1015 assert!(value != both_different);
1016 }
1017}