Skip to main content

behavior/effects/
sending.rs

1//! Typed send effects, their composition contract, and event ownership.
2
3use crate::{
4    Behavior, BirthProtocol, BirthProtocolProduct, ChildDelivery, ChildInput, ComposedEvent,
5    Delivery, EndpointAddress, EstablishedDelivery, InjectEvent, Inside, NoBirthProtocols,
6    Protocol,
7};
8use core::future::Future;
9
10/// Total settlement of one statically selected action item.
11///
12/// Rejection and dependency blocking retain the complete original item.
13/// Interpreter corruption does the same. Accepted items are consumed and leave
14/// only the capability's promised receipt. Whether an item was attempted at all
15/// belongs to [`SettledItem`], so a concrete interpreter cannot fabricate that
16/// product-level fact.
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18pub enum ItemSettlement<Item, Accepted, Rejection, Prerequisite> {
19    /// The capability consumed the item and returned its promised receipt.
20    Accepted(Accepted),
21    /// The capability lawfully rejected the complete item.
22    Rejected { item: Item, reason: Rejection },
23    /// A declared prerequisite did not commit, so the item remains untouched.
24    Blocked {
25        item: Item,
26        prerequisite: Prerequisite,
27    },
28    /// The interpreter violated its contract while the item remained owned.
29    Corrupt { item: Item, fault: InterpreterFault },
30}
31
32/// Product-owned evidence that an action item was attempted or left untouched.
33#[derive(Clone, Copy, Debug, Eq, PartialEq)]
34pub enum SettledItem<Item, Settlement> {
35    /// The concrete interpreter returned the item's complete settlement.
36    Attempted(Settlement),
37    /// Product traversal stopped at an earlier corrupt item.
38    Unattempted(Item),
39}
40
41/// Completion state of one total static product traversal.
42///
43/// Both variants own the complete settlement shape. `Corrupt` contains the
44/// factual committed prefix, the exact corrupt item, and every later item as
45/// [`SettledItem::Unattempted`].
46#[derive(Clone, Copy, Debug, Eq, PartialEq)]
47pub enum Interpretation<Settlement> {
48    Complete(Settlement),
49    Corrupt(Settlement),
50}
51
52impl<Settlement> Interpretation<Settlement> {
53    /// Transform the complete settlement shape without changing whether the
54    /// interpreter completed or corrupted.
55    #[must_use]
56    pub fn map<Mapped>(self, map: impl FnOnce(Settlement) -> Mapped) -> Interpretation<Mapped> {
57        match self {
58            Self::Complete(settlement) => Interpretation::Complete(map(settlement)),
59            Self::Corrupt(settlement) => Interpretation::Corrupt(map(settlement)),
60        }
61    }
62
63    /// Recover the complete owned settlement shape.
64    #[must_use]
65    pub fn into_settlement(self) -> Settlement {
66        match self {
67            Self::Complete(settlement) | Self::Corrupt(settlement) => settlement,
68        }
69    }
70}
71
72/// Interpret two statically named send products in declared order.
73///
74/// A corrupt earlier product retains the complete later product as
75/// unattempted. Expected rejection inside the earlier product does not stop
76/// the later product because it remains a complete interpretation.
77#[doc(hidden)]
78pub async fn settle_in_order<Interpreter, RootEvent, Path, Earlier, Later>(
79    earlier: Earlier,
80    later: Later,
81    interpreter: &mut Interpreter,
82) -> Interpretation<(Earlier::Settlements, Later::Settlements)>
83where
84    Interpreter: Send,
85    Earlier: InterpretSends<Interpreter, RootEvent, Path>,
86    Later: InterpretSends<Interpreter, RootEvent, Path>,
87{
88    let earlier = match earlier.interpret(interpreter).await {
89        Interpretation::Complete(earlier) => earlier,
90        Interpretation::Corrupt(earlier) => {
91            return Interpretation::Corrupt((earlier, later.unattempted()));
92        }
93    };
94    later
95        .interpret(interpreter)
96        .await
97        .map(|later| (earlier, later))
98}
99
100/// Read-only control-flow status of one complete retained settlement product.
101#[derive(Clone, Copy, Debug, Eq, PartialEq)]
102pub enum SettlementStatus {
103    /// Every item was attempted and accepted.
104    Accepted,
105    /// At least one item was lawfully rejected or blocked and none corrupted.
106    Rejected,
107    /// Interpretation corrupted or left an unattempted suffix.
108    Corrupt,
109}
110
111impl SettlementStatus {
112    #[must_use]
113    pub const fn combine(self, later: Self) -> Self {
114        match (self, later) {
115            (Self::Corrupt, _) | (_, Self::Corrupt) => Self::Corrupt,
116            (Self::Rejected, _) | (_, Self::Rejected) => Self::Rejected,
117            (Self::Accepted, Self::Accepted) => Self::Accepted,
118        }
119    }
120}
121
122/// Lossless status projection over an exact retained settlement value.
123pub trait ClassifySettlement {
124    /// Inspect every member without consuming or rewriting the settlement.
125    fn settlement_status(&self) -> SettlementStatus;
126}
127
128impl<Item, Accepted, Rejection, Prerequisite> ClassifySettlement
129    for ItemSettlement<Item, Accepted, Rejection, Prerequisite>
130{
131    fn settlement_status(&self) -> SettlementStatus {
132        match self {
133            Self::Accepted(_) => SettlementStatus::Accepted,
134            Self::Rejected { .. } | Self::Blocked { .. } => SettlementStatus::Rejected,
135            Self::Corrupt { .. } => SettlementStatus::Corrupt,
136        }
137    }
138}
139
140impl<Item, Settlement> ClassifySettlement for SettledItem<Item, Settlement>
141where
142    Settlement: ClassifySettlement,
143{
144    fn settlement_status(&self) -> SettlementStatus {
145        match self {
146            Self::Attempted(settlement) => settlement.settlement_status(),
147            Self::Unattempted(_) => SettlementStatus::Corrupt,
148        }
149    }
150}
151
152impl<Settlement> ClassifySettlement for Interpretation<Settlement>
153where
154    Settlement: ClassifySettlement,
155{
156    fn settlement_status(&self) -> SettlementStatus {
157        match self {
158            Self::Complete(settlement) => settlement.settlement_status(),
159            Self::Corrupt(_) => SettlementStatus::Corrupt,
160        }
161    }
162}
163
164impl<Settlement> ClassifySettlement for Vec<Settlement>
165where
166    Settlement: ClassifySettlement,
167{
168    fn settlement_status(&self) -> SettlementStatus {
169        let mut status = SettlementStatus::Accepted;
170        for settlement in self {
171            status = status.combine(settlement.settlement_status());
172        }
173        status
174    }
175}
176
177impl ClassifySettlement for crate::Never {
178    fn settlement_status(&self) -> SettlementStatus {
179        match *self {}
180    }
181}
182
183/// One concrete value that can occur in [`crate::Actions`].
184///
185/// The capability item owns its settlement vocabulary. Every conforming
186/// interpreter therefore agrees on the exact accepted receipt, rejection,
187/// and prerequisite types for that item. Interpreter corruption is the one
188/// shared [`InterpreterFault`] sum.
189///
190/// A runtime cannot substitute a different rejection type for the same item:
191///
192/// ```compile_fail,E0053
193/// struct Request;
194/// struct RequiredRejection;
195/// struct RuntimeRejection;
196///
197/// impl behavior::ActionItem for Request {
198///     type Accepted = ();
199///     type Rejection = RequiredRejection;
200///     type Prerequisite = behavior::Never;
201/// }
202///
203/// struct Runtime;
204/// impl behavior::InterpretItem<Request, (), behavior::Here> for Runtime {
205///     fn interpret_item(
206///         &mut self,
207///         item: Request,
208///     ) -> impl core::future::Future<
209///         Output = behavior::ItemSettlement<
210///             Request,
211///             (),
212///             RuntimeRejection,
213///             behavior::Never,
214///         >,
215///     > + Send {
216///         async move {
217///             behavior::ItemSettlement::Rejected { item, reason: RuntimeRejection }
218///         }
219///     }
220/// }
221/// ```
222pub trait ActionItem: Sized + Send {
223    type Accepted: Send;
224    type Rejection: Send;
225    type Prerequisite: Send;
226}
227
228/// Exact result of one action item within an interpreted action product.
229///
230/// The inner sum records the capability attempt. The outer sum preserves an
231/// untouched item when an earlier corrupt item stopped ordered traversal.
232pub type ActionItemResult<
233    Item,
234    Accepted = <Item as ActionItem>::Accepted,
235    Rejection = <Item as ActionItem>::Rejection,
236    Prerequisite = <Item as ActionItem>::Prerequisite,
237> = SettledItem<Item, ItemSettlement<Item, Accepted, Rejection, Prerequisite>>;
238
239/// A broken interpreter invariant, distinct from expected capability rejection.
240#[derive(Clone, Copy, Debug, Eq, PartialEq)]
241pub enum InterpreterFault {
242    MissingCapability,
243    CorruptTraversal,
244}
245
246/// Exact reason one structural parent report was not accepted.
247#[derive(Clone, Copy, Debug, Eq, PartialEq)]
248pub enum ParentReportReason {
249    ClosedParentControlLane,
250}
251
252/// Concrete interpreter ownership port for one exact typed action item.
253///
254/// `Item`, `RootEvent`, and `Path` select the capability statically. Distinct
255/// delivery and runtime-request values remain distinct implementations without
256/// an erased envelope, registry, or runtime lookup.
257pub trait InterpretItem<Item, RootEvent, Path>: Send
258where
259    Item: ActionItem,
260{
261    /// Attempt exactly one item and return its complete settlement.
262    fn interpret_item(
263        &mut self,
264        item: Item,
265    ) -> impl Future<
266        Output = ItemSettlement<Item, Item::Accepted, Item::Rejection, Item::Prerequisite>,
267    > + Send;
268}
269
270/// Static settlement product determined solely by one concrete sends value.
271///
272/// Every action item declares its own accepted, rejection, and prerequisite
273/// types. A containing product therefore has one settlement type under every
274/// conforming interpreter. `unattempted` preserves every item untouched after
275/// an earlier corrupt item stops traversal.
276///
277/// A runtime cannot select another settlement product for the same sends value:
278///
279/// ```compile_fail,E0271
280/// struct RuntimeSettlement;
281///
282/// fn runtime_selected<Runtime>(
283///     requests: behavior::InterpreterRequests<behavior::ReportToParent<u8>>,
284///     runtime: &mut Runtime,
285/// ) -> impl core::future::Future<
286///     Output = behavior::Interpretation<RuntimeSettlement>,
287/// > + Send
288/// where
289///     Runtime: behavior::InterpretItem<
290///         behavior::ReportToParent<u8>,
291///         (),
292///         behavior::Here,
293///     >,
294/// {
295///     <behavior::InterpreterRequests<behavior::ReportToParent<u8>> as
296///         behavior::InterpretSends<Runtime, (), behavior::Here>>::interpret(
297///             requests,
298///             runtime,
299///         )
300/// }
301/// ```
302pub trait SendSettlements: Sized {
303    /// Complete settlement product corresponding to `Self`.
304    type Settlements: Send + ClassifySettlement;
305
306    /// Preserve every item without granting interpretation authority.
307    fn unattempted(self) -> Self::Settlements;
308}
309
310/// Static interpretation of one complete sends value at an absolute event path.
311///
312/// Implementations are monomorphized over `Interpreter`; there is no erased
313/// envelope, runtime lane lookup, or downcast. `RootEvent` is the event type
314/// ultimately enqueued for the actor and `Path` is the current send owner's
315/// absolute position in it. Lawful rejection and blocking continue to later
316/// independent items. Corruption stops interpretation but retains the exact
317/// fault item and every untouched suffix value in the settlement shape.
318pub trait InterpretSends<Interpreter, RootEvent, Path>: SendSettlements + Send {
319    /// Interpret every value in this product in its declared stable order.
320    fn interpret(
321        self,
322        interpreter: &mut Interpreter,
323    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send;
324}
325
326/// The lane owned by the current named send product.
327pub enum Own {}
328
329/// Static evidence that a sends type contains one request lane.
330///
331/// Implementations append the input exactly once to that lane and leave every
332/// other lane unchanged. `Path` distinguishes repeated request types without
333/// erasing their position or choosing a lane at runtime.
334///
335/// [`Own`] selects a named product's own semantic lane. [`SendLayer`] carries
336/// wrapper-owned and inner effects as explicit named fields; request routing
337/// remains a compile-time proof rather than a runtime lane lookup.
338pub trait SendInput<Input, Path> {
339    fn emit(&mut self, input: Input);
340}
341
342/// Send effects emitted by a pure actor transition.
343///
344/// Values compose without interpreting them. This keeps communications and
345/// interpreter requests inside the explicit [`crate::Actions`] boundary.
346pub trait SendEffects: Sized {
347    fn empty() -> Self;
348    fn append(&mut self, other: Self);
349
350    #[must_use]
351    fn combine(mut self, other: Self) -> Self {
352        self.append(other);
353        self
354    }
355
356    /// Append one request to its statically selected semantic lane.
357    fn send<Input, Path>(&mut self, input: Input)
358    where
359        Self: SendInput<Input, Path>,
360    {
361        <Self as SendInput<Input, Path>>::emit(self, input);
362    }
363
364    /// Build a send product containing one request in its selected lane.
365    #[must_use]
366    fn sending<Input, Path>(input: Input) -> Self
367    where
368        Self: SendInput<Input, Path>,
369    {
370        let mut sends = Self::empty();
371        sends.send(input);
372        sends
373    }
374}
375
376/// Static projection of intentional logical destinations from one concrete
377/// sends product.
378///
379/// Implementations mirror the product's [`InterpretSends`] traversal without
380/// inspecting values. Only [`Delivery<P>`] contributes `P`; exact established
381/// deliveries, creator-local child deliveries and inputs, and interpreter
382/// requests contribute nothing. Named products append their field projections
383/// in interpretation order, preserving repeated protocol occurrences.
384///
385/// Custom named sends products must implement this trait explicitly. There is
386/// deliberately no blanket `Vec<T>` implementation that could silently treat
387/// an unknown delivery representation as having no logical destination.
388///
389/// ```compile_fail,E0277
390/// use behavior::{
391///     Actions, Behavior, BehaviorActed, LogicalHostRequirements, MailAddr,
392///     Never, NoBirths, Protocol, SendEffects, User,
393/// };
394/// struct OpaqueSends;
395/// impl SendEffects for OpaqueSends {
396///     fn empty() -> Self { Self }
397///     fn append(&mut self, _: Self) {}
398/// }
399/// impl<E> behavior::SendsFor<E> for OpaqueSends {}
400/// struct Actor;
401/// impl Protocol for Actor { type Addr = MailAddr; type Msg = (); }
402/// impl Behavior for Actor {
403///     type Protocol = Self;
404///     type Event = User<MailAddr, ()>;
405///     type Sends = OpaqueSends;
406///     type Ph = Never;
407///     type Error = Never;
408///     type Birth = NoBirths;
409///     fn transition(&mut self, _: behavior::ActiveTurn, _: Self::Event)
410///         -> BehaviorActed<Self> { Ok(Actions::cont()) }
411/// }
412/// fn require_complete<B: LogicalHostRequirements>() {}
413/// require_complete::<Actor>();
414/// ```
415pub trait LogicalDeliveryProtocols: SendEffects {
416    /// Ordered, duplicate-preserving logical protocol occurrences.
417    type Protocols: BirthProtocolProduct;
418}
419
420/// Proof that send effects are lawful for one complete event type.
421///
422/// Ordinary communications are independent of `Event`. Interpreter requests
423/// that return a local fact are not: their continuation must select an exact
424/// member of `Event`. Composite products implement this trait structurally,
425/// reindexing only their wrapped behavior effects through an outer event
426/// injection.
427///
428/// An un-reindexed return to the emitter cannot be paired with an added outer event
429/// layer:
430///
431/// ```compile_fail
432/// use behavior::{SendsFor, EventLayer, Here, MailAddr, ReturnsToEmitter,
433///     InterpreterRequest, InterpreterRequests, User};
434/// struct Request;
435/// impl InterpreterRequest for Request {
436///     type ReturnToEmitter = ReturnsToEmitter<u8, Here>;
437/// }
438/// fn lawful<E, F: SendsFor<E>>() {}
439/// type Inner = EventLayer<u8, User<MailAddr, ()>>;
440/// type Outer = EventLayer<(), Inner>;
441/// lawful::<Outer, InterpreterRequests<Request>>();
442/// ```
443pub trait SendsFor<Event>: SendEffects {}
444
445/// One action whose exact interpretation result returns to its live source.
446///
447/// [`ActionItem`] determines the complete result. An implementation selects
448/// only the actor receiving it, so an action cannot discard a rejected or
449/// unattempted value or reinterpret its status. Bombay admits the exact input
450/// through [`SourceAdmission`] or keeps it in lifecycle custody.
451pub trait SourceAction: ActionItem {
452    /// Actor-owned ingress selection for the result.
453    type Source;
454}
455
456/// Ordered actions whose normalized results return to their emitting actor.
457///
458/// This product is interpreter-facing machinery. Aggregate builders expose
459/// domain operations, not this structural lane.
460pub struct SourceActions<Item> {
461    items: Vec<Item>,
462}
463
464impl<Item> SourceActions<Item> {
465    /// Number of requests retained in authored order.
466    #[must_use]
467    pub fn len(&self) -> usize {
468        self.items.len()
469    }
470
471    /// Report whether this ordered request lane contains no items.
472    #[must_use]
473    pub fn is_empty(&self) -> bool {
474        self.items.is_empty()
475    }
476
477    /// Consume the lane into its requests in authored order.
478    #[must_use]
479    pub fn into_items(self) -> Vec<Item> {
480        self.items
481    }
482}
483
484impl<Item> SendEffects for SourceActions<Item> {
485    fn empty() -> Self {
486        Self { items: Vec::new() }
487    }
488
489    fn append(&mut self, mut other: Self) {
490        self.items.append(&mut other.items);
491    }
492}
493
494impl<Item> SendInput<Item, Own> for SourceActions<Item> {
495    fn emit(&mut self, input: Item) {
496        self.items.push(input);
497    }
498}
499
500impl<Item> LogicalDeliveryProtocols for SourceActions<Item> {
501    type Protocols = crate::NoBirthProtocols;
502}
503
504impl<Event, Item> SendsFor<Event> for SourceActions<Item> where Item: SourceAction {}
505
506/// Exact results for one [`SourceActions`] lane.
507///
508/// Closed admission retains values in this same product. There is no second
509/// residual representation and no inverse conversion.
510pub struct SourceSettlements<Item>
511where
512    Item: SourceAction,
513{
514    inputs: Vec<ActionItemResult<Item>>,
515}
516
517impl<Item> SourceSettlements<Item>
518where
519    Item: SourceAction,
520{
521    fn new(inputs: Vec<ActionItemResult<Item>>) -> Self {
522        Self { inputs }
523    }
524
525    /// Transfer every retained input in authored order.
526    #[must_use]
527    pub fn into_inputs(self) -> Vec<ActionItemResult<Item>> {
528        self.inputs
529    }
530}
531
532impl<Item> ClassifySettlement for SourceSettlements<Item>
533where
534    Item: SourceAction,
535{
536    fn settlement_status(&self) -> SettlementStatus {
537        self.inputs.settlement_status()
538    }
539}
540
541impl<Item> SendSettlements for SourceActions<Item>
542where
543    Item: SourceAction,
544{
545    type Settlements = SourceSettlements<Item>;
546
547    fn unattempted(self) -> Self::Settlements {
548        SourceSettlements::new(
549            self.items
550                .into_iter()
551                .map(SettledItem::Unattempted)
552                .collect(),
553        )
554    }
555}
556
557impl<Interpreter, RootEvent, Path, Item> InterpretSends<Interpreter, RootEvent, Path>
558    for SourceActions<Item>
559where
560    Interpreter: InterpretItem<Item, RootEvent, Path>,
561    Item: SourceAction,
562{
563    fn interpret(
564        self,
565        interpreter: &mut Interpreter,
566    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
567        async move {
568            let mut items = self.items.into_iter();
569            let mut inputs = Vec::with_capacity(items.len());
570            while let Some(item) = items.next() {
571                match settle_item::<Item, Interpreter, RootEvent, Path>(item, interpreter).await {
572                    Interpretation::Complete(settlement) => {
573                        inputs.push(settlement);
574                    }
575                    Interpretation::Corrupt(settlement) => {
576                        inputs.push(settlement);
577                        inputs.extend(items.map(SettledItem::Unattempted));
578                        return Interpretation::Corrupt(SourceSettlements::new(inputs));
579                    }
580                }
581            }
582            Interpretation::Complete(SourceSettlements::new(inputs))
583        }
584    }
585}
586
587/// Bombay ownership port for one exact current-actor system input.
588///
589/// Success transfers the input to the existing actor loop. Closed admission
590/// returns the unchanged input to the current lifecycle host.
591///
592/// An event without the exact source ingress cannot implement this port:
593///
594/// ```compile_fail,E0277
595/// struct EventWithoutInput;
596/// struct Owner;
597/// struct Input;
598/// struct Host;
599/// impl behavior::SourceAdmission<EventWithoutInput, Owner, Input> for Host {
600///     async fn admit_source(&mut self, _: Input) -> Result<(), Input> { Ok(()) }
601/// }
602/// ```
603pub trait SourceAdmission<RootEvent, Source, Input>: Send
604where
605    RootEvent: crate::EventIngress<Source, Input>,
606{
607    /// Attempt one source input without discarding closed-control ownership.
608    fn admit_source(&mut self, input: Input) -> impl Future<Output = Result<(), Input>> + Send;
609}
610
611/// Result of offering at most one ordered source settlement.
612pub enum SourceCustody<Residual> {
613    /// No source input remains in the complete residual product.
614    Exhausted(Residual),
615    /// Exactly one source input transferred; the residual remains in custody.
616    Admitted(Residual),
617    /// Admission closed; the residual contains the current and untouched suffix.
618    Closed(Residual),
619}
620
621impl<Residual> SourceCustody<Residual> {
622    /// Transform the complete residual without changing its custody state.
623    #[must_use]
624    pub fn map<Mapped>(self, map: impl FnOnce(Residual) -> Mapped) -> SourceCustody<Mapped> {
625        match self {
626            Self::Exhausted(residual) => SourceCustody::Exhausted(map(residual)),
627            Self::Admitted(residual) => SourceCustody::Admitted(map(residual)),
628            Self::Closed(residual) => SourceCustody::Closed(map(residual)),
629        }
630    }
631}
632
633/// Static one-at-a-time source admission for one complete settlement product.
634pub trait SourceSettlementCustody<Host, RootEvent>: Sized {
635    /// Offer only the next source input in declared order.
636    fn offer_next_to_source(
637        self,
638        host: &mut Host,
639    ) -> impl Future<Output = SourceCustody<Self>> + Send;
640}
641
642/// Offer one source input from two settlement products in declared order.
643///
644/// The later product is untouched unless the earlier product is exhausted.
645/// Even when the earlier product admits an input, this operation returns so
646/// the actor loop can process that input and its transitive effects first.
647pub(super) async fn offer_source_in_order<Host, RootEvent, Earlier, Later>(
648    earlier: Earlier,
649    later: Later,
650    host: &mut Host,
651) -> SourceCustody<(Earlier, Later)>
652where
653    Host: Send,
654    Earlier: SourceSettlementCustody<Host, RootEvent> + Send,
655    Later: SourceSettlementCustody<Host, RootEvent> + Send,
656{
657    match earlier.offer_next_to_source(host).await {
658        SourceCustody::Exhausted(earlier) => later
659            .offer_next_to_source(host)
660            .await
661            .map(|later| (earlier, later)),
662        SourceCustody::Admitted(earlier) => SourceCustody::Admitted((earlier, later)),
663        SourceCustody::Closed(earlier) => SourceCustody::Closed((earlier, later)),
664    }
665}
666
667impl<Host, RootEvent, Earlier, Later> SourceSettlementCustody<Host, RootEvent> for (Earlier, Later)
668where
669    Host: Send,
670    Earlier: SourceSettlementCustody<Host, RootEvent> + Send,
671    Later: SourceSettlementCustody<Host, RootEvent> + Send,
672{
673    fn offer_next_to_source(
674        self,
675        host: &mut Host,
676    ) -> impl Future<Output = SourceCustody<Self>> + Send {
677        offer_source_in_order(self.0, self.1, host)
678    }
679}
680
681impl<Host, RootEvent, Item> SourceSettlementCustody<Host, RootEvent> for SourceSettlements<Item>
682where
683    Host: SourceAdmission<RootEvent, Item::Source, ActionItemResult<Item>>,
684    RootEvent: crate::EventIngress<Item::Source, ActionItemResult<Item>>,
685    Item: SourceAction,
686{
687    fn offer_next_to_source(
688        self,
689        host: &mut Host,
690    ) -> impl Future<Output = SourceCustody<Self>> + Send {
691        async move {
692            let mut source_inputs = self.inputs.into_iter();
693            let Some(input) = source_inputs.next() else {
694                return SourceCustody::Exhausted(Self::new(Vec::new()));
695            };
696            match host.admit_source(input).await {
697                Ok(()) => SourceCustody::Admitted(Self::new(source_inputs.collect())),
698                Err(input) => {
699                    let mut residual = Vec::with_capacity(source_inputs.len() + 1);
700                    residual.push(input);
701                    residual.extend(source_inputs);
702                    SourceCustody::Closed(Self::new(residual))
703                }
704            }
705        }
706    }
707}
708
709impl<Host, RootEvent> SourceSettlementCustody<Host, RootEvent> for NoSends {
710    fn offer_next_to_source(
711        self,
712        _: &mut Host,
713    ) -> impl Future<Output = SourceCustody<Self>> + Send {
714        async move { SourceCustody::Exhausted(self) }
715    }
716}
717
718impl<Host, RootEvent, Item> SourceSettlementCustody<Host, RootEvent> for Vec<ActionItemResult<Item>>
719where
720    Item: ActionItem,
721{
722    fn offer_next_to_source(
723        self,
724        _: &mut Host,
725    ) -> impl Future<Output = SourceCustody<Self>> + Send {
726        async move { SourceCustody::Exhausted(self) }
727    }
728}
729
730impl<Host, RootEvent> SourceSettlementCustody<Host, RootEvent> for Vec<crate::Never> {
731    fn offer_next_to_source(
732        self,
733        _: &mut Host,
734    ) -> impl Future<Output = SourceCustody<Self>> + Send {
735        async move { SourceCustody::Exhausted(self) }
736    }
737}
738
739impl<Host, RootEvent, Owned, Inner> SourceSettlementCustody<Host, RootEvent>
740    for SendLayer<Owned, Inner>
741where
742    Host: Send,
743    Owned: SourceSettlementCustody<Host, RootEvent> + Send,
744    Inner: SourceSettlementCustody<Host, RootEvent> + Send,
745{
746    fn offer_next_to_source(
747        self,
748        host: &mut Host,
749    ) -> impl Future<Output = SourceCustody<Self>> + Send {
750        async move {
751            offer_source_in_order(self.inner, self.owned, host)
752                .await
753                .map(|(inner, owned)| SendLayer::new(owned, inner))
754        }
755    }
756}
757
758/// An interpreter request that produces no later fact for the emitting actor.
759pub enum NoReturnToEmitter {}
760
761/// An interpreter request whose later `Input` returns to the emitting actor at
762/// `Path`, relative to the effect lane that owns the request.
763pub struct ReturnsToEmitter<Input, Path>(core::marker::PhantomData<fn(Input, Path)>);
764
765/// Local-return contract declared by one interpreter-facing request.
766pub trait ReturnToEmitterFor<Event> {}
767
768impl<Event> ReturnToEmitterFor<Event> for NoReturnToEmitter {}
769
770impl<Event, Input, Path> ReturnToEmitterFor<Event> for ReturnsToEmitter<Input, Path> where
771    Event: InjectEvent<Input, Path>
772{
773}
774
775/// Declares only the continuation returning to the actor that emitted this
776/// interpreter request. Destinations owned by a child, parent, ancestor, or
777/// established actor are separate capabilities and are not reindexed when the
778/// emitter is wrapped.
779pub trait InterpreterRequest {
780    type ReturnToEmitter;
781}
782
783/// Transfer one owned report to the emitter's established parent.
784///
785/// The request is an ordinary typed send effect. Its interpreter uses the
786/// already-established creator/child relationship, attaches the emitter's
787/// exact creator-local nonce, and injects a [`crate::ChildReport`] into the
788/// parent's closed event algebra. It performs no address or protocol lookup.
789/// A root behavior has no parent capability and therefore cannot interpret
790/// this request.
791#[derive(Debug, Clone, Copy, PartialEq, Eq)]
792pub struct ReportToParent<R> {
793    /// Complete report value transferred to the parent.
794    pub report: R,
795}
796
797impl<R> ReportToParent<R> {
798    /// Construct one structural parent report.
799    #[must_use]
800    pub const fn new(report: R) -> Self {
801        Self { report }
802    }
803
804    /// Recover ownership of the complete report value.
805    #[must_use]
806    pub fn into_inner(self) -> R {
807        self.report
808    }
809}
810
811impl<R> InterpreterRequest for ReportToParent<R> {
812    type ReturnToEmitter = NoReturnToEmitter;
813}
814
815impl<R> ActionItem for ReportToParent<R>
816where
817    R: Send,
818{
819    type Accepted = ();
820    type Rejection = ParentReportReason;
821    type Prerequisite = crate::Never;
822}
823
824/// Send effects containing no communications or interpreter requests.
825///
826/// A behavior layer that adds an event lane but emits nothing of its own uses
827/// this named value rather than an ambiguous `()`.
828#[derive(Debug, Clone, Copy, PartialEq, Eq)]
829pub struct NoSends;
830
831impl SendEffects for NoSends {
832    fn empty() -> Self {
833        Self
834    }
835
836    fn append(&mut self, _: Self) {}
837}
838
839impl LogicalDeliveryProtocols for NoSends {
840    type Protocols = NoBirthProtocols;
841}
842
843impl<Event> SendsFor<Event> for NoSends {}
844
845impl SendSettlements for NoSends {
846    type Settlements = Self;
847
848    fn unattempted(self) -> Self::Settlements {
849        self
850    }
851}
852
853impl ClassifySettlement for NoSends {
854    fn settlement_status(&self) -> SettlementStatus {
855        SettlementStatus::Accepted
856    }
857}
858
859impl<Interpreter, RootEvent, Path> InterpretSends<Interpreter, RootEvent, Path> for NoSends {
860    fn interpret(
861        self,
862        _: &mut Interpreter,
863    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
864        async move { Interpretation::Complete(self) }
865    }
866}
867
868/// Send effects introduced by one wrapper around inner send effects.
869///
870/// `owned` contains effects introduced by the current behavior layer and
871/// `inner` contains effects of the wrapped interaction. The structural
872/// [`SendsFor`] implementation is the composition law:
873///
874/// ```text
875/// Event'   = OwnedEvent + InnerEvent
876/// Effects' = OwnedEffects × InnerEffects
877/// ```
878///
879/// Owned return to the emitters target `Event'`; inner return to the emitters target
880/// `InnerEvent` and are therefore lifted through the same `Inner` injection.
881/// Established actor, child, and ancestor destinations are unaffected because
882/// they are not return to the emitters.
883#[derive(Debug, Clone, Copy, PartialEq, Eq)]
884pub struct SendLayer<Owned, Inner> {
885    pub owned: Owned,
886    pub inner: Inner,
887}
888
889impl<Owned, Inner> SendLayer<Owned, Inner> {
890    #[must_use]
891    pub const fn new(owned: Owned, inner: Inner) -> Self {
892        Self { owned, inner }
893    }
894}
895
896impl<Owned: SendEffects, Inner: SendEffects> SendEffects for SendLayer<Owned, Inner> {
897    fn empty() -> Self {
898        Self::new(Owned::empty(), Inner::empty())
899    }
900
901    fn append(&mut self, other: Self) {
902        self.owned.append(other.owned);
903        self.inner.append(other.inner);
904    }
905}
906
907impl<Owned, Inner> LogicalDeliveryProtocols for SendLayer<Owned, Inner>
908where
909    Owned: LogicalDeliveryProtocols,
910    Inner: LogicalDeliveryProtocols,
911{
912    // Interpretation preserves authored inner-to-outer wrapper order.
913    type Protocols = <Inner::Protocols as BirthProtocolProduct>::Append<Owned::Protocols>;
914}
915
916impl<Event, OwnedEffects, InnerEffects> SendsFor<Event> for SendLayer<OwnedEffects, InnerEffects>
917where
918    Event: ComposedEvent,
919    OwnedEffects: SendsFor<Event>,
920    InnerEffects: SendsFor<Event::Inner>,
921{
922}
923
924impl<Owned, Inner> SendSettlements for SendLayer<Owned, Inner>
925where
926    Owned: SendSettlements,
927    Inner: SendSettlements,
928{
929    type Settlements = SendLayer<Owned::Settlements, Inner::Settlements>;
930
931    fn unattempted(self) -> Self::Settlements {
932        SendLayer::new(self.owned.unattempted(), self.inner.unattempted())
933    }
934}
935
936impl<Owned, Inner> ClassifySettlement for SendLayer<Owned, Inner>
937where
938    Owned: ClassifySettlement,
939    Inner: ClassifySettlement,
940{
941    fn settlement_status(&self) -> SettlementStatus {
942        self.inner
943            .settlement_status()
944            .combine(self.owned.settlement_status())
945    }
946}
947
948impl<Input, Path, Owned, Inner> SendInput<Input, Path> for SendLayer<Owned, Inner>
949where
950    Owned: SendInput<Input, Path>,
951{
952    fn emit(&mut self, input: Input) {
953        self.owned.emit(input);
954    }
955}
956
957impl<Interpreter, RootEvent, Path, Owned, Inner> InterpretSends<Interpreter, RootEvent, Path>
958    for SendLayer<Owned, Inner>
959where
960    Interpreter: Send,
961    Owned: InterpretSends<Interpreter, RootEvent, Path> + Send,
962    Inner: InterpretSends<Interpreter, RootEvent, Inside<Path>> + Send,
963{
964    fn interpret(
965        self,
966        interpreter: &mut Interpreter,
967    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
968        async move {
969            let inner = <Inner as InterpretSends<Interpreter, RootEvent, Inside<Path>>>::interpret(
970                self.inner,
971                interpreter,
972            )
973            .await;
974            let inner = match inner {
975                Interpretation::Complete(inner) => inner,
976                Interpretation::Corrupt(inner) => {
977                    return Interpretation::Corrupt(SendLayer::new(
978                        self.owned.unattempted(),
979                        inner,
980                    ));
981                }
982            };
983            match <Owned as InterpretSends<Interpreter, RootEvent, Path>>::interpret(
984                self.owned,
985                interpreter,
986            )
987            .await
988            {
989                Interpretation::Complete(owned) => {
990                    Interpretation::Complete(SendLayer::new(owned, inner))
991                }
992                Interpretation::Corrupt(owned) => {
993                    Interpretation::Corrupt(SendLayer::new(owned, inner))
994                }
995            }
996        }
997    }
998}
999
1000impl<T> SendEffects for Vec<T> {
1001    fn empty() -> Self {
1002        Vec::new()
1003    }
1004
1005    fn append(&mut self, mut other: Self) {
1006        Vec::append(self, &mut other);
1007    }
1008}
1009
1010impl<P: Protocol> LogicalDeliveryProtocols for Vec<Delivery<P>> {
1011    type Protocols = BirthProtocol<P, NoBirthProtocols>;
1012}
1013
1014impl<P: Protocol, Occurrence> LogicalDeliveryProtocols for Vec<ChildDelivery<P, Occurrence>> {
1015    type Protocols = NoBirthProtocols;
1016}
1017
1018impl<Child, Source, Input, Occurrence> LogicalDeliveryProtocols
1019    for Vec<ChildInput<Child, Source, Input, Occurrence>>
1020where
1021    Child: Behavior,
1022{
1023    type Protocols = NoBirthProtocols;
1024}
1025
1026impl<P> LogicalDeliveryProtocols for Vec<EstablishedDelivery<P>>
1027where
1028    P: Protocol,
1029    P::Addr: EndpointAddress,
1030{
1031    type Protocols = NoBirthProtocols;
1032}
1033
1034impl LogicalDeliveryProtocols for Vec<crate::Never> {
1035    type Protocols = NoBirthProtocols;
1036}
1037
1038impl<Event, T> SendsFor<Event> for Vec<T> {}
1039
1040impl<Item> SendSettlements for Vec<Item>
1041where
1042    Item: ActionItem,
1043{
1044    type Settlements = Vec<ActionItemResult<Item>>;
1045
1046    fn unattempted(self) -> Self::Settlements {
1047        unattempted_items(self)
1048    }
1049}
1050
1051/// Interpret exactly one item and attach its product-owned attempt evidence.
1052///
1053/// This is the indivisible form of [`InterpretSends`]. It marks the enclosing
1054/// interpretation corrupt exactly when the concrete item result is corrupt;
1055/// lawful rejection and blocking remain complete outcomes.
1056pub async fn settle_item<Item, Interpreter, RootEvent, Path>(
1057    item: Item,
1058    interpreter: &mut Interpreter,
1059) -> Interpretation<ActionItemResult<Item>>
1060where
1061    Item: ActionItem,
1062    Interpreter: InterpretItem<Item, RootEvent, Path>,
1063{
1064    let settlement =
1065        <Interpreter as InterpretItem<Item, RootEvent, Path>>::interpret_item(interpreter, item)
1066            .await;
1067    match settlement {
1068        corrupt @ ItemSettlement::Corrupt { .. } => {
1069            Interpretation::Corrupt(SettledItem::Attempted(corrupt))
1070        }
1071        settled => Interpretation::Complete(SettledItem::Attempted(settled)),
1072    }
1073}
1074
1075async fn interpret_items<Item, Interpreter, RootEvent, Path>(
1076    items: Vec<Item>,
1077    interpreter: &mut Interpreter,
1078) -> Interpretation<Vec<ActionItemResult<Item>>>
1079where
1080    Item: ActionItem,
1081    Interpreter: InterpretItem<Item, RootEvent, Path>,
1082{
1083    let mut items = items.into_iter();
1084    let mut settlements = Vec::with_capacity(items.len());
1085    while let Some(item) = items.next() {
1086        match settle_item::<Item, Interpreter, RootEvent, Path>(item, interpreter).await {
1087            Interpretation::Complete(settlement) => settlements.push(settlement),
1088            Interpretation::Corrupt(settlement) => {
1089                settlements.push(settlement);
1090                settlements.extend(items.map(SettledItem::Unattempted));
1091                return Interpretation::Corrupt(settlements);
1092            }
1093        }
1094    }
1095    Interpretation::Complete(settlements)
1096}
1097
1098fn unattempted_items<Item>(items: Vec<Item>) -> Vec<ActionItemResult<Item>>
1099where
1100    Item: ActionItem,
1101{
1102    items.into_iter().map(SettledItem::Unattempted).collect()
1103}
1104
1105impl<Interpreter, RootEvent, Path, P> InterpretSends<Interpreter, RootEvent, Path>
1106    for Vec<Delivery<P>>
1107where
1108    Interpreter: InterpretItem<Delivery<P>, RootEvent, Path>,
1109    P: Protocol,
1110    Delivery<P>: ActionItem,
1111{
1112    fn interpret(
1113        self,
1114        interpreter: &mut Interpreter,
1115    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1116        interpret_items(self, interpreter)
1117    }
1118}
1119
1120impl<Interpreter, RootEvent, Path, P, Occurrence> InterpretSends<Interpreter, RootEvent, Path>
1121    for Vec<ChildDelivery<P, Occurrence>>
1122where
1123    Interpreter: InterpretItem<ChildDelivery<P, Occurrence>, RootEvent, Path>,
1124    P: Protocol,
1125    ChildDelivery<P, Occurrence>: ActionItem,
1126{
1127    fn interpret(
1128        self,
1129        interpreter: &mut Interpreter,
1130    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1131        interpret_items(self, interpreter)
1132    }
1133}
1134
1135impl<Interpreter, RootEvent, Path, Child, Source, Input, Occurrence>
1136    InterpretSends<Interpreter, RootEvent, Path>
1137    for Vec<ChildInput<Child, Source, Input, Occurrence>>
1138where
1139    Interpreter: InterpretItem<ChildInput<Child, Source, Input, Occurrence>, RootEvent, Path>,
1140    Child: Behavior,
1141    Child::Event: crate::ChildInputIngress<Source, Input>,
1142    ChildInput<Child, Source, Input, Occurrence>: ActionItem,
1143{
1144    fn interpret(
1145        self,
1146        interpreter: &mut Interpreter,
1147    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1148        interpret_items(self, interpreter)
1149    }
1150}
1151
1152impl<Interpreter, RootEvent, Path, P> InterpretSends<Interpreter, RootEvent, Path>
1153    for Vec<EstablishedDelivery<P>>
1154where
1155    Interpreter: InterpretItem<EstablishedDelivery<P>, RootEvent, Path>,
1156    P: Protocol,
1157    P::Addr: EndpointAddress,
1158    EstablishedDelivery<P>: ActionItem,
1159{
1160    fn interpret(
1161        self,
1162        interpreter: &mut Interpreter,
1163    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1164        interpret_items(self, interpreter)
1165    }
1166}
1167
1168impl SendSettlements for Vec<crate::Never> {
1169    type Settlements = Self;
1170
1171    fn unattempted(self) -> Self::Settlements {
1172        self
1173    }
1174}
1175
1176impl<Interpreter, RootEvent, Path> InterpretSends<Interpreter, RootEvent, Path>
1177    for Vec<crate::Never>
1178{
1179    fn interpret(
1180        self,
1181        _: &mut Interpreter,
1182    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1183        async move { Interpretation::Complete(self) }
1184    }
1185}
1186
1187impl<T> SendInput<T, Own> for Vec<T> {
1188    fn emit(&mut self, input: T) {
1189        self.push(input);
1190    }
1191}
1192
1193/// Requests interpreted by the runtime local to the emitting actor.
1194///
1195/// Unlike [`crate::Delivery`], a interpreter request has no actor address. Its
1196/// recipient is definitionally the interpreter of the actor whose transition
1197/// emitted it. This distinct send lane lets interpreters route ordinary
1198/// deliveries and interpreter requests with disjoint static implementations.
1199#[derive(Debug, Clone, PartialEq, Eq)]
1200pub struct InterpreterRequests<M> {
1201    requests: Vec<M>,
1202}
1203
1204impl<M> InterpreterRequests<M> {
1205    #[must_use]
1206    pub fn new(requests: Vec<M>) -> Self {
1207        Self { requests }
1208    }
1209    #[must_use]
1210    pub fn one(request: M) -> Self {
1211        Self::new(vec![request])
1212    }
1213    #[must_use]
1214    pub fn as_slice(&self) -> &[M] {
1215        &self.requests
1216    }
1217    pub fn iter(&self) -> core::slice::Iter<'_, M> {
1218        self.requests.iter()
1219    }
1220    #[must_use]
1221    pub fn len(&self) -> usize {
1222        self.requests.len()
1223    }
1224    #[must_use]
1225    pub fn is_empty(&self) -> bool {
1226        self.requests.is_empty()
1227    }
1228    pub fn extend(&mut self, requests: impl IntoIterator<Item = M>) {
1229        self.requests.extend(requests);
1230    }
1231    #[must_use]
1232    pub fn into_requests(self) -> Vec<M> {
1233        self.requests
1234    }
1235}
1236
1237impl<M> core::ops::Index<usize> for InterpreterRequests<M> {
1238    type Output = M;
1239    fn index(&self, index: usize) -> &Self::Output {
1240        &self.requests[index]
1241    }
1242}
1243
1244impl<M> IntoIterator for InterpreterRequests<M> {
1245    type Item = M;
1246    type IntoIter = std::vec::IntoIter<M>;
1247    fn into_iter(self) -> Self::IntoIter {
1248        self.requests.into_iter()
1249    }
1250}
1251
1252impl<'a, M> IntoIterator for &'a InterpreterRequests<M> {
1253    type Item = &'a M;
1254    type IntoIter = core::slice::Iter<'a, M>;
1255    fn into_iter(self) -> Self::IntoIter {
1256        self.requests.iter()
1257    }
1258}
1259
1260impl<M> SendEffects for InterpreterRequests<M> {
1261    fn empty() -> Self {
1262        Self::new(Vec::new())
1263    }
1264    fn append(&mut self, mut other: Self) {
1265        self.requests.append(&mut other.requests);
1266    }
1267}
1268
1269impl<M> LogicalDeliveryProtocols for InterpreterRequests<M> {
1270    type Protocols = NoBirthProtocols;
1271}
1272
1273impl<Event, M> SendsFor<Event> for InterpreterRequests<M>
1274where
1275    M: InterpreterRequest,
1276    M::ReturnToEmitter: ReturnToEmitterFor<Event>,
1277{
1278}
1279
1280impl<M> SendInput<M, Own> for InterpreterRequests<M> {
1281    fn emit(&mut self, input: M) {
1282        self.requests.push(input);
1283    }
1284}
1285
1286impl<Request> SendSettlements for InterpreterRequests<Request>
1287where
1288    Request: ActionItem,
1289{
1290    type Settlements = Vec<ActionItemResult<Request>>;
1291
1292    fn unattempted(self) -> Self::Settlements {
1293        unattempted_items(self.requests)
1294    }
1295}
1296
1297impl<Interpreter, RootEvent, Path, Request> InterpretSends<Interpreter, RootEvent, Path>
1298    for InterpreterRequests<Request>
1299where
1300    Interpreter: InterpretItem<Request, RootEvent, Path>,
1301    Request: ActionItem,
1302{
1303    fn interpret(
1304        self,
1305        interpreter: &mut Interpreter,
1306    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1307        interpret_items(self.requests, interpreter)
1308    }
1309}
1310
1311#[cfg(test)]
1312mod tests {
1313    use super::*;
1314
1315    #[test]
1316    fn send_accumulation_obeys_identity_and_associativity() {
1317        let values = vec![1, 2];
1318        assert_eq!(Vec::new().combine(values.clone()), values);
1319        assert_eq!(values.clone().combine(Vec::new()), values);
1320
1321        let left = vec![1].combine(vec![2]).combine(vec![3]);
1322        let right = vec![1].combine(vec![2].combine(vec![3]));
1323        assert_eq!(left, right);
1324    }
1325
1326    #[test]
1327    fn vector_and_service_lanes_emit_and_iterate_in_order() {
1328        assert!(<Vec<u8> as SendEffects>::empty().is_empty());
1329        let mut vector = Vec::new();
1330        <Vec<u8> as SendInput<u8, Own>>::emit(&mut vector, 1);
1331        assert_eq!(vector, [1]);
1332
1333        let mut services = InterpreterRequests::one(2);
1334        services.extend([4, 5]);
1335        <InterpreterRequests<u8> as SendInput<u8, Own>>::emit(&mut services, 3);
1336        assert!(!services.is_empty());
1337        assert_eq!(services.as_slice(), [2, 4, 5, 3]);
1338        assert_eq!(
1339            (&services).into_iter().copied().collect::<Vec<_>>(),
1340            [2, 4, 5, 3]
1341        );
1342        assert_eq!(services.into_iter().collect::<Vec<_>>(), [2, 4, 5, 3]);
1343
1344        let requests = InterpreterRequests::new(vec![4, 5]).into_requests();
1345        assert_eq!(requests, [4, 5]);
1346    }
1347
1348    #[test]
1349    fn source_and_interpreter_lanes_report_complete_ordered_contents() {
1350        let empty = <SourceActions<u8> as SendEffects>::empty();
1351        assert!(empty.is_empty());
1352        assert_eq!(empty.len(), 0);
1353
1354        let mut prefix = <SourceActions<u8> as SendEffects>::empty();
1355        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut prefix, 1);
1356        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut prefix, 2);
1357        let mut suffix = <SourceActions<u8> as SendEffects>::empty();
1358        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut suffix, 3);
1359        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut suffix, 4);
1360        prefix.append(suffix);
1361        assert!(!prefix.is_empty());
1362        assert_eq!(prefix.len(), 4);
1363        assert_eq!(prefix.into_items(), [1, 2, 3, 4]);
1364
1365        let requests = InterpreterRequests::new(vec![5, 6, 7]);
1366        assert_eq!(requests.len(), 3);
1367    }
1368
1369    struct Returning;
1370
1371    impl InterpreterRequest for Returning {
1372        type ReturnToEmitter = ReturnsToEmitter<u8, crate::Here>;
1373    }
1374
1375    fn lawful<Event, Effects: SendsFor<Event>>() {}
1376
1377    #[test]
1378    fn local_return_proofs_compose_through_exact_event_layers() {
1379        type Inner = crate::EventLayer<u8, crate::User<crate::MailAddr, ()>>;
1380        type Outer = crate::EventLayer<(), Inner>;
1381
1382        lawful::<Inner, InterpreterRequests<Returning>>();
1383        lawful::<Outer, SendLayer<NoSends, InterpreterRequests<Returning>>>();
1384    }
1385
1386    #[test]
1387    fn send_layer_emits_into_its_designated_owned_lane() {
1388        let mut effects = SendLayer::new(Vec::<u8>::new(), Vec::<u16>::new());
1389        <SendLayer<Vec<u8>, Vec<u16>> as SendInput<u8, Own>>::emit(&mut effects, 7);
1390        assert_eq!(effects.owned, [7]);
1391        assert!(effects.inner.is_empty());
1392    }
1393
1394    #[derive(Debug, PartialEq, Eq)]
1395    enum Seen {
1396        Inner(u8),
1397        Outer(u16),
1398    }
1399
1400    struct Trace(Vec<Seen>);
1401
1402    type TraceEvent =
1403        crate::EventLayer<u16, crate::EventLayer<u8, crate::User<crate::MailAddr, ()>>>;
1404
1405    impl ActionItem for u8 {
1406        type Accepted = ();
1407        type Rejection = crate::Never;
1408        type Prerequisite = crate::Never;
1409    }
1410
1411    impl ActionItem for u16 {
1412        type Accepted = ();
1413        type Rejection = crate::Never;
1414        type Prerequisite = crate::Never;
1415    }
1416
1417    impl InterpretItem<u8, TraceEvent, crate::Inside<crate::Here>> for Trace {
1418        fn interpret_item(
1419            &mut self,
1420            request: u8,
1421        ) -> impl Future<
1422            Output = ItemSettlement<
1423                u8,
1424                <u8 as ActionItem>::Accepted,
1425                <u8 as ActionItem>::Rejection,
1426                <u8 as ActionItem>::Prerequisite,
1427            >,
1428        > + Send {
1429            async move {
1430                self.0.push(Seen::Inner(request));
1431                ItemSettlement::Accepted(())
1432            }
1433        }
1434    }
1435
1436    impl InterpretItem<u16, TraceEvent, crate::Here> for Trace {
1437        fn interpret_item(
1438            &mut self,
1439            request: u16,
1440        ) -> impl Future<
1441            Output = ItemSettlement<
1442                u16,
1443                <u16 as ActionItem>::Accepted,
1444                <u16 as ActionItem>::Rejection,
1445                <u16 as ActionItem>::Prerequisite,
1446            >,
1447        > + Send {
1448            async move {
1449                self.0.push(Seen::Outer(request));
1450                ItemSettlement::Accepted(())
1451            }
1452        }
1453    }
1454
1455    #[tokio::test]
1456    async fn structural_interpretation_visits_every_lane_inner_to_outer() {
1457        let effects = SendLayer::new(
1458            InterpreterRequests::new(vec![3_u16, 5]),
1459            SendLayer::new(InterpreterRequests::one(2_u8), NoSends),
1460        );
1461        let mut trace = Trace(Vec::new());
1462
1463        <_ as InterpretSends<_, TraceEvent, crate::Here>>::interpret(effects, &mut trace).await;
1464
1465        assert_eq!(trace.0, [Seen::Inner(2), Seen::Outer(3), Seen::Outer(5)]);
1466    }
1467}