Skip to main content

behavior/actor/
addressing.rs

1//! Protocol-indexed actor recipients and deliveries.
2
3use core::marker::PhantomData;
4
5use crate::{
6    ActionItem, Behavior, InterpretationProgress, ItemSettlement, MessageProtocol, Never, Protocol,
7    finish_item, prepare_item,
8};
9
10/// A pure logical actor-address namespace.
11///
12/// An address names a transport or resolution domain. It does not allocate an
13/// actor and it does not prove that an actor is installed. Fresh allocation is
14/// interpreter-owned; the creator-local [`Address::Nonce`] is correlation
15/// evidence only and is deliberately not convertible into an address here.
16pub 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
39/// Runtime-owned exact message endpoint family for one logical address namespace.
40///
41/// A runtime implements this trait on its own address newtype, selecting one
42/// statically projected endpoint representation for each concrete protocol.
43/// The projection may reuse a representation; [`EstablishedRecipient<P>`]
44/// still preserves `P` and prevents cross-protocol substitution. Ordinary
45/// protocols continue to declare only their canonical [`Protocol::Addr`] and
46/// [`Protocol::Msg`]; they never author endpoint keys or endpoint associated
47/// types. An endpoint is cloneable acquaintance evidence, but it is not
48/// intrinsically `Send`: thread transfer is required only by the concrete
49/// asynchronous interpretation boundary that performs it.
50///
51/// A local endpoint remains valid, but cannot enter the sendable
52/// [`crate::InterpretSends`] path:
53///
54/// ```compile_fail,E0277
55/// #[derive(Clone, Copy, PartialEq, Eq)]
56/// struct LocalAddr(u8);
57/// impl behavior::Address for LocalAddr { type Nonce = u8; }
58/// struct LocalEndpoint<P>(std::rc::Rc<()>, core::marker::PhantomData<fn() -> P>);
59/// impl<P> Clone for LocalEndpoint<P> {
60///     fn clone(&self) -> Self { Self(self.0.clone(), core::marker::PhantomData) }
61/// }
62/// impl behavior::RecipientAddress for LocalAddr {
63///     type Established<P> = LocalEndpoint<P> where P: behavior::Protocol<Addr = Self>;
64/// }
65/// struct LocalProtocol;
66/// impl behavior::Protocol for LocalProtocol {
67///     type Addr = LocalAddr;
68///     type Msg = std::rc::Rc<()>;
69/// }
70/// struct Runtime;
71/// impl<RootEvent, Path> behavior::InterpretItem<behavior::EstablishedDelivery<LocalProtocol>, RootEvent, Path>
72///     for Runtime
73/// {
74///     fn interpret_item<'a>(&'a mut self, input: &'a mut Option<behavior::EstablishedDelivery<LocalProtocol>>, received: &'a mut Option<behavior::ItemSettlement<behavior::EstablishedDelivery<LocalProtocol>, (), behavior::ExactDeliveryReason, behavior::Never>>) -> impl core::future::Future<Output = ()> + Send + 'a where behavior::EstablishedDelivery<LocalProtocol>: 'a {
75///         async move {
76///             if received.is_some() { return; }
77///             let Some(delivery) = input.take() else { return; };
78///             drop(delivery);
79///             *received = Some(behavior::ItemSettlement::Accepted(()));
80///         }
81///     }
82/// }
83/// fn require_async<T>()
84/// where
85///     T: behavior::InterpretSends<Runtime, behavior::User<LocalAddr, std::rc::Rc<()>>, behavior::Here>,
86/// {}
87/// let endpoint = LocalEndpoint(std::rc::Rc::new(()), core::marker::PhantomData);
88/// let recipient = behavior::EstablishedRecipient::<LocalProtocol>::issued(endpoint);
89/// let _delivery = behavior::EstablishedDelivery::new(recipient, std::rc::Rc::new(()));
90/// require_async::<Vec<behavior::EstablishedDelivery<LocalProtocol>>>();
91/// ```
92pub trait RecipientAddress: Address + Sized {
93    type Established<P>: Clone
94    where
95        P: Protocol<Addr = Self>;
96}
97
98/// Runtime-owned installed actor family for an address namespace.
99///
100/// The runtime must bind one protocol endpoint and its matching concrete
101/// lifecycle authority to the same incarnation before issuing this value.
102/// A namespace used only for protocol messaging implements
103/// [`RecipientAddress`] without this stronger port.
104pub 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    /// Project the message-only endpoint from one installed actor.
114    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
128/// Pure logical destination for one concrete protocol signature.
129///
130/// The destination protocol owner is part of the type even when two protocols
131/// share the same address namespace and message type. This value proves only
132/// the static signature at a logical address; it does not prove that an exact
133/// executable incarnation has been installed there. Addressed recipients are
134/// retained for genuine transport and name-resolution boundaries.
135pub 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    /// Return the logical address, independent of any sending actor.
155    #[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
174/// Inert capability for one exact protocol endpoint.
175///
176/// The endpoint type is selected by `P::Addr`, so `P` remains the only
177/// protocol identity and ordinary domain types carry no endpoint parameter.
178/// The endpoint has no direct accessor or send method. It crosses only an
179/// explicit interpretation boundary. That boundary is public and therefore a
180/// deliberate power-user authority boundary, not exclusive runtime authority.
181///
182/// ```compile_fail,E0599
183/// #[derive(Clone, Copy, PartialEq, Eq)]
184/// struct RuntimeAddr(u64);
185/// impl behavior::Address for RuntimeAddr { type Nonce = u64; }
186/// struct Worker;
187/// impl behavior::Protocol for Worker { type Addr = RuntimeAddr; type Msg = (); }
188/// #[derive(Clone)]
189/// struct Endpoint;
190/// impl behavior::RecipientAddress for RuntimeAddr {
191///     type Established<P> = Endpoint where P: behavior::Protocol<Addr = Self>;
192/// }
193/// let recipient = behavior::EstablishedRecipient::<Worker>::issued(Endpoint);
194/// let _endpoint = recipient.endpoint();
195/// ```
196pub 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    /// Issue a capability from an exact endpoint established or imported by
210    /// an interpreter.
211    ///
212    /// This constructor performs no allocation or validation. It proves only
213    /// protocol messaging; it never establishes a concrete behavior or
214    /// lifecycle authority.
215    #[must_use]
216    pub const fn issued(endpoint: <P::Addr as RecipientAddress>::Established<P>) -> Self {
217        Self { endpoint }
218    }
219
220    /// Transfer the endpoint through an explicit interpretation boundary.
221    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
229/// Public power-user transfer boundary for one exact endpoint.
230pub 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
286/// Inert capability for one exact installed concrete behavior.
287///
288/// An established recipient proves the public protocol endpoint. This value
289/// additionally preserves which concrete behavior was installed, allowing
290/// lifecycle effects to require static evidence about that behavior's event
291/// algebra. It remains inert: no direct send, shutdown, endpoint accessor, or
292/// other ambient effect is exposed.
293///
294/// A protocol recipient cannot issue installed-actor authority:
295///
296/// ```compile_fail,E0271
297/// #[derive(Clone, Copy, Eq, PartialEq)]
298/// struct RuntimeAddr;
299/// impl behavior::Address for RuntimeAddr { type Nonce = u8; }
300/// #[derive(Clone)]
301/// struct Endpoint;
302/// struct Installed<B: behavior::Behavior>(Endpoint, std::sync::mpsc::Sender<B::Event>);
303/// impl<B: behavior::Behavior> Clone for Installed<B> {
304///     fn clone(&self) -> Self { Self(self.0.clone(), self.1.clone()) }
305/// }
306/// impl behavior::EndpointAddress for RuntimeAddr {
307///     type Established<P> = Endpoint where P: behavior::Protocol<Addr = Self>;
308///     type Installed<B> = Installed<B>
309///         where B: behavior::Behavior<Protocol: behavior::Protocol<Addr = Self>>;
310///     fn recipient<B>(installed: &Self::Installed<B>) -> Endpoint
311///     where B: behavior::Behavior<Protocol: behavior::Protocol<Addr = Self>> {
312///         installed.0.clone()
313///     }
314/// }
315/// struct Worker;
316/// impl behavior::Protocol for Worker { type Addr = RuntimeAddr; type Msg = (); }
317/// impl behavior::Behavior for Worker {
318///     type Protocol = Self;
319///     type Event = behavior::User<RuntimeAddr, ()>;
320///     type Sends = behavior::NoSends;
321///     type Ph = behavior::Never;
322///     type Error = behavior::Never;
323///     type Birth = behavior::NoBirths;
324///     fn transition(&mut self, _: behavior::ActiveTurn, _: Self::Event)
325///         -> behavior::BehaviorActed<Self> { Ok(behavior::Actions::cont()) }
326/// }
327/// let recipient = behavior::EstablishedRecipient::<Worker>::issued(Endpoint);
328/// let _: behavior::EstablishedActor<Worker> = behavior::EstablishedActor::issued(recipient);
329/// ```
330///
331/// Two behaviors sharing one protocol retain distinct installed authority:
332///
333/// ```compile_fail,E0308
334/// #[derive(Clone, Copy, Eq, PartialEq)]
335/// struct RuntimeAddr;
336/// impl behavior::Address for RuntimeAddr { type Nonce = u8; }
337/// #[derive(Clone)]
338/// struct Endpoint;
339/// struct Installed<B: behavior::Behavior>(Endpoint, std::sync::mpsc::Sender<B::Event>);
340/// impl<B: behavior::Behavior> Clone for Installed<B> {
341///     fn clone(&self) -> Self { Self(self.0.clone(), self.1.clone()) }
342/// }
343/// impl behavior::EndpointAddress for RuntimeAddr {
344///     type Established<P> = Endpoint where P: behavior::Protocol<Addr = Self>;
345///     type Installed<B> = Installed<B>
346///         where B: behavior::Behavior<Protocol: behavior::Protocol<Addr = Self>>;
347///     fn recipient<B>(installed: &Self::Installed<B>) -> Endpoint
348///     where B: behavior::Behavior<Protocol: behavior::Protocol<Addr = Self>> {
349///         installed.0.clone()
350///     }
351/// }
352/// struct Shared;
353/// impl behavior::Protocol for Shared { type Addr = RuntimeAddr; type Msg = (); }
354/// struct First;
355/// struct Second;
356/// impl behavior::Behavior for First {
357///     type Protocol = Shared;
358///     type Event = behavior::User<RuntimeAddr, ()>;
359///     type Sends = behavior::NoSends;
360///     type Ph = behavior::Never;
361///     type Error = behavior::Never;
362///     type Birth = behavior::NoBirths;
363///     fn transition(&mut self, _: behavior::ActiveTurn, _: Self::Event)
364///         -> behavior::BehaviorActed<Self> { Ok(behavior::Actions::cont()) }
365/// }
366/// impl behavior::Behavior for Second {
367///     type Protocol = Shared;
368///     type Event = behavior::EventLayer<u8, behavior::User<RuntimeAddr, ()>>;
369///     type Sends = behavior::NoSends;
370///     type Ph = behavior::Never;
371///     type Error = behavior::Never;
372///     type Birth = behavior::NoBirths;
373///     fn transition(&mut self, _: behavior::ActiveTurn, _: Self::Event)
374///         -> behavior::BehaviorActed<Self> { Ok(behavior::Actions::cont()) }
375/// }
376/// let (control, _inbox) = std::sync::mpsc::channel::<<First as behavior::Behavior>::Event>();
377/// let first = behavior::EstablishedActor::<First>::issued(Installed(Endpoint, control));
378/// let _: behavior::EstablishedActor<Second> = first;
379/// ```
380pub 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    /// Issue an exact actor capability after successful installation.
394    ///
395    /// This power-user boundary accepts one runtime-owned installed value.
396    /// Only successful fresh installation and binding commit may issue it.
397    /// It performs no allocation or validation itself.
398    #[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    /// Project the exact public-protocol recipient for this incarnation.
406    #[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    /// Consume the concrete-actor proof and retain its exact protocol
414    /// recipient.
415    #[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    /// Transfer the complete installed value with its exact `B` index.
423    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
431/// Public power-user transfer boundary for one exact installed actor.
432pub 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/// One pure communication addressed to a concrete protocol signature.
507///
508/// Protocol identity is not inferred from the payload. Consequently, two
509/// protocols with the same address and message types still have distinct
510/// delivery types.
511///
512/// ```compile_fail,E0308
513/// struct Queue;
514/// struct Worker;
515/// impl behavior::Protocol for Queue {
516///     type Addr = behavior::MailAddr;
517///     type Msg = u8;
518/// }
519/// impl behavior::Protocol for Worker {
520///     type Addr = behavior::MailAddr;
521///     type Msg = u8;
522/// }
523///
524/// let worker = behavior::Recipient::<Worker>::global(behavior::MailAddr(1));
525/// let _: behavior::Delivery<Queue> = behavior::Delivery::new(worker, 7);
526/// ```
527///
528/// A destination also fixes its message and address namespaces:
529///
530/// ```compile_fail,E0308
531/// #[derive(Clone, Copy, PartialEq, Eq)]
532/// struct OtherAddr(u64);
533/// impl behavior::Address for OtherAddr {
534///     type Nonce = u64;
535/// }
536/// struct Worker;
537/// impl behavior::Protocol for Worker {
538///     type Addr = behavior::MailAddr;
539///     type Msg = u8;
540/// }
541/// let _ = behavior::Recipient::<Worker>::global(OtherAddr(1));
542/// ```
543///
544/// ```compile_fail,E0308
545/// # struct Worker;
546/// # impl behavior::Protocol for Worker {
547/// #     type Addr = behavior::MailAddr;
548/// #     type Msg = u8;
549/// # }
550/// let worker = behavior::Recipient::<Worker>::global(behavior::MailAddr(1));
551/// let _ = behavior::Delivery::<Worker>::new(worker, "wrong payload");
552/// ```
553/// Exact reason one logical delivery was not accepted.
554#[derive(Clone, Copy, Debug, Eq, PartialEq)]
555pub enum LogicalDeliveryReason {
556    UnknownAddress,
557    ClosedRecipient,
558}
559
560/// Exact reason one established delivery was not accepted.
561#[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
650/// One pure communication to an exact installed incarnation.
651///
652/// Unlike [`Delivery`], this effect carries the runtime-issued endpoint and
653/// requires no address-to-endpoint resolution. Constructing it remains pure;
654/// only an explicit [`crate::InterpretItem`] implementation for this exact
655/// delivery type can
656/// perform the communication.
657///
658/// Exact endpoints remain protocol-indexed even when two protocols share an
659/// address namespace and message type:
660///
661/// ```compile_fail,E0308
662/// #[derive(Clone, Copy, PartialEq, Eq)]
663/// struct RuntimeAddr(u64);
664/// impl behavior::Address for RuntimeAddr { type Nonce = u64; }
665/// struct Endpoint<P>(core::marker::PhantomData<fn() -> P>);
666/// impl<P> Clone for Endpoint<P> {
667///     fn clone(&self) -> Self { Self(core::marker::PhantomData) }
668/// }
669/// impl behavior::RecipientAddress for RuntimeAddr {
670///     type Established<P> = Endpoint<P> where P: behavior::Protocol<Addr = Self>;
671/// }
672/// struct Queue;
673/// struct Worker;
674/// impl behavior::Protocol for Queue { type Addr = RuntimeAddr; type Msg = u8; }
675/// impl behavior::Protocol for Worker { type Addr = RuntimeAddr; type Msg = u8; }
676/// let worker = behavior::EstablishedRecipient::<Worker>::issued(Endpoint(core::marker::PhantomData));
677/// let _: behavior::EstablishedDelivery<Queue> = behavior::EstablishedDelivery::new(worker, 7);
678/// ```
679pub 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}