Skip to main content

behavior/actor/
addressing.rs

1//! Typed actor addresses, routes, recipients, and deliveries.
2
3use core::marker::PhantomData;
4
5/// A pure actor-address namespace.
6pub trait Address: Copy + Eq {
7    type Nonce: Copy + Eq;
8
9    #[must_use]
10    fn birth(self, nonce: Self::Nonce) -> Self;
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub struct MailAddr(pub u64);
15
16impl From<u64> for MailAddr {
17    fn from(value: u64) -> Self {
18        Self(value)
19    }
20}
21
22impl From<MailAddr> for u64 {
23    fn from(value: MailAddr) -> Self {
24        value.0
25    }
26}
27
28impl Address for MailAddr {
29    type Nonce = u64;
30
31    fn birth(self, nonce: u64) -> Self {
32        Self(self.0 ^ nonce.wrapping_mul(0x9E37_79B9_7F4A_7C15))
33    }
34}
35
36/// An address expression for ordinary actor delivery.
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum Route<A: Address> {
39    Global(A),
40    Child(A::Nonce),
41}
42
43impl<A: Address> Route<A> {
44    #[must_use]
45    pub const fn global(address: A) -> Self {
46        Self::Global(address)
47    }
48
49    #[must_use]
50    pub const fn child(nonce: A::Nonce) -> Self {
51        Self::Child(nonce)
52    }
53}
54
55impl<A: Address> From<A> for Route<A> {
56    fn from(address: A) -> Self {
57        Self::global(address)
58    }
59}
60
61/// A recipient statically coupled to the message it accepts.
62pub struct Recipient<A: Address, M> {
63    route: Route<A>,
64    message: PhantomData<fn(M)>,
65}
66
67impl<A: Address, M> Copy for Recipient<A, M> {}
68
69impl<A: Address, M> Clone for Recipient<A, M> {
70    fn clone(&self) -> Self {
71        *self
72    }
73}
74
75impl<A: Address, M> Recipient<A, M> {
76    #[must_use]
77    pub fn global(address: A) -> Self {
78        Self::from(Route::global(address))
79    }
80
81    #[must_use]
82    pub fn child(nonce: A::Nonce) -> Self {
83        Self::from(Route::child(nonce))
84    }
85
86    #[must_use]
87    pub fn route(self) -> Route<A> {
88        self.route
89    }
90
91    const fn from_route(route: Route<A>) -> Self {
92        Self {
93            route,
94            message: PhantomData,
95        }
96    }
97}
98
99impl<A: Address, M> From<Route<A>> for Recipient<A, M> {
100    fn from(route: Route<A>) -> Self {
101        Self::from_route(route)
102    }
103}
104
105impl<A: Address, M> PartialEq for Recipient<A, M> {
106    fn eq(&self, other: &Self) -> bool {
107        self.route == other.route
108    }
109}
110
111impl<A: Address, M> Eq for Recipient<A, M> {}
112
113impl<A: Address + core::fmt::Debug, M> core::fmt::Debug for Recipient<A, M>
114where
115    A::Nonce: core::fmt::Debug,
116{
117    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
118        self.route.fmt(f)
119    }
120}
121
122/// One statically typed send operation.
123#[derive(Clone, PartialEq, Eq)]
124pub struct Delivery<A: Address, M> {
125    pub to: Recipient<A, M>,
126    pub message: M,
127}
128
129impl<A: Address, M> Delivery<A, M> {
130    #[must_use]
131    pub fn new(to: Recipient<A, M>, message: M) -> Self {
132        Self { to, message }
133    }
134}