actix/address/
envelope.rs

1use tokio::sync::oneshot::Sender;
2
3use crate::{
4    actor::{Actor, AsyncContext},
5    context::Context,
6    handler::{Handler, Message, MessageResponse},
7};
8
9/// Converter trait, packs message into a suitable envelope.
10pub trait ToEnvelope<A, M: Message>
11where
12    A: Actor + Handler<M>,
13    A::Context: ToEnvelope<A, M>,
14{
15    /// Pack message into suitable envelope
16    fn pack(msg: M, tx: Option<Sender<M::Result>>) -> Envelope<A>;
17}
18
19pub trait EnvelopeProxy<A: Actor> {
20    /// handle message within new actor and context
21    fn handle(&mut self, act: &mut A, ctx: &mut A::Context);
22}
23
24impl<A, M> ToEnvelope<A, M> for Context<A>
25where
26    A: Actor<Context = Context<A>> + Handler<M>,
27    M: Message + Send + 'static,
28    M::Result: Send,
29{
30    fn pack(msg: M, tx: Option<Sender<M::Result>>) -> Envelope<A> {
31        Envelope::new(msg, tx)
32    }
33}
34
35pub struct Envelope<A: Actor>(Box<dyn EnvelopeProxy<A> + Send>);
36
37impl<A: Actor> Envelope<A> {
38    pub fn new<M>(msg: M, tx: Option<Sender<M::Result>>) -> Self
39    where
40        A: Handler<M>,
41        A::Context: AsyncContext<A>,
42        M: Message + Send + 'static,
43        M::Result: Send,
44    {
45        Envelope(Box::new(SyncEnvelopeProxy { tx, msg: Some(msg) }))
46    }
47
48    pub fn with_proxy(proxy: Box<dyn EnvelopeProxy<A> + Send>) -> Self {
49        Envelope(proxy)
50    }
51}
52
53impl<A: Actor> EnvelopeProxy<A> for Envelope<A> {
54    fn handle(&mut self, act: &mut A, ctx: &mut <A as Actor>::Context) {
55        self.0.handle(act, ctx)
56    }
57}
58
59pub struct SyncEnvelopeProxy<M>
60where
61    M: Message + Send,
62    M::Result: Send,
63{
64    msg: Option<M>,
65    tx: Option<Sender<M::Result>>,
66}
67
68impl<A, M> EnvelopeProxy<A> for SyncEnvelopeProxy<M>
69where
70    M: Message + Send + 'static,
71    M::Result: Send,
72    A: Actor + Handler<M>,
73    A::Context: AsyncContext<A>,
74{
75    fn handle(&mut self, act: &mut A, ctx: &mut <A as Actor>::Context) {
76        let tx = self.tx.take();
77        if tx.is_some() && tx.as_ref().unwrap().is_closed() {
78            return;
79        }
80
81        if let Some(msg) = self.msg.take() {
82            let fut = <A as Handler<M>>::handle(act, msg, ctx);
83            fut.handle(ctx, tx)
84        }
85    }
86}