Skip to main content

behavior/effects/
actions.rs

1//! The explicit result of one actor behavior transition.
2
3use super::sending::SendAlgebra;
4use crate::actor::{Address, BirthMode, Create};
5use crate::next::{Never, Step, Stopped};
6
7pub type Become<Ph = Never> = Step<Ph, Stopped>;
8
9/// Bombay's typed realization of the actor transition effects: communications,
10/// fresh actor creation, and next behavior or termination.
11///
12/// An interpreter resolves every fresh creation in `creates` before
13/// interpreting any ordinary delivery or [`crate::ServiceSends`] request in
14/// `sends` from this value. A successful resolution installs and binds the
15/// child; a rejected resolution binds nothing. This ordering lets a same-action
16/// [`crate::ObserveCreation`] request return the committed result rather than
17/// the behavior's intent. When creation is rejected, a same-action
18/// [`crate::ObserveChild`] for its nonce is consumed without installing an
19/// observation or emitting [`crate::ChildStopped`], while
20/// [`crate::ObserveCreation`] reports the rejection. A later creation cannot
21/// inherit that consumed observation. Creation order is vector order, and each
22/// concrete named send lane retains its own order; this contract does not
23/// impose an order between independent lanes. Constructing a value remains
24/// pure.
25pub struct Actions<A: Address, Ph, Sends, Birth: BirthMode> {
26    pub sends: Sends,
27    pub creates: Vec<Create<A, Birth::Child>>,
28    pub become_: Become<Ph>,
29}
30
31impl<A, Ph, Sends, Birth> core::fmt::Debug for Actions<A, Ph, Sends, Birth>
32where
33    A: Address + core::fmt::Debug,
34    A::Nonce: core::fmt::Debug,
35    Ph: core::fmt::Debug,
36    Sends: core::fmt::Debug,
37    Birth: BirthMode,
38    Birth::Child: core::fmt::Debug,
39{
40    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41        formatter
42            .debug_struct("Actions")
43            .field("sends", &self.sends)
44            .field("creates", &self.creates)
45            .field("become", &self.become_)
46            .finish()
47    }
48}
49
50impl<A, Ph, Sends, Birth> PartialEq for Actions<A, Ph, Sends, Birth>
51where
52    A: Address + PartialEq,
53    A::Nonce: PartialEq,
54    Ph: PartialEq,
55    Sends: PartialEq,
56    Birth: BirthMode,
57    Birth::Child: PartialEq,
58{
59    fn eq(&self, other: &Self) -> bool {
60        self.sends == other.sends && self.creates == other.creates && self.become_ == other.become_
61    }
62}
63
64impl<A, Ph, Sends, Birth> Eq for Actions<A, Ph, Sends, Birth>
65where
66    A: Address + Eq,
67    A::Nonce: Eq,
68    Ph: Eq,
69    Sends: Eq,
70    Birth: BirthMode,
71    Birth::Child: Eq,
72{
73}
74
75impl<A: Address, Ph, Sends, Birth: BirthMode> Actions<A, Ph, Sends, Birth> {
76    /// Transform only the send algebra, preserving creation order and the
77    /// next-behavior verdict exactly.
78    #[must_use]
79    pub fn map_sends<Mapped>(
80        self,
81        map: impl FnOnce(Sends) -> Mapped,
82    ) -> Actions<A, Ph, Mapped, Birth> {
83        Actions {
84            sends: map(self.sends),
85            creates: self.creates,
86            become_: self.become_,
87        }
88    }
89
90    /// Transform only the next-behavior verdict, preserving sends and
91    /// creation order exactly.
92    #[must_use]
93    pub fn map_become<NextPh>(
94        self,
95        map: impl FnOnce(Become<Ph>) -> Become<NextPh>,
96    ) -> Actions<A, NextPh, Sends, Birth> {
97        Actions {
98            sends: self.sends,
99            creates: self.creates,
100            become_: map(self.become_),
101        }
102    }
103}
104
105impl<A: Address, Ph, Sends: SendAlgebra, Birth: BirthMode> Actions<A, Ph, Sends, Birth> {
106    #[must_use]
107    pub const fn new(
108        sends: Sends,
109        creates: Vec<Create<A, Birth::Child>>,
110        become_: Become<Ph>,
111    ) -> Self {
112        Self {
113            sends,
114            creates,
115            become_,
116        }
117    }
118
119    #[must_use]
120    pub fn just(become_: Become<Ph>) -> Self {
121        Self {
122            sends: Sends::empty(),
123            creates: Vec::new(),
124            become_,
125        }
126    }
127
128    #[must_use]
129    pub fn cont() -> Self {
130        Self::just(Step::Continue)
131    }
132    #[must_use]
133    pub fn stop() -> Self {
134        Self::just(Step::Stop(Stopped))
135    }
136    #[must_use]
137    pub fn goto(phase: Ph) -> Self {
138        Self::just(Step::Goto(phase))
139    }
140
141    /// Continue after emitting the complete declared send product.
142    #[must_use]
143    pub fn send(sends: Sends) -> Self {
144        Self::new(sends, Vec::new(), Step::Continue)
145    }
146
147    /// Continue after staging the complete declared creation product.
148    #[must_use]
149    pub fn create(creates: Vec<Create<A, Birth::Child>>) -> Self {
150        Self::new(Sends::empty(), creates, Step::Continue)
151    }
152}
153
154impl<A: Address, Ph, Sends, Birth: BirthMode>
155    From<(Sends, Vec<Create<A, Birth::Child>>, Become<Ph>)> for Actions<A, Ph, Sends, Birth>
156{
157    fn from((sends, creates, become_): (Sends, Vec<Create<A, Birth::Child>>, Become<Ph>)) -> Self {
158        Self {
159            sends,
160            creates,
161            become_,
162        }
163    }
164}
165
166pub type Acted<A, Ph, Sends, Birth, E> = Result<Actions<A, Ph, Sends, Birth>, E>;
167
168#[cfg(test)]
169mod tests {
170    use super::*;
171    use crate::{Births, CreationKind, MailAddr, NoBirths};
172
173    #[test]
174    fn equality_and_debug_cover_every_named_effect_leg() {
175        type Plain = Actions<MailAddr, u8, Vec<u8>, NoBirths>;
176
177        let value = Plain::new(vec![1], Vec::new(), Step::Goto(3));
178        assert_eq!(value, Plain::new(vec![1], Vec::new(), Step::Goto(3)));
179        assert_ne!(value, Plain::new(vec![2], Vec::new(), Step::Goto(3)));
180        assert_ne!(value, Plain::new(vec![1], Vec::new(), Step::Goto(4)));
181        assert_ne!(value, Plain::new(vec![1], Vec::new(), Step::Continue));
182        assert_eq!(
183            format!("{value:?}"),
184            "Actions { sends: [1], creates: [], become: Goto(3) }"
185        );
186
187        type Creating = Actions<MailAddr, Never, Vec<u8>, Births<u8>>;
188        let created = Creating::new(
189            Vec::new(),
190            vec![Create::new(7, 9, CreationKind::Birth)],
191            Step::Continue,
192        );
193        let other_creation = Creating::new(
194            Vec::new(),
195            vec![Create::new(8, 9, CreationKind::Birth)],
196            Step::Continue,
197        );
198        assert_ne!(created, other_creation);
199    }
200
201    #[test]
202    fn mapping_sends_preserves_creation_order_and_verdict() {
203        let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
204            vec![1, 2],
205            vec![
206                Create::new(3, (), CreationKind::Birth),
207                Create::new(4, (), CreationKind::replacement_of(3)),
208            ],
209            Step::Goto(7),
210        );
211
212        let mapped = actions.map_sends(|sends| sends.len());
213        assert_eq!(mapped.sends, 2);
214        assert_eq!(
215            mapped
216                .creates
217                .iter()
218                .map(|creation| creation.nonce)
219                .collect::<Vec<_>>(),
220            [3, 4]
221        );
222        assert!(matches!(mapped.become_, Step::Goto(7)));
223    }
224
225    #[test]
226    fn mapping_become_preserves_sends_and_creation_order() {
227        let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
228            vec![1, 2],
229            vec![Create::new(3, (), CreationKind::Birth)],
230            Step::Goto(7),
231        );
232
233        let mapped: Actions<MailAddr, Never, Vec<u8>, Births<()>> =
234            actions.map_become(|_| Step::Stop(Stopped));
235        assert_eq!(mapped.sends, [1, 2]);
236        assert_eq!(mapped.creates[0].nonce, 3);
237        assert!(matches!(mapped.become_, Step::Stop(Stopped)));
238    }
239}