1use core::future::{self, Future};
4use core::pin::pin;
5use core::task::Poll;
6
7use super::sending::{
8 ClassifySettlement, InterpretItem, InterpretSends, Interpretation, InterpretationProgress,
9 InterpreterFault, ItemSettlement, SendEffects, SendInput, SendSettlements, SettledItem,
10 SettlementStatus, SourceAdmission, SourceCustody, SourceProgress, SourceSettlementCustody,
11 offer_source_in_order,
12};
13use crate::actor::{
14 Address, BirthMode, Births, ChildCreationProduct, ChildHead, ChildNamespaceExhausted,
15 CreateChild, CreationRejection, Creations, DispatchBirth, NoBirths, RetirementBirths,
16 RoutedCreation,
17};
18use crate::next::{Never, Step, Stopped};
19use crate::transition::{Behavior, BehaviorAddr};
20use crate::user_event::{EventIngress, User, UserEvent};
21
22pub type Become<Ph = Never> = Step<Ph, Stopped>;
23
24#[derive(Clone, Debug, Eq, PartialEq)]
31pub struct ActionSettlement<Creations, Sends, Ph> {
32 pub creations: Creations,
33 pub sends: Sends,
34 pub become_: Become<Ph>,
35}
36
37#[derive(Clone, Debug, Eq, PartialEq)]
39pub enum CreationSettlement<Requests, Settlements> {
40 Settled(Settlements),
42 Rejected {
44 creations: Requests,
45 reason: ChildNamespaceExhausted,
46 },
47 Corrupt {
49 creations: Requests,
50 fault: InterpreterFault,
51 },
52}
53
54#[must_use = "a retirement creation settlement must remain in terminal custody"]
60#[derive(Clone, Debug, Eq, PartialEq)]
61pub struct RetirementCreationSettlement<Settlement> {
62 settlement: Settlement,
63}
64
65impl<Settlement> RetirementCreationSettlement<Settlement> {
66 #[must_use]
67 pub const fn new(settlement: Settlement) -> Self {
68 Self { settlement }
69 }
70
71 #[must_use]
72 pub fn into_settlement(self) -> Settlement {
73 self.settlement
74 }
75}
76
77pub trait ActionSettlements: Sized {
83 type Settlements;
84 type SourceCustody;
85 type InterpretationCustody;
86 fn prepare_interpretation(
87 progress: &mut Option<
88 InterpretationProgress<Self, Self::InterpretationCustody, Self::Settlements>,
89 >,
90 );
91 fn finish_interpretation(
92 progress: &mut Option<
93 InterpretationProgress<Self, Self::InterpretationCustody, Self::Settlements>,
94 >,
95 );
96}
97
98impl<A, Ph, Sends, Birth> ActionSettlements for Actions<A, Ph, Sends, Birth>
99where
100 A: Address,
101 Sends: SendSettlements,
102 Birth: CreationSettlements<A>,
103{
104 type Settlements = ActionSettlement<Birth::Settlements, Sends::Settlements, Ph>;
105 type SourceCustody = (
106 (
107 Option<SourceProgress<Birth::Settlements, Birth::SourceCustody>>,
108 Option<SourceProgress<Sends::Settlements, Sends::SourceCustody>>,
109 ),
110 Become<Ph>,
111 );
112 type InterpretationCustody = (
113 (
114 Option<
115 InterpretationProgress<
116 Creations<CreateChild<A, Birth::Child>>,
117 Birth::InterpretationCustody,
118 Birth::Settlements,
119 >,
120 >,
121 Option<InterpretationProgress<Sends, Sends::InterpretationCustody, Sends::Settlements>>,
122 ),
123 Become<Ph>,
124 );
125
126 fn prepare_interpretation(
127 progress: &mut Option<
128 InterpretationProgress<Self, Self::InterpretationCustody, Self::Settlements>,
129 >,
130 ) {
131 if matches!(progress, Some(InterpretationProgress::Original(_))) {
132 match progress.take() {
133 Some(InterpretationProgress::Original(Actions {
134 creates,
135 sends,
136 become_,
137 })) => {
138 *progress = Some(InterpretationProgress::Interpreting((
139 (
140 Some(InterpretationProgress::Original(creates)),
141 Some(InterpretationProgress::Original(sends)),
142 ),
143 become_,
144 )));
145 }
146 retained => *progress = retained,
147 }
148 }
149 }
150
151 fn finish_interpretation(
152 progress: &mut Option<
153 InterpretationProgress<Self, Self::InterpretationCustody, Self::Settlements>,
154 >,
155 ) {
156 if !matches!(
157 progress,
158 Some(InterpretationProgress::Interpreting((
159 (
160 Some(InterpretationProgress::Completed(_)),
161 Some(InterpretationProgress::Completed(_))
162 ),
163 _
164 )))
165 ) {
166 return;
167 }
168 match progress.take() {
171 Some(InterpretationProgress::Interpreting((
172 (
173 Some(InterpretationProgress::Completed(creations)),
174 Some(InterpretationProgress::Completed(sends)),
175 ),
176 become_,
177 ))) => {
178 let completed = match (creations, sends) {
179 (Interpretation::Complete(creations), Interpretation::Complete(sends)) => {
180 Interpretation::Complete(ActionSettlement {
181 creations,
182 sends,
183 become_,
184 })
185 }
186 (
187 Interpretation::Complete(creations) | Interpretation::Corrupt(creations),
188 Interpretation::Corrupt(sends),
189 )
190 | (Interpretation::Corrupt(creations), Interpretation::Complete(sends)) => {
191 Interpretation::Corrupt(ActionSettlement {
192 creations,
193 sends,
194 become_,
195 })
196 }
197 };
198 *progress = Some(InterpretationProgress::Completed(completed));
199 }
200 retained => *progress = retained,
201 }
202 }
203}
204
205pub trait BehaviorSettlements: Behavior {
212 type Settlements;
213 type SourceCustody;
214 type InterpretationCustody;
215}
216
217impl<B> BehaviorSettlements for B
218where
219 B: Behavior,
220 B::Sends: SendSettlements,
221 B::Birth: CreationSettlements<BehaviorAddr<B>>,
222{
223 type Settlements =
224 <Actions<BehaviorAddr<B>, B::Ph, B::Sends, B::Birth> as ActionSettlements>::Settlements;
225 type SourceCustody =
226 <Actions<BehaviorAddr<B>, B::Ph, B::Sends, B::Birth> as ActionSettlements>::SourceCustody;
227 type InterpretationCustody = <Actions<BehaviorAddr<B>, B::Ph, B::Sends, B::Birth> as ActionSettlements>::InterpretationCustody;
228}
229
230impl<Requests, Settlements> ClassifySettlement for CreationSettlement<Requests, Settlements>
231where
232 Settlements: ClassifySettlement,
233{
234 fn settlement_status(&self) -> SettlementStatus {
235 match self {
236 Self::Settled(settlements) => settlements.settlement_status(),
237 Self::Rejected { .. } => SettlementStatus::Rejected,
238 Self::Corrupt { .. } => SettlementStatus::Corrupt,
239 }
240 }
241}
242
243impl<Settlement> ClassifySettlement for RetirementCreationSettlement<Settlement>
244where
245 Settlement: ClassifySettlement,
246{
247 fn settlement_status(&self) -> SettlementStatus {
248 self.settlement.settlement_status()
249 }
250}
251
252impl<Item> ClassifySettlement for Creations<Item>
253where
254 Item: ClassifySettlement,
255{
256 fn settlement_status(&self) -> SettlementStatus {
257 let mut status = SettlementStatus::Accepted;
258 for item in self.iter() {
259 status = status.combine(item.settlement_status());
260 }
261 status
262 }
263}
264
265pub trait CreationSettlements<A: Address>: BirthMode {
267 type Settlements: ClassifySettlement;
268 type SourceCustody;
269 type InterpretationCustody;
270 fn prepare_interpretation(
271 progress: &mut Option<
272 InterpretationProgress<
273 Creations<CreateChild<A, Self::Child>>,
274 Self::InterpretationCustody,
275 Self::Settlements,
276 >,
277 >,
278 );
279 fn finish_interpretation(
280 progress: &mut Option<
281 InterpretationProgress<
282 Creations<CreateChild<A, Self::Child>>,
283 Self::InterpretationCustody,
284 Self::Settlements,
285 >,
286 >,
287 );
288}
289
290impl<A: Address> CreationSettlements<A> for NoBirths {
291 type Settlements = Creations<Never>;
292 type SourceCustody = Self::Settlements;
293 type InterpretationCustody = ();
294 fn prepare_interpretation(
295 progress: &mut Option<
296 InterpretationProgress<
297 Creations<CreateChild<A, Never>>,
298 Self::InterpretationCustody,
299 Self::Settlements,
300 >,
301 >,
302 ) {
303 match progress.take() {
304 Some(InterpretationProgress::Original(original)) => {
305 let settlements = original
306 .into_iter()
307 .map(|creation| {
308 let (_, never, _) = creation.into_parts();
309 match never {}
310 })
311 .collect();
312 *progress = Some(InterpretationProgress::Completed(Interpretation::Complete(
313 Creations::from_items(settlements),
314 )));
315 }
316 retained => *progress = retained,
317 }
318 }
319 fn finish_interpretation(
320 progress: &mut Option<
321 InterpretationProgress<
322 Creations<CreateChild<A, Never>>,
323 Self::InterpretationCustody,
324 Self::Settlements,
325 >,
326 >,
327 ) {
328 Self::prepare_interpretation(progress);
329 }
330}
331
332impl<A, C> CreationSettlements<A> for Births<C>
333where
334 A: Address,
335 C: ChildCreationProduct<A, ChildHead>,
336{
337 type Settlements = CreationSettlement<
338 Creations<CreateChild<A, C>>,
339 Creations<
340 SettledItem<
341 RoutedCreation<A, C>,
342 ItemSettlement<
343 RoutedCreation<A, C>,
344 <C as ChildCreationProduct<A, ChildHead>>::Result,
345 CreationRejection,
346 Never,
347 >,
348 >,
349 >,
350 >;
351 type SourceCustody = (
352 Option<CreationsSettled<A, C>>,
353 Option<Result<(), CreationsSettled<A, C>>>,
354 );
355 type InterpretationCustody = CreationInterpretationCustody<A, C>;
356 fn prepare_interpretation(
357 progress: &mut Option<
358 InterpretationProgress<
359 Creations<CreateChild<A, C>>,
360 Self::InterpretationCustody,
361 Self::Settlements,
362 >,
363 >,
364 ) {
365 prepare_creations(progress);
366 }
367 fn finish_interpretation(
368 progress: &mut Option<
369 InterpretationProgress<
370 Creations<CreateChild<A, C>>,
371 Self::InterpretationCustody,
372 Self::Settlements,
373 >,
374 >,
375 ) {
376 finish_creations(progress);
377 }
378}
379
380impl<A, C> CreationSettlements<A> for RetirementBirths<C>
381where
382 A: Address,
383 C: ChildCreationProduct<A, ChildHead>,
384{
385 type Settlements =
386 RetirementCreationSettlement<<Births<C> as CreationSettlements<A>>::Settlements>;
387 type SourceCustody = Self::Settlements;
388 type InterpretationCustody = Option<
389 InterpretationProgress<
390 Creations<CreateChild<A, C>>,
391 <Births<C> as CreationSettlements<A>>::InterpretationCustody,
392 <Births<C> as CreationSettlements<A>>::Settlements,
393 >,
394 >;
395 fn prepare_interpretation(
396 progress: &mut Option<
397 InterpretationProgress<
398 Creations<CreateChild<A, C>>,
399 Self::InterpretationCustody,
400 Self::Settlements,
401 >,
402 >,
403 ) {
404 match progress.take() {
405 Some(InterpretationProgress::Original(original)) => {
406 *progress = Some(InterpretationProgress::Interpreting(Some(
407 InterpretationProgress::Original(original),
408 )))
409 }
410 retained => *progress = retained,
411 }
412 }
413 fn finish_interpretation(
414 progress: &mut Option<
415 InterpretationProgress<
416 Creations<CreateChild<A, C>>,
417 Self::InterpretationCustody,
418 Self::Settlements,
419 >,
420 >,
421 ) {
422 match progress.take() {
425 Some(InterpretationProgress::Interpreting(Some(
426 InterpretationProgress::Completed(received),
427 ))) => {
428 *progress = Some(InterpretationProgress::Completed(
429 received.map(RetirementCreationSettlement::new),
430 ));
431 }
432 retained => *progress = retained,
433 }
434 }
435}
436
437#[must_use = "a returned creation batch must be admitted or retained"]
443pub struct CreationsSettled<A, C>
444where
445 A: Address,
446 C: ChildCreationProduct<A, ChildHead>,
447{
448 settlement: <Births<C> as CreationSettlements<A>>::Settlements,
449}
450
451pub enum CreationEvent<A, C, M>
458where
459 A: Address,
460 C: ChildCreationProduct<A, ChildHead>,
461{
462 Settlements(CreationsSettled<A, C>),
463 User(User<A, M>),
464}
465
466impl<A, C, M> EventIngress<Births<C>, CreationsSettled<A, C>> for CreationEvent<A, C, M>
467where
468 A: Address,
469 C: ChildCreationProduct<A, ChildHead>,
470{
471 fn ingress(input: CreationsSettled<A, C>) -> Self {
472 Self::Settlements(input)
473 }
474}
475
476impl<A, C, M> UserEvent for CreationEvent<A, C, M>
477where
478 A: Address,
479 C: ChildCreationProduct<A, ChildHead>,
480{
481 type Addr = A;
482 type Message = M;
483
484 fn user(from: A, message: M) -> Self {
485 Self::User(User::new(from, message))
486 }
487
488 fn into_user(self) -> Result<User<A, M>, Self> {
489 match self {
490 Self::User(event) => Ok(event),
491 settlements @ Self::Settlements(_) => Err(settlements),
492 }
493 }
494}
495
496impl<A, C> CreationsSettled<A, C>
497where
498 A: Address,
499 C: ChildCreationProduct<A, ChildHead>,
500{
501 #[must_use]
502 pub const fn new(settlement: <Births<C> as CreationSettlements<A>>::Settlements) -> Self {
503 Self { settlement }
504 }
505
506 #[must_use]
507 pub fn into_settlement(self) -> <Births<C> as CreationSettlements<A>>::Settlements {
508 self.settlement
509 }
510}
511
512impl<Host, RootEvent> SourceSettlementCustody<Host, RootEvent> for Creations<Never> {
513 type Custody = Self;
514 fn prepare_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
515 *progress = match progress.take() {
516 Some(SourceProgress::Original(original)) => Some(SourceProgress::Completed(
517 SourceCustody::Exhausted(original),
518 )),
519 progress => progress,
520 };
521 }
522 fn offer_next_to_source(
523 _: &mut Self::Custody,
524 _: &mut Host,
525 ) -> impl Future<Output = ()> + Send {
526 future::ready(())
527 }
528 fn finish_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
529 *progress = match progress.take() {
530 Some(SourceProgress::Original(original) | SourceProgress::Offering(original)) => Some(
531 SourceProgress::Completed(SourceCustody::Exhausted(original)),
532 ),
533 retained => retained,
534 };
535 }
536}
537
538impl<A, C, Host, RootEvent> SourceSettlementCustody<Host, RootEvent>
539 for CreationSettlement<
540 Creations<CreateChild<A, C>>,
541 Creations<
542 SettledItem<
543 RoutedCreation<A, C>,
544 ItemSettlement<
545 RoutedCreation<A, C>,
546 <C as ChildCreationProduct<A, ChildHead>>::Result,
547 CreationRejection,
548 Never,
549 >,
550 >,
551 >,
552 >
553where
554 A: Address,
555 A::Nonce: Send,
556 C: ChildCreationProduct<A, ChildHead> + Send,
557 <C as ChildCreationProduct<A, ChildHead>>::Result: Send,
558 Host: SourceAdmission<RootEvent, Births<C>, CreationsSettled<A, C>>,
559 RootEvent: crate::EventIngress<Births<C>, CreationsSettled<A, C>>,
560{
561 type Custody = (
562 Option<CreationsSettled<A, C>>,
563 Option<Result<(), CreationsSettled<A, C>>>,
564 );
565 fn prepare_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
566 *progress = match progress.take() {
567 Some(SourceProgress::Original(original)) if matches!(&original, CreationSettlement::Settled(settlements) if settlements.is_empty()) => {
568 Some(SourceProgress::Completed(SourceCustody::Exhausted(
569 original,
570 )))
571 }
572 Some(SourceProgress::Original(original)) => Some(SourceProgress::Offering((
573 Some(CreationsSettled::new(original)),
574 None,
575 ))),
576 progress => progress,
577 };
578 }
579 fn offer_next_to_source(
580 custody: &mut Self::Custody,
581 host: &mut Host,
582 ) -> impl Future<Output = ()> + Send {
583 async move {
584 if custody.1.is_none() {
585 host.admit_source(&mut custody.0, &mut custody.1).await;
586 }
587 }
588 }
589 fn finish_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
590 *progress = match progress.take() {
591 Some(SourceProgress::Offering((None, Some(Ok(()))))) => {
592 Some(SourceProgress::Completed(SourceCustody::Admitted(
593 CreationSettlement::Settled(Creations::empty()),
594 )))
595 }
596 Some(SourceProgress::Offering((None, Some(Err(returned))))) => Some(
597 SourceProgress::Completed(SourceCustody::Closed(returned.into_settlement())),
598 ),
599 progress => progress,
600 };
601 }
602}
603
604impl<A, C, Host, RootEvent> SourceSettlementCustody<Host, RootEvent>
605 for RetirementCreationSettlement<
606 CreationSettlement<
607 Creations<CreateChild<A, C>>,
608 Creations<
609 SettledItem<
610 RoutedCreation<A, C>,
611 ItemSettlement<
612 RoutedCreation<A, C>,
613 <C as ChildCreationProduct<A, ChildHead>>::Result,
614 CreationRejection,
615 Never,
616 >,
617 >,
618 >,
619 >,
620 >
621where
622 A: Address,
623 A::Nonce: Send,
624 C: ChildCreationProduct<A, ChildHead> + Send,
625 <C as ChildCreationProduct<A, ChildHead>>::Result: Send,
626{
627 type Custody = Self;
628 fn prepare_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
629 *progress = match progress.take() {
630 Some(SourceProgress::Original(original)) if matches!(&original.settlement, CreationSettlement::Settled(settlements) if settlements.is_empty()) => {
631 Some(SourceProgress::Completed(SourceCustody::Exhausted(
632 original,
633 )))
634 }
635 Some(SourceProgress::Original(original)) => {
636 Some(SourceProgress::Completed(SourceCustody::Retained(original)))
637 }
638 progress => progress,
639 };
640 }
641 fn offer_next_to_source(
642 _: &mut Self::Custody,
643 _: &mut Host,
644 ) -> impl Future<Output = ()> + Send {
645 future::ready(())
646 }
647 fn finish_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
648 *progress = match progress.take() {
649 Some(SourceProgress::Original(original) | SourceProgress::Offering(original)) if matches!(&original.settlement, CreationSettlement::Settled(settlements) if settlements.is_empty()) => {
650 Some(SourceProgress::Completed(SourceCustody::Exhausted(
651 original,
652 )))
653 }
654 Some(SourceProgress::Original(original) | SourceProgress::Offering(original)) => {
655 Some(SourceProgress::Completed(SourceCustody::Retained(original)))
656 }
657 retained => retained,
658 };
659 }
660}
661
662pub enum CreationInterpretationCustody<A, C>
665where
666 A: Address,
667 C: ChildCreationProduct<A, ChildHead>,
668{
669 Routing {
670 input: Option<Creations<CreateChild<A, C>>>,
671 received: Option<
672 ItemSettlement<
673 Creations<CreateChild<A, C>>,
674 Creations<RoutedCreation<A, C>>,
675 ChildNamespaceExhausted,
676 Never,
677 >,
678 >,
679 },
680 Children(
681 Vec<(
682 Option<RoutedCreation<A, C>>,
683 Option<
684 ItemSettlement<
685 RoutedCreation<A, C>,
686 <C as ChildCreationProduct<A, ChildHead>>::Result,
687 CreationRejection,
688 Never,
689 >,
690 >,
691 )>,
692 ),
693}
694
695fn prepare_creations<A, C>(
696 progress: &mut Option<
697 InterpretationProgress<
698 Creations<CreateChild<A, C>>,
699 CreationInterpretationCustody<A, C>,
700 CreationSettlement<
701 Creations<CreateChild<A, C>>,
702 Creations<
703 SettledItem<
704 RoutedCreation<A, C>,
705 ItemSettlement<
706 RoutedCreation<A, C>,
707 <C as ChildCreationProduct<A, ChildHead>>::Result,
708 CreationRejection,
709 Never,
710 >,
711 >,
712 >,
713 >,
714 >,
715 >,
716) where
717 A: Address,
718 C: ChildCreationProduct<A, ChildHead>,
719{
720 if matches!(progress, Some(InterpretationProgress::Original(_))) {
721 match progress.take() {
722 Some(InterpretationProgress::Original(input)) => {
723 *progress = Some(InterpretationProgress::Interpreting(
724 CreationInterpretationCustody::Routing {
725 input: Some(input),
726 received: None,
727 },
728 ));
729 }
730 retained => *progress = retained,
731 }
732 }
733}
734
735fn finish_routing<A, C>(
736 progress: &mut Option<
737 InterpretationProgress<
738 Creations<CreateChild<A, C>>,
739 CreationInterpretationCustody<A, C>,
740 <Births<C> as CreationSettlements<A>>::Settlements,
741 >,
742 >,
743) where
744 A: Address,
745 C: ChildCreationProduct<A, ChildHead>,
746{
747 if !matches!(
748 progress,
749 Some(InterpretationProgress::Interpreting(
750 CreationInterpretationCustody::Routing {
751 input: None,
752 received: Some(_)
753 }
754 ))
755 ) {
756 return;
757 }
758 match progress.take() {
759 Some(InterpretationProgress::Interpreting(CreationInterpretationCustody::Routing {
760 input: None,
761 received: Some(received),
762 })) => {
763 *progress = Some(match received {
764 ItemSettlement::Accepted(routed) => {
765 InterpretationProgress::Interpreting(CreationInterpretationCustody::Children(
766 routed
767 .into_iter()
768 .map(|input| (Some(input), None))
769 .collect(),
770 ))
771 }
772 ItemSettlement::Rejected { item, reason } => InterpretationProgress::Completed(
773 Interpretation::Complete(CreationSettlement::Rejected {
774 creations: item,
775 reason,
776 }),
777 ),
778 ItemSettlement::Corrupt { item, fault } => InterpretationProgress::Completed(
779 Interpretation::Corrupt(CreationSettlement::Corrupt {
780 creations: item,
781 fault,
782 }),
783 ),
784 ItemSettlement::Blocked { prerequisite, .. } => match prerequisite {},
785 });
786 }
787 retained => *progress = retained,
788 }
789}
790
791async fn settle_child<A, C, Interpreter>(
792 input: &mut Option<RoutedCreation<A, C>>,
793 received: &mut Option<
794 ItemSettlement<
795 RoutedCreation<A, C>,
796 <C as ChildCreationProduct<A, ChildHead>>::Result,
797 CreationRejection,
798 Never,
799 >,
800 >,
801 interpreter: &mut Interpreter,
802) where
803 A: Address,
804 C: ChildCreationProduct<A, ChildHead> + DispatchBirth<A, Interpreter>,
805{
806 if received.is_some() {
807 return;
808 }
809 let Some(original) = input.take() else {
810 return;
811 };
812 let (creation, route) = original.into_parts();
813 let (id, child, kind) = creation.into_parts();
814 let mut attempt = pin!(child.dispatch_birth(id, route, kind, interpreter));
815 future::poll_fn(|context| match attempt.as_mut().poll(context) {
816 Poll::Pending => Poll::Pending,
817 Poll::Ready(reply) => {
818 *received = Some(reply);
819 Poll::Ready(())
820 }
821 })
822 .await;
823}
824
825async fn interpret_creations<A, C, Interpreter, RootEvent, Path>(
826 progress: &mut Option<
827 InterpretationProgress<
828 Creations<CreateChild<A, C>>,
829 CreationInterpretationCustody<A, C>,
830 <Births<C> as CreationSettlements<A>>::Settlements,
831 >,
832 >,
833 interpreter: &mut Interpreter,
834) where
835 A: Address,
836 A::Nonce: Send,
837 C: ChildCreationProduct<A, ChildHead> + DispatchBirth<A, Interpreter> + Send,
838 <C as ChildCreationProduct<A, ChildHead>>::Result: Send,
839 Interpreter: InterpretItem<Creations<CreateChild<A, C>>, RootEvent, Path> + Send,
840{
841 prepare_creations(progress);
842 if let Some(InterpretationProgress::Interpreting(CreationInterpretationCustody::Routing {
843 input,
844 received,
845 })) = progress
846 {
847 <Interpreter as InterpretItem<Creations<CreateChild<A,C>>, RootEvent, Path>>::interpret_item(
848 interpreter, input, received,
849 ).await;
850 }
851 finish_routing(progress);
852 let Some(InterpretationProgress::Interpreting(CreationInterpretationCustody::Children(rows))) =
853 progress
854 else {
855 return;
856 };
857 for (input, received) in rows {
858 match (input.as_ref(), received.as_ref()) {
859 (None, Some(ItemSettlement::Corrupt { .. })) => break,
860 (None, Some(_)) => continue,
861 (Some(_), None) => {}
862 _ => return,
863 }
864 settle_child(input, received, interpreter).await;
865 match (input.as_ref(), received.as_ref()) {
866 (None, Some(ItemSettlement::Corrupt { .. })) => break,
867 (None, Some(_)) => {}
868 _ => return,
869 }
870 }
871 finish_creations(progress);
872}
873
874fn finish_creations<A, C>(
875 progress: &mut Option<
876 InterpretationProgress<
877 Creations<CreateChild<A, C>>,
878 CreationInterpretationCustody<A, C>,
879 <Births<C> as CreationSettlements<A>>::Settlements,
880 >,
881 >,
882) where
883 A: Address,
884 C: ChildCreationProduct<A, ChildHead>,
885{
886 finish_routing(progress);
887 let Some(InterpretationProgress::Interpreting(CreationInterpretationCustody::Children(rows))) =
888 progress.as_ref()
889 else {
890 return;
891 };
892 let corrupt = rows
893 .iter()
894 .position(|(_, received)| matches!(received, Some(ItemSettlement::Corrupt { .. })));
895 let complete = rows.iter().enumerate().all(|(index, (input, received))| {
896 if corrupt.is_some_and(|corrupt| index > corrupt) {
897 input.is_some() && received.is_none()
898 } else {
899 input.is_none() && received.is_some()
900 }
901 });
902 if !complete {
903 return;
904 }
905 let Some(InterpretationProgress::Interpreting(CreationInterpretationCustody::Children(rows))) =
906 progress.take()
907 else {
908 return;
909 };
910 let mut remaining = rows.into_iter();
911 let mut settled = Vec::with_capacity(remaining.len());
912 while let Some((input, received)) = remaining.next() {
913 match (input, received) {
914 (None, Some(received)) => settled.push(SettledItem::Attempted(received)),
915 (Some(input), None) => settled.push(SettledItem::Unattempted(input)),
916 (input, received) => {
917 let rows = settled
918 .into_iter()
919 .map(|settled| match settled {
920 SettledItem::Attempted(received) => (None, Some(received)),
921 SettledItem::Unattempted(input) => (Some(input), None),
922 })
923 .chain(core::iter::once((input, received)))
924 .chain(remaining)
925 .collect();
926 *progress = Some(InterpretationProgress::Interpreting(
927 CreationInterpretationCustody::Children(rows),
928 ));
929 return;
930 }
931 }
932 }
933 let settlement = CreationSettlement::Settled(Creations::from_items(settled));
934 *progress = Some(InterpretationProgress::Completed(match corrupt {
935 Some(_) => Interpretation::Corrupt(settlement),
936 None => Interpretation::Complete(settlement),
937 }));
938}
939
940pub trait InterpretCreations<A, Interpreter, RootEvent, Path>: CreationSettlements<A>
945where
946 A: Address,
947{
948 fn interpret_creations(
949 progress: &mut Option<
950 InterpretationProgress<
951 Creations<CreateChild<A, Self::Child>>,
952 Self::InterpretationCustody,
953 Self::Settlements,
954 >,
955 >,
956 interpreter: &mut Interpreter,
957 ) -> impl Future<Output = ()> + Send;
958}
959
960impl<A, Interpreter, RootEvent, Path> InterpretCreations<A, Interpreter, RootEvent, Path>
961 for NoBirths
962where
963 A: Address,
964 Creations<CreateChild<A, Never>>: Send,
965{
966 fn interpret_creations(
967 progress: &mut Option<
968 InterpretationProgress<
969 Creations<CreateChild<A, Never>>,
970 Self::InterpretationCustody,
971 Self::Settlements,
972 >,
973 >,
974 _: &mut Interpreter,
975 ) -> impl Future<Output = ()> + Send {
976 async move {
977 <Self as CreationSettlements<A>>::prepare_interpretation(progress);
978 }
979 }
980}
981
982impl<A, C, Interpreter, RootEvent, Path> InterpretCreations<A, Interpreter, RootEvent, Path>
983 for Births<C>
984where
985 A: Address,
986 A::Nonce: Send,
987 C: ChildCreationProduct<A, ChildHead> + DispatchBirth<A, Interpreter> + Send,
988 <C as ChildCreationProduct<A, ChildHead>>::Result: Send,
989 Interpreter: InterpretItem<Creations<CreateChild<A, C>>, RootEvent, Path> + Send,
990{
991 fn interpret_creations(
992 progress: &mut Option<
993 InterpretationProgress<
994 Creations<CreateChild<A, C>>,
995 Self::InterpretationCustody,
996 Self::Settlements,
997 >,
998 >,
999 interpreter: &mut Interpreter,
1000 ) -> impl Future<Output = ()> + Send {
1001 interpret_creations::<A, C, Interpreter, RootEvent, Path>(progress, interpreter)
1002 }
1003}
1004
1005impl<A, C, Interpreter, RootEvent, Path> InterpretCreations<A, Interpreter, RootEvent, Path>
1006 for RetirementBirths<C>
1007where
1008 A: Address,
1009 C: ChildCreationProduct<A, ChildHead>,
1010 Births<C>: BirthMode<Child = C> + InterpretCreations<A, Interpreter, RootEvent, Path>,
1011 Creations<CreateChild<A, C>>: Send,
1012 <Births<C> as CreationSettlements<A>>::InterpretationCustody: Send,
1013 <Births<C> as CreationSettlements<A>>::Settlements: Send,
1014 Interpreter: Send,
1015{
1016 fn interpret_creations(
1017 progress: &mut Option<
1018 InterpretationProgress<
1019 Creations<CreateChild<A, C>>,
1020 Self::InterpretationCustody,
1021 Self::Settlements,
1022 >,
1023 >,
1024 interpreter: &mut Interpreter,
1025 ) -> impl Future<Output = ()> + Send {
1026 async move {
1027 <Self as CreationSettlements<A>>::prepare_interpretation(progress);
1028 let Some(InterpretationProgress::Interpreting(base)) = progress else {
1029 return;
1030 };
1031 <Births<C> as InterpretCreations<A,Interpreter,RootEvent,Path>>::interpret_creations(base,interpreter).await;
1032 <Births<C> as CreationSettlements<A>>::finish_interpretation(base);
1033 <Self as CreationSettlements<A>>::finish_interpretation(progress);
1034 }
1035 }
1036}
1037
1038impl<Creations, Sends, Ph> ClassifySettlement for ActionSettlement<Creations, Sends, Ph>
1039where
1040 Creations: ClassifySettlement,
1041 Sends: ClassifySettlement,
1042{
1043 fn settlement_status(&self) -> SettlementStatus {
1044 self.creations
1045 .settlement_status()
1046 .combine(self.sends.settlement_status())
1047 }
1048}
1049
1050impl<Host, RootEvent, Creations, Sends, Ph> SourceSettlementCustody<Host, RootEvent>
1051 for ActionSettlement<Creations, Sends, Ph>
1052where
1053 Host: Send,
1054 Creations: SourceSettlementCustody<Host, RootEvent> + Send,
1055 Sends: SourceSettlementCustody<Host, RootEvent> + Send,
1056 Ph: Send,
1057{
1058 type Custody = (
1059 <(Creations, Sends) as SourceSettlementCustody<Host, RootEvent>>::Custody,
1060 Become<Ph>,
1061 );
1062 fn prepare_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
1063 *progress = match progress.take() {
1064 Some(SourceProgress::Original(original)) => Some(SourceProgress::Offering((
1065 (
1066 Some(SourceProgress::Original(original.creations)),
1067 Some(SourceProgress::Original(original.sends)),
1068 ),
1069 original.become_,
1070 ))),
1071 progress => progress,
1072 };
1073 }
1074 fn offer_next_to_source(
1075 custody: &mut Self::Custody,
1076 host: &mut Host,
1077 ) -> impl Future<Output = ()> + Send {
1078 offer_source_in_order::<Host, RootEvent, Creations, Sends>(&mut custody.0, host)
1079 }
1080 fn finish_source(progress: &mut Option<SourceProgress<Self, Self::Custody>>) {
1081 let (custody, become_) = match progress.take() {
1082 Some(SourceProgress::Offering(custody)) => custody,
1083 retained => {
1084 *progress = retained;
1085 return;
1086 }
1087 };
1088 let mut product = Some(SourceProgress::Offering(custody));
1089 <(Creations, Sends) as SourceSettlementCustody<Host, RootEvent>>::finish_source(
1090 &mut product,
1091 );
1092 *progress = match product {
1093 Some(SourceProgress::Original((creations, sends))) => {
1094 Some(SourceProgress::Original(Self {
1095 creations,
1096 sends,
1097 become_,
1098 }))
1099 }
1100 Some(SourceProgress::Offering(custody)) => {
1101 Some(SourceProgress::Offering((custody, become_)))
1102 }
1103 Some(SourceProgress::Completed(reply)) => Some(SourceProgress::Completed(reply.map(
1104 |(creations, sends)| Self {
1105 creations,
1106 sends,
1107 become_,
1108 },
1109 ))),
1110 None => None,
1111 };
1112 }
1113}
1114
1115pub trait AppendSend<Input, Path>: Sized {
1118 #[must_use]
1120 fn append_send(self, input: Input) -> Self;
1121}
1122
1123#[must_use = "actor transition effects must be interpreted, inspected, or retained"]
1138pub struct Actions<A: Address, Ph, Sends, Birth: BirthMode> {
1139 pub sends: Sends,
1140 pub creates: Creations<CreateChild<A, Birth::Child>>,
1141 pub become_: Become<Ph>,
1142}
1143
1144impl<A, Ph, Sends, Birth> core::fmt::Debug for Actions<A, Ph, Sends, Birth>
1145where
1146 A: Address + core::fmt::Debug,
1147 A::Nonce: core::fmt::Debug,
1148 Ph: core::fmt::Debug,
1149 Sends: core::fmt::Debug,
1150 Birth: BirthMode,
1151 Birth::Child: core::fmt::Debug,
1152{
1153 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1154 formatter
1155 .debug_struct("Actions")
1156 .field("sends", &self.sends)
1157 .field("creates", &self.creates)
1158 .field("become", &self.become_)
1159 .finish()
1160 }
1161}
1162
1163impl<A, Ph, Sends, Birth> PartialEq for Actions<A, Ph, Sends, Birth>
1164where
1165 A: Address + PartialEq,
1166 A::Nonce: PartialEq,
1167 Ph: PartialEq,
1168 Sends: PartialEq,
1169 Birth: BirthMode,
1170 Birth::Child: PartialEq,
1171{
1172 fn eq(&self, other: &Self) -> bool {
1173 self.sends == other.sends && self.creates == other.creates && self.become_ == other.become_
1174 }
1175}
1176
1177impl<A, Ph, Sends, Birth> Eq for Actions<A, Ph, Sends, Birth>
1178where
1179 A: Address + Eq,
1180 A::Nonce: Eq,
1181 Ph: Eq,
1182 Sends: Eq,
1183 Birth: BirthMode,
1184 Birth::Child: Eq,
1185{
1186}
1187
1188impl<A: Address, Ph, Sends, Birth: BirthMode> Actions<A, Ph, Sends, Birth> {
1189 #[must_use]
1192 pub fn map_sends<Mapped>(
1193 self,
1194 map: impl FnOnce(Sends) -> Mapped,
1195 ) -> Actions<A, Ph, Mapped, Birth> {
1196 Actions {
1197 sends: map(self.sends),
1198 creates: self.creates,
1199 become_: self.become_,
1200 }
1201 }
1202
1203 #[must_use]
1206 pub fn map_become<NextPh>(
1207 self,
1208 map: impl FnOnce(Become<Ph>) -> Become<NextPh>,
1209 ) -> Actions<A, NextPh, Sends, Birth> {
1210 Actions {
1211 sends: self.sends,
1212 creates: self.creates,
1213 become_: map(self.become_),
1214 }
1215 }
1216
1217 #[must_use]
1223 pub fn with_send<Input, Path>(mut self, input: Input) -> Self
1224 where
1225 Sends: SendInput<Input, Path>,
1226 {
1227 <Sends as SendInput<Input, Path>>::emit(&mut self.sends, input);
1228 self
1229 }
1230
1231 pub async fn interpret<Interpreter, RootEvent, Path>(
1240 progress: &mut Option<
1241 InterpretationProgress<
1242 Self,
1243 <Self as ActionSettlements>::InterpretationCustody,
1244 <Self as ActionSettlements>::Settlements,
1245 >,
1246 >,
1247 interpreter: &mut Interpreter,
1248 ) where
1249 Ph: Send,
1250 Sends: InterpretSends<Interpreter, RootEvent, Path>,
1251 Birth: InterpretCreations<A, Interpreter, RootEvent, Path>,
1252 Self: Send,
1253 <Self as ActionSettlements>::Settlements: Send,
1254 <Self as ActionSettlements>::InterpretationCustody: Send,
1255 Interpreter: Send,
1256 {
1257 Self::prepare_interpretation(progress);
1258 let Some(InterpretationProgress::Interpreting(((creates, sends), _))) = progress else {
1259 return;
1260 };
1261 Birth::interpret_creations(creates, interpreter).await;
1262 Birth::finish_interpretation(creates);
1263 match creates {
1264 Some(InterpretationProgress::Completed(Interpretation::Complete(_))) => {
1265 Sends::interpret(sends, interpreter).await;
1266 Sends::finish_interpretation(sends);
1267 }
1268 Some(InterpretationProgress::Completed(Interpretation::Corrupt(_))) => {
1269 Sends::unattempted(sends);
1270 }
1271 _ => return,
1274 }
1275 Self::finish_interpretation(progress);
1276 }
1277}
1278
1279impl<A, Ph, Sends, Birth, Input, Path> AppendSend<Input, Path> for Actions<A, Ph, Sends, Birth>
1280where
1281 A: Address,
1282 Birth: BirthMode,
1283 Sends: SendInput<Input, Path>,
1284{
1285 fn append_send(self, input: Input) -> Self {
1286 self.with_send::<Input, Path>(input)
1287 }
1288}
1289
1290impl<A: Address, Ph, Sends: SendEffects, Birth: BirthMode> Actions<A, Ph, Sends, Birth> {
1291 #[must_use]
1292 pub const fn new(
1293 sends: Sends,
1294 creates: Creations<CreateChild<A, Birth::Child>>,
1295 become_: Become<Ph>,
1296 ) -> Self {
1297 Self {
1298 sends,
1299 creates,
1300 become_,
1301 }
1302 }
1303
1304 #[must_use]
1305 pub fn just(become_: Become<Ph>) -> Self {
1306 Self {
1307 sends: Sends::empty(),
1308 creates: Creations::empty(),
1309 become_,
1310 }
1311 }
1312
1313 #[must_use]
1314 pub fn cont() -> Self {
1315 Self::just(Step::Continue)
1316 }
1317 #[must_use]
1318 pub fn stop() -> Self {
1319 Self::just(Step::Stop(Stopped))
1320 }
1321 #[must_use]
1322 pub fn goto(phase: Ph) -> Self {
1323 Self::just(Step::Goto(phase))
1324 }
1325
1326 #[must_use]
1328 pub fn send(sends: Sends) -> Self {
1329 Self::new(sends, Creations::empty(), Step::Continue)
1330 }
1331
1332 #[must_use]
1334 pub fn create(creates: Creations<CreateChild<A, Birth::Child>>) -> Self {
1335 Self::new(Sends::empty(), creates, Step::Continue)
1336 }
1337}
1338
1339impl<A: Address, Ph, Sends, Birth: BirthMode>
1340 From<(Sends, Creations<CreateChild<A, Birth::Child>>, Become<Ph>)>
1341 for Actions<A, Ph, Sends, Birth>
1342{
1343 fn from(
1344 (sends, creates, become_): (Sends, Creations<CreateChild<A, Birth::Child>>, Become<Ph>),
1345 ) -> Self {
1346 Self {
1347 sends,
1348 creates,
1349 become_,
1350 }
1351 }
1352}
1353
1354pub type Acted<A, Ph, Sends, Birth, E> = Result<Actions<A, Ph, Sends, Birth>, E>;
1355
1356#[cfg(test)]
1357mod tests {
1358 use super::*;
1359 use crate::{Births, CreationSequence, MailAddr, NoBirths, Own};
1360
1361 fn two_ids() -> (crate::CreationId, crate::CreationId) {
1362 let mut sequence = CreationSequence::new();
1363 let first = sequence.issue().expect("the first creation ID exists");
1364 let second = sequence.issue().expect("the second creation ID exists");
1365 (first, second)
1366 }
1367
1368 #[test]
1369 fn equality_and_debug_cover_every_named_effect_leg() {
1370 type Plain = Actions<MailAddr, u8, Vec<u8>, NoBirths>;
1371 type Creating = Actions<MailAddr, Never, Vec<u8>, Births<u8>>;
1372
1373 let value = Plain::new(vec![1], Creations::empty(), Step::Goto(3));
1374 assert_eq!(
1375 value,
1376 Plain::new(vec![1], Creations::empty(), Step::Goto(3))
1377 );
1378 assert_ne!(
1379 value,
1380 Plain::new(vec![2], Creations::empty(), Step::Goto(3))
1381 );
1382 assert_ne!(
1383 value,
1384 Plain::new(vec![1], Creations::empty(), Step::Goto(4))
1385 );
1386 assert_ne!(
1387 value,
1388 Plain::new(vec![1], Creations::empty(), Step::Continue)
1389 );
1390 assert_eq!(
1391 format!("{value:?}"),
1392 "Actions { sends: [1], creates: Creations { items: [] }, become: Goto(3) }"
1393 );
1394
1395 let (first, second) = two_ids();
1396 let created = Creating::new(
1397 Vec::new(),
1398 Creations::one(CreateChild::birth(first, 9)),
1399 Step::Continue,
1400 );
1401 let other_creation = Creating::new(
1402 Vec::new(),
1403 Creations::one(CreateChild::birth(second, 9)),
1404 Step::Continue,
1405 );
1406 assert_ne!(created, other_creation);
1407 }
1408
1409 #[test]
1410 fn mapping_sends_preserves_creation_order_and_verdict() {
1411 let (first, second) = two_ids();
1412 let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
1413 vec![1, 2],
1414 Creations::one(CreateChild::birth(first, ())).and(CreateChild::replacement(
1415 second,
1416 first,
1417 (),
1418 )),
1419 Step::Goto(7),
1420 );
1421
1422 let mapped = actions.map_sends(|sends| sends.len());
1423 assert_eq!(mapped.sends, 2);
1424 assert_eq!(
1425 mapped
1426 .creates
1427 .iter()
1428 .map(CreateChild::id)
1429 .collect::<Vec<_>>(),
1430 [first, second]
1431 );
1432 assert!(matches!(mapped.become_, Step::Goto(7)));
1433 }
1434
1435 #[test]
1436 fn mapping_become_preserves_sends_and_creation_order() {
1437 let (first, _) = two_ids();
1438 let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
1439 vec![1, 2],
1440 Creations::one(CreateChild::birth(first, ())),
1441 Step::Goto(7),
1442 );
1443
1444 let mapped: Actions<MailAddr, Never, Vec<u8>, Births<()>> =
1445 actions.map_become(|_| Step::Stop(Stopped));
1446 assert_eq!(mapped.sends, [1, 2]);
1447 let mapped_creation_id = mapped.creates.iter().next().map(CreateChild::id);
1448 assert_eq!(mapped_creation_id, Some(first));
1449 assert!(matches!(mapped.become_, Step::Stop(Stopped)));
1450 }
1451
1452 #[test]
1453 fn fluent_send_changes_only_the_selected_effect_leg() {
1454 let (first, second) = two_ids();
1455 let actions: Actions<MailAddr, u8, Vec<u8>, Births<()>> = Actions::new(
1456 vec![1],
1457 Creations::one(CreateChild::birth(first, ())).and(CreateChild::replacement(
1458 second,
1459 first,
1460 (),
1461 )),
1462 Step::Goto(7),
1463 )
1464 .with_send::<_, Own>(2)
1465 .with_send::<_, Own>(3);
1466
1467 assert_eq!(actions.sends, [1, 2, 3]);
1468 assert_eq!(
1469 actions
1470 .creates
1471 .iter()
1472 .map(CreateChild::id)
1473 .collect::<Vec<_>>(),
1474 [first, second]
1475 );
1476 assert!(matches!(actions.become_, Step::Goto(7)));
1477
1478 let stopped: Actions<MailAddr, Never, Vec<u8>, NoBirths> =
1479 Actions::stop().with_send::<_, Own>(5);
1480 assert_eq!(stopped.sends, [5]);
1481 assert!(matches!(stopped.become_, Step::Stop(Stopped)));
1482 }
1483}