1use super::sending::{SendEffects, SendInput};
4use crate::actor::{Address, BirthMode, Create};
5use crate::next::{Never, Step, Stopped};
6
7pub type Become<Ph = Never> = Step<Ph, Stopped>;
8
9pub trait AppendSend<Input, Path>: Sized {
12 #[must_use]
14 fn append_send(self, input: Input) -> Self;
15}
16
17pub struct Actions<A: Address, Ph, Sends, Birth: BirthMode> {
34 pub sends: Sends,
35 pub creates: Vec<Create<A, Birth::Child>>,
36 pub become_: Become<Ph>,
37}
38
39impl<A, Ph, Sends, Birth> core::fmt::Debug for Actions<A, Ph, Sends, Birth>
40where
41 A: Address + core::fmt::Debug,
42 A::Nonce: core::fmt::Debug,
43 Ph: core::fmt::Debug,
44 Sends: core::fmt::Debug,
45 Birth: BirthMode,
46 Birth::Child: core::fmt::Debug,
47{
48 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49 formatter
50 .debug_struct("Actions")
51 .field("sends", &self.sends)
52 .field("creates", &self.creates)
53 .field("become", &self.become_)
54 .finish()
55 }
56}
57
58impl<A, Ph, Sends, Birth> PartialEq for Actions<A, Ph, Sends, Birth>
59where
60 A: Address + PartialEq,
61 A::Nonce: PartialEq,
62 Ph: PartialEq,
63 Sends: PartialEq,
64 Birth: BirthMode,
65 Birth::Child: PartialEq,
66{
67 fn eq(&self, other: &Self) -> bool {
68 self.sends == other.sends && self.creates == other.creates && self.become_ == other.become_
69 }
70}
71
72impl<A, Ph, Sends, Birth> Eq for Actions<A, Ph, Sends, Birth>
73where
74 A: Address + Eq,
75 A::Nonce: Eq,
76 Ph: Eq,
77 Sends: Eq,
78 Birth: BirthMode,
79 Birth::Child: Eq,
80{
81}
82
83impl<A: Address, Ph, Sends, Birth: BirthMode> Actions<A, Ph, Sends, Birth> {
84 #[must_use]
87 pub fn map_sends<Mapped>(
88 self,
89 map: impl FnOnce(Sends) -> Mapped,
90 ) -> Actions<A, Ph, Mapped, Birth> {
91 Actions {
92 sends: map(self.sends),
93 creates: self.creates,
94 become_: self.become_,
95 }
96 }
97
98 #[must_use]
101 pub fn map_become<NextPh>(
102 self,
103 map: impl FnOnce(Become<Ph>) -> Become<NextPh>,
104 ) -> Actions<A, NextPh, Sends, Birth> {
105 Actions {
106 sends: self.sends,
107 creates: self.creates,
108 become_: map(self.become_),
109 }
110 }
111
112 #[must_use]
118 pub fn with_send<Input, Path>(mut self, input: Input) -> Self
119 where
120 Sends: SendInput<Input, Path>,
121 {
122 <Sends as SendInput<Input, Path>>::emit(&mut self.sends, input);
123 self
124 }
125}
126
127impl<A, Ph, Sends, Birth, Input, Path> AppendSend<Input, Path> for Actions<A, Ph, Sends, Birth>
128where
129 A: Address,
130 Birth: BirthMode,
131 Sends: SendInput<Input, Path>,
132{
133 fn append_send(self, input: Input) -> Self {
134 self.with_send::<Input, Path>(input)
135 }
136}
137
138impl<A: Address, Ph, Sends: SendEffects, Birth: BirthMode> Actions<A, Ph, Sends, Birth> {
139 #[must_use]
140 pub const fn new(
141 sends: Sends,
142 creates: Vec<Create<A, Birth::Child>>,
143 become_: Become<Ph>,
144 ) -> Self {
145 Self {
146 sends,
147 creates,
148 become_,
149 }
150 }
151
152 #[must_use]
153 pub fn just(become_: Become<Ph>) -> Self {
154 Self {
155 sends: Sends::empty(),
156 creates: Vec::new(),
157 become_,
158 }
159 }
160
161 #[must_use]
162 pub fn cont() -> Self {
163 Self::just(Step::Continue)
164 }
165 #[must_use]
166 pub fn stop() -> Self {
167 Self::just(Step::Stop(Stopped))
168 }
169 #[must_use]
170 pub fn goto(phase: Ph) -> Self {
171 Self::just(Step::Goto(phase))
172 }
173
174 #[must_use]
176 pub fn send(sends: Sends) -> Self {
177 Self::new(sends, Vec::new(), Step::Continue)
178 }
179
180 #[must_use]
182 pub fn create(creates: Vec<Create<A, Birth::Child>>) -> Self {
183 Self::new(Sends::empty(), creates, Step::Continue)
184 }
185}
186
187impl<A: Address, Ph, Sends, Birth: BirthMode>
188 From<(Sends, Vec<Create<A, Birth::Child>>, Become<Ph>)> for Actions<A, Ph, Sends, Birth>
189{
190 fn from((sends, creates, become_): (Sends, Vec<Create<A, Birth::Child>>, Become<Ph>)) -> Self {
191 Self {
192 sends,
193 creates,
194 become_,
195 }
196 }
197}
198
199pub type Acted<A, Ph, Sends, Birth, E> = Result<Actions<A, Ph, Sends, Birth>, E>;
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use crate::{Births, CreationKind, MailAddr, NoBirths, Own};
205
206 #[test]
207 fn equality_and_debug_cover_every_named_effect_leg() {
208 type Plain = Actions<MailAddr, u8, Vec<u8>, NoBirths>;
209 type Creating = Actions<MailAddr, Never, Vec<u8>, Births<u8>>;
210
211 let value = Plain::new(vec![1], Vec::new(), Step::Goto(3));
212 assert_eq!(value, Plain::new(vec![1], Vec::new(), Step::Goto(3)));
213 assert_ne!(value, Plain::new(vec![2], Vec::new(), Step::Goto(3)));
214 assert_ne!(value, Plain::new(vec![1], Vec::new(), Step::Goto(4)));
215 assert_ne!(value, Plain::new(vec![1], Vec::new(), Step::Continue));
216 assert_eq!(
217 format!("{value:?}"),
218 "Actions { sends: [1], creates: [], become: Goto(3) }"
219 );
220
221 let created = Creating::new(
222 Vec::new(),
223 vec![Create::new(7, 9, CreationKind::Birth)],
224 Step::Continue,
225 );
226 let other_creation = Creating::new(
227 Vec::new(),
228 vec![Create::new(8, 9, CreationKind::Birth)],
229 Step::Continue,
230 );
231 assert_ne!(created, other_creation);
232 }
233
234 #[test]
235 fn mapping_sends_preserves_creation_order_and_verdict() {
236 let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
237 vec![1, 2],
238 vec![
239 Create::new(3, (), CreationKind::Birth),
240 Create::new(4, (), CreationKind::replacement_of(3)),
241 ],
242 Step::Goto(7),
243 );
244
245 let mapped = actions.map_sends(|sends| sends.len());
246 assert_eq!(mapped.sends, 2);
247 assert_eq!(
248 mapped
249 .creates
250 .iter()
251 .map(|creation| creation.nonce)
252 .collect::<Vec<_>>(),
253 [3, 4]
254 );
255 assert!(matches!(mapped.become_, Step::Goto(7)));
256 }
257
258 #[test]
259 fn mapping_become_preserves_sends_and_creation_order() {
260 let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
261 vec![1, 2],
262 vec![Create::new(3, (), CreationKind::Birth)],
263 Step::Goto(7),
264 );
265
266 let mapped: Actions<MailAddr, Never, Vec<u8>, Births<()>> =
267 actions.map_become(|_| Step::Stop(Stopped));
268 assert_eq!(mapped.sends, [1, 2]);
269 assert_eq!(mapped.creates[0].nonce, 3);
270 assert!(matches!(mapped.become_, Step::Stop(Stopped)));
271 }
272
273 #[test]
274 fn fluent_send_changes_only_the_selected_effect_leg() {
275 let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
276 vec![1],
277 vec![
278 Create::new(3, (), CreationKind::Birth),
279 Create::new(4, (), CreationKind::replacement_of(3)),
280 ],
281 Step::Goto(7),
282 )
283 .with_send::<_, Own>(2)
284 .with_send::<_, Own>(3);
285
286 assert_eq!(actions.sends, [1, 2, 3]);
287 assert_eq!(
288 actions
289 .creates
290 .iter()
291 .map(|creation| creation.nonce)
292 .collect::<Vec<_>>(),
293 [3, 4]
294 );
295 assert!(matches!(actions.become_, Step::Goto(7)));
296
297 let stopped: Actions<MailAddr, Never, Vec<u8>, NoBirths> =
298 Actions::stop().with_send::<_, Own>(5);
299 assert_eq!(stopped.sends, [5]);
300 assert!(matches!(stopped.become_, Step::Stop(Stopped)));
301 }
302}