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    /// No live-source input remains, but exact terminal custody is required.
616    Retained(Residual),
617    /// Exactly one source input transferred; the residual remains in custody.
618    Admitted(Residual),
619    /// Admission closed; the residual contains the current and untouched suffix.
620    Closed(Residual),
621}
622
623impl<Residual> SourceCustody<Residual> {
624    /// Transform the complete residual without changing its custody state.
625    #[must_use]
626    pub fn map<Mapped>(self, map: impl FnOnce(Residual) -> Mapped) -> SourceCustody<Mapped> {
627        match self {
628            Self::Exhausted(residual) => SourceCustody::Exhausted(map(residual)),
629            Self::Retained(residual) => SourceCustody::Retained(map(residual)),
630            Self::Admitted(residual) => SourceCustody::Admitted(map(residual)),
631            Self::Closed(residual) => SourceCustody::Closed(map(residual)),
632        }
633    }
634}
635
636/// Static one-at-a-time source admission for one complete settlement product.
637pub trait SourceSettlementCustody<Host, RootEvent>: Sized {
638    /// Offer only the next source input in declared order.
639    fn offer_next_to_source(
640        self,
641        host: &mut Host,
642    ) -> impl Future<Output = SourceCustody<Self>> + Send;
643}
644
645/// Offer one source input from two settlement products in declared order.
646///
647/// The later product is untouched unless the earlier product is exhausted.
648/// Even when the earlier product admits an input, this operation returns so
649/// the actor loop can process that input and its transitive effects first.
650pub(super) async fn offer_source_in_order<Host, RootEvent, Earlier, Later>(
651    earlier: Earlier,
652    later: Later,
653    host: &mut Host,
654) -> SourceCustody<(Earlier, Later)>
655where
656    Host: Send,
657    Earlier: SourceSettlementCustody<Host, RootEvent> + Send,
658    Later: SourceSettlementCustody<Host, RootEvent> + Send,
659{
660    match earlier.offer_next_to_source(host).await {
661        SourceCustody::Exhausted(earlier) => later
662            .offer_next_to_source(host)
663            .await
664            .map(|later| (earlier, later)),
665        SourceCustody::Retained(earlier) => match later.offer_next_to_source(host).await {
666            SourceCustody::Exhausted(later) | SourceCustody::Retained(later) => {
667                SourceCustody::Retained((earlier, later))
668            }
669            SourceCustody::Admitted(later) => SourceCustody::Admitted((earlier, later)),
670            SourceCustody::Closed(later) => SourceCustody::Closed((earlier, later)),
671        },
672        SourceCustody::Admitted(earlier) => SourceCustody::Admitted((earlier, later)),
673        SourceCustody::Closed(earlier) => SourceCustody::Closed((earlier, later)),
674    }
675}
676
677impl<Host, RootEvent, Earlier, Later> SourceSettlementCustody<Host, RootEvent> for (Earlier, Later)
678where
679    Host: Send,
680    Earlier: SourceSettlementCustody<Host, RootEvent> + Send,
681    Later: SourceSettlementCustody<Host, RootEvent> + Send,
682{
683    fn offer_next_to_source(
684        self,
685        host: &mut Host,
686    ) -> impl Future<Output = SourceCustody<Self>> + Send {
687        offer_source_in_order(self.0, self.1, host)
688    }
689}
690
691impl<Host, RootEvent, Item> SourceSettlementCustody<Host, RootEvent> for SourceSettlements<Item>
692where
693    Host: SourceAdmission<RootEvent, Item::Source, ActionItemResult<Item>>,
694    RootEvent: crate::EventIngress<Item::Source, ActionItemResult<Item>>,
695    Item: SourceAction,
696{
697    fn offer_next_to_source(
698        self,
699        host: &mut Host,
700    ) -> impl Future<Output = SourceCustody<Self>> + Send {
701        async move {
702            let mut source_inputs = self.inputs.into_iter();
703            let Some(input) = source_inputs.next() else {
704                return SourceCustody::Exhausted(Self::new(Vec::new()));
705            };
706            match host.admit_source(input).await {
707                Ok(()) => SourceCustody::Admitted(Self::new(source_inputs.collect())),
708                Err(input) => {
709                    let mut residual = Vec::with_capacity(source_inputs.len() + 1);
710                    residual.push(input);
711                    residual.extend(source_inputs);
712                    SourceCustody::Closed(Self::new(residual))
713                }
714            }
715        }
716    }
717}
718
719impl<Host, RootEvent> SourceSettlementCustody<Host, RootEvent> for NoSends {
720    fn offer_next_to_source(
721        self,
722        _: &mut Host,
723    ) -> impl Future<Output = SourceCustody<Self>> + Send {
724        async move { SourceCustody::Exhausted(self) }
725    }
726}
727
728impl<Host, RootEvent, Item> SourceSettlementCustody<Host, RootEvent> for Vec<ActionItemResult<Item>>
729where
730    Item: ActionItem,
731{
732    fn offer_next_to_source(
733        self,
734        _: &mut Host,
735    ) -> impl Future<Output = SourceCustody<Self>> + Send {
736        async move { SourceCustody::Exhausted(self) }
737    }
738}
739
740impl<Host, RootEvent> SourceSettlementCustody<Host, RootEvent> for Vec<crate::Never> {
741    fn offer_next_to_source(
742        self,
743        _: &mut Host,
744    ) -> impl Future<Output = SourceCustody<Self>> + Send {
745        async move { SourceCustody::Exhausted(self) }
746    }
747}
748
749impl<Host, RootEvent, Owned, Inner> SourceSettlementCustody<Host, RootEvent>
750    for SendLayer<Owned, Inner>
751where
752    Host: Send,
753    Owned: SourceSettlementCustody<Host, RootEvent> + Send,
754    Inner: SourceSettlementCustody<Host, RootEvent> + Send,
755{
756    fn offer_next_to_source(
757        self,
758        host: &mut Host,
759    ) -> impl Future<Output = SourceCustody<Self>> + Send {
760        async move {
761            offer_source_in_order(self.inner, self.owned, host)
762                .await
763                .map(|(inner, owned)| SendLayer::new(owned, inner))
764        }
765    }
766}
767
768/// An interpreter request that produces no later fact for the emitting actor.
769pub enum NoReturnToEmitter {}
770
771/// An interpreter request whose later `Input` returns to the emitting actor at
772/// `Path`, relative to the effect lane that owns the request.
773pub struct ReturnsToEmitter<Input, Path>(core::marker::PhantomData<fn(Input, Path)>);
774
775/// Local-return contract declared by one interpreter-facing request.
776pub trait ReturnToEmitterFor<Event> {}
777
778impl<Event> ReturnToEmitterFor<Event> for NoReturnToEmitter {}
779
780impl<Event, Input, Path> ReturnToEmitterFor<Event> for ReturnsToEmitter<Input, Path> where
781    Event: InjectEvent<Input, Path>
782{
783}
784
785/// Declares only the continuation returning to the actor that emitted this
786/// interpreter request. Destinations owned by a child, parent, ancestor, or
787/// established actor are separate capabilities and are not reindexed when the
788/// emitter is wrapped.
789pub trait InterpreterRequest {
790    type ReturnToEmitter;
791}
792
793/// Transfer one owned report to the emitter's established parent.
794///
795/// The request is an ordinary typed send effect. Its interpreter uses the
796/// already-established creator/child relationship, attaches the emitter's
797/// exact creator-local nonce, and injects a [`crate::ChildReport`] into the
798/// parent's closed event algebra. It performs no address or protocol lookup.
799/// A root behavior has no parent capability and therefore cannot interpret
800/// this request.
801#[derive(Debug, Clone, Copy, PartialEq, Eq)]
802pub struct ReportToParent<R> {
803    /// Complete report value transferred to the parent.
804    pub report: R,
805}
806
807impl<R> ReportToParent<R> {
808    /// Construct one structural parent report.
809    #[must_use]
810    pub const fn new(report: R) -> Self {
811        Self { report }
812    }
813
814    /// Recover ownership of the complete report value.
815    #[must_use]
816    pub fn into_inner(self) -> R {
817        self.report
818    }
819}
820
821impl<R> InterpreterRequest for ReportToParent<R> {
822    type ReturnToEmitter = NoReturnToEmitter;
823}
824
825impl<R> ActionItem for ReportToParent<R>
826where
827    R: Send,
828{
829    type Accepted = ();
830    type Rejection = ParentReportReason;
831    type Prerequisite = crate::Never;
832}
833
834/// Send effects containing no communications or interpreter requests.
835///
836/// A behavior layer that adds an event lane but emits nothing of its own uses
837/// this named value rather than an ambiguous `()`.
838#[derive(Debug, Clone, Copy, PartialEq, Eq)]
839pub struct NoSends;
840
841impl SendEffects for NoSends {
842    fn empty() -> Self {
843        Self
844    }
845
846    fn append(&mut self, _: Self) {}
847}
848
849impl LogicalDeliveryProtocols for NoSends {
850    type Protocols = NoBirthProtocols;
851}
852
853impl<Event> SendsFor<Event> for NoSends {}
854
855impl SendSettlements for NoSends {
856    type Settlements = Self;
857
858    fn unattempted(self) -> Self::Settlements {
859        self
860    }
861}
862
863impl ClassifySettlement for NoSends {
864    fn settlement_status(&self) -> SettlementStatus {
865        SettlementStatus::Accepted
866    }
867}
868
869impl<Interpreter, RootEvent, Path> InterpretSends<Interpreter, RootEvent, Path> for NoSends {
870    fn interpret(
871        self,
872        _: &mut Interpreter,
873    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
874        async move { Interpretation::Complete(self) }
875    }
876}
877
878/// Send effects introduced by one wrapper around inner send effects.
879///
880/// `owned` contains effects introduced by the current behavior layer and
881/// `inner` contains effects of the wrapped interaction. The structural
882/// [`SendsFor`] implementation is the composition law:
883///
884/// ```text
885/// Event'   = OwnedEvent + InnerEvent
886/// Effects' = OwnedEffects × InnerEffects
887/// ```
888///
889/// Owned return to the emitters target `Event'`; inner return to the emitters target
890/// `InnerEvent` and are therefore lifted through the same `Inner` injection.
891/// Established actor, child, and ancestor destinations are unaffected because
892/// they are not return to the emitters.
893#[derive(Debug, Clone, Copy, PartialEq, Eq)]
894pub struct SendLayer<Owned, Inner> {
895    pub owned: Owned,
896    pub inner: Inner,
897}
898
899impl<Owned, Inner> SendLayer<Owned, Inner> {
900    #[must_use]
901    pub const fn new(owned: Owned, inner: Inner) -> Self {
902        Self { owned, inner }
903    }
904}
905
906impl<Owned: SendEffects, Inner: SendEffects> SendEffects for SendLayer<Owned, Inner> {
907    fn empty() -> Self {
908        Self::new(Owned::empty(), Inner::empty())
909    }
910
911    fn append(&mut self, other: Self) {
912        self.owned.append(other.owned);
913        self.inner.append(other.inner);
914    }
915}
916
917impl<Owned, Inner> LogicalDeliveryProtocols for SendLayer<Owned, Inner>
918where
919    Owned: LogicalDeliveryProtocols,
920    Inner: LogicalDeliveryProtocols,
921{
922    // Interpretation preserves authored inner-to-outer wrapper order.
923    type Protocols = <Inner::Protocols as BirthProtocolProduct>::Append<Owned::Protocols>;
924}
925
926impl<Event, OwnedEffects, InnerEffects> SendsFor<Event> for SendLayer<OwnedEffects, InnerEffects>
927where
928    Event: ComposedEvent,
929    OwnedEffects: SendsFor<Event>,
930    InnerEffects: SendsFor<Event::Inner>,
931{
932}
933
934impl<Owned, Inner> SendSettlements for SendLayer<Owned, Inner>
935where
936    Owned: SendSettlements,
937    Inner: SendSettlements,
938{
939    type Settlements = SendLayer<Owned::Settlements, Inner::Settlements>;
940
941    fn unattempted(self) -> Self::Settlements {
942        SendLayer::new(self.owned.unattempted(), self.inner.unattempted())
943    }
944}
945
946impl<Owned, Inner> ClassifySettlement for SendLayer<Owned, Inner>
947where
948    Owned: ClassifySettlement,
949    Inner: ClassifySettlement,
950{
951    fn settlement_status(&self) -> SettlementStatus {
952        self.inner
953            .settlement_status()
954            .combine(self.owned.settlement_status())
955    }
956}
957
958impl<Input, Path, Owned, Inner> SendInput<Input, Path> for SendLayer<Owned, Inner>
959where
960    Owned: SendInput<Input, Path>,
961{
962    fn emit(&mut self, input: Input) {
963        self.owned.emit(input);
964    }
965}
966
967impl<Interpreter, RootEvent, Path, Owned, Inner> InterpretSends<Interpreter, RootEvent, Path>
968    for SendLayer<Owned, Inner>
969where
970    Interpreter: Send,
971    Owned: InterpretSends<Interpreter, RootEvent, Path> + Send,
972    Inner: InterpretSends<Interpreter, RootEvent, Inside<Path>> + Send,
973{
974    fn interpret(
975        self,
976        interpreter: &mut Interpreter,
977    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
978        async move {
979            let inner = <Inner as InterpretSends<Interpreter, RootEvent, Inside<Path>>>::interpret(
980                self.inner,
981                interpreter,
982            )
983            .await;
984            let inner = match inner {
985                Interpretation::Complete(inner) => inner,
986                Interpretation::Corrupt(inner) => {
987                    return Interpretation::Corrupt(SendLayer::new(
988                        self.owned.unattempted(),
989                        inner,
990                    ));
991                }
992            };
993            match <Owned as InterpretSends<Interpreter, RootEvent, Path>>::interpret(
994                self.owned,
995                interpreter,
996            )
997            .await
998            {
999                Interpretation::Complete(owned) => {
1000                    Interpretation::Complete(SendLayer::new(owned, inner))
1001                }
1002                Interpretation::Corrupt(owned) => {
1003                    Interpretation::Corrupt(SendLayer::new(owned, inner))
1004                }
1005            }
1006        }
1007    }
1008}
1009
1010impl<T> SendEffects for Vec<T> {
1011    fn empty() -> Self {
1012        Vec::new()
1013    }
1014
1015    fn append(&mut self, mut other: Self) {
1016        Vec::append(self, &mut other);
1017    }
1018}
1019
1020impl<P: Protocol> LogicalDeliveryProtocols for Vec<Delivery<P>> {
1021    type Protocols = BirthProtocol<P, NoBirthProtocols>;
1022}
1023
1024impl<P: Protocol, Occurrence> LogicalDeliveryProtocols for Vec<ChildDelivery<P, Occurrence>> {
1025    type Protocols = NoBirthProtocols;
1026}
1027
1028impl<Child, Source, Input, Occurrence> LogicalDeliveryProtocols
1029    for Vec<ChildInput<Child, Source, Input, Occurrence>>
1030where
1031    Child: Behavior,
1032{
1033    type Protocols = NoBirthProtocols;
1034}
1035
1036impl<P> LogicalDeliveryProtocols for Vec<EstablishedDelivery<P>>
1037where
1038    P: Protocol,
1039    P::Addr: EndpointAddress,
1040{
1041    type Protocols = NoBirthProtocols;
1042}
1043
1044impl LogicalDeliveryProtocols for Vec<crate::Never> {
1045    type Protocols = NoBirthProtocols;
1046}
1047
1048impl<Event, T> SendsFor<Event> for Vec<T> {}
1049
1050impl<Item> SendSettlements for Vec<Item>
1051where
1052    Item: ActionItem,
1053{
1054    type Settlements = Vec<ActionItemResult<Item>>;
1055
1056    fn unattempted(self) -> Self::Settlements {
1057        unattempted_items(self)
1058    }
1059}
1060
1061/// Interpret exactly one item and attach its product-owned attempt evidence.
1062///
1063/// This is the indivisible form of [`InterpretSends`]. It marks the enclosing
1064/// interpretation corrupt exactly when the concrete item result is corrupt;
1065/// lawful rejection and blocking remain complete outcomes.
1066pub async fn settle_item<Item, Interpreter, RootEvent, Path>(
1067    item: Item,
1068    interpreter: &mut Interpreter,
1069) -> Interpretation<ActionItemResult<Item>>
1070where
1071    Item: ActionItem,
1072    Interpreter: InterpretItem<Item, RootEvent, Path>,
1073{
1074    let settlement =
1075        <Interpreter as InterpretItem<Item, RootEvent, Path>>::interpret_item(interpreter, item)
1076            .await;
1077    match settlement {
1078        corrupt @ ItemSettlement::Corrupt { .. } => {
1079            Interpretation::Corrupt(SettledItem::Attempted(corrupt))
1080        }
1081        settled => Interpretation::Complete(SettledItem::Attempted(settled)),
1082    }
1083}
1084
1085async fn interpret_items<Item, Interpreter, RootEvent, Path>(
1086    items: Vec<Item>,
1087    interpreter: &mut Interpreter,
1088) -> Interpretation<Vec<ActionItemResult<Item>>>
1089where
1090    Item: ActionItem,
1091    Interpreter: InterpretItem<Item, RootEvent, Path>,
1092{
1093    let mut items = items.into_iter();
1094    let mut settlements = Vec::with_capacity(items.len());
1095    while let Some(item) = items.next() {
1096        match settle_item::<Item, Interpreter, RootEvent, Path>(item, interpreter).await {
1097            Interpretation::Complete(settlement) => settlements.push(settlement),
1098            Interpretation::Corrupt(settlement) => {
1099                settlements.push(settlement);
1100                settlements.extend(items.map(SettledItem::Unattempted));
1101                return Interpretation::Corrupt(settlements);
1102            }
1103        }
1104    }
1105    Interpretation::Complete(settlements)
1106}
1107
1108fn unattempted_items<Item>(items: Vec<Item>) -> Vec<ActionItemResult<Item>>
1109where
1110    Item: ActionItem,
1111{
1112    items.into_iter().map(SettledItem::Unattempted).collect()
1113}
1114
1115impl<Interpreter, RootEvent, Path, P> InterpretSends<Interpreter, RootEvent, Path>
1116    for Vec<Delivery<P>>
1117where
1118    Interpreter: InterpretItem<Delivery<P>, RootEvent, Path>,
1119    P: Protocol,
1120    Delivery<P>: ActionItem,
1121{
1122    fn interpret(
1123        self,
1124        interpreter: &mut Interpreter,
1125    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1126        interpret_items(self, interpreter)
1127    }
1128}
1129
1130impl<Interpreter, RootEvent, Path, P, Occurrence> InterpretSends<Interpreter, RootEvent, Path>
1131    for Vec<ChildDelivery<P, Occurrence>>
1132where
1133    Interpreter: InterpretItem<ChildDelivery<P, Occurrence>, RootEvent, Path>,
1134    P: Protocol,
1135    ChildDelivery<P, Occurrence>: ActionItem,
1136{
1137    fn interpret(
1138        self,
1139        interpreter: &mut Interpreter,
1140    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1141        interpret_items(self, interpreter)
1142    }
1143}
1144
1145impl<Interpreter, RootEvent, Path, Child, Source, Input, Occurrence>
1146    InterpretSends<Interpreter, RootEvent, Path>
1147    for Vec<ChildInput<Child, Source, Input, Occurrence>>
1148where
1149    Interpreter: InterpretItem<ChildInput<Child, Source, Input, Occurrence>, RootEvent, Path>,
1150    Child: Behavior,
1151    Child::Event: crate::ChildInputIngress<Source, Input>,
1152    ChildInput<Child, Source, Input, Occurrence>: ActionItem,
1153{
1154    fn interpret(
1155        self,
1156        interpreter: &mut Interpreter,
1157    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1158        interpret_items(self, interpreter)
1159    }
1160}
1161
1162impl<Interpreter, RootEvent, Path, P> InterpretSends<Interpreter, RootEvent, Path>
1163    for Vec<EstablishedDelivery<P>>
1164where
1165    Interpreter: InterpretItem<EstablishedDelivery<P>, RootEvent, Path>,
1166    P: Protocol,
1167    P::Addr: EndpointAddress,
1168    EstablishedDelivery<P>: ActionItem,
1169{
1170    fn interpret(
1171        self,
1172        interpreter: &mut Interpreter,
1173    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1174        interpret_items(self, interpreter)
1175    }
1176}
1177
1178impl SendSettlements for Vec<crate::Never> {
1179    type Settlements = Self;
1180
1181    fn unattempted(self) -> Self::Settlements {
1182        self
1183    }
1184}
1185
1186impl<Interpreter, RootEvent, Path> InterpretSends<Interpreter, RootEvent, Path>
1187    for Vec<crate::Never>
1188{
1189    fn interpret(
1190        self,
1191        _: &mut Interpreter,
1192    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1193        async move { Interpretation::Complete(self) }
1194    }
1195}
1196
1197impl<T> SendInput<T, Own> for Vec<T> {
1198    fn emit(&mut self, input: T) {
1199        self.push(input);
1200    }
1201}
1202
1203/// Requests interpreted by the runtime local to the emitting actor.
1204///
1205/// Unlike [`crate::Delivery`], a interpreter request has no actor address. Its
1206/// recipient is definitionally the interpreter of the actor whose transition
1207/// emitted it. This distinct send lane lets interpreters route ordinary
1208/// deliveries and interpreter requests with disjoint static implementations.
1209#[derive(Debug, Clone, PartialEq, Eq)]
1210pub struct InterpreterRequests<M> {
1211    requests: Vec<M>,
1212}
1213
1214impl<M> InterpreterRequests<M> {
1215    #[must_use]
1216    pub fn new(requests: Vec<M>) -> Self {
1217        Self { requests }
1218    }
1219    #[must_use]
1220    pub fn one(request: M) -> Self {
1221        Self::new(vec![request])
1222    }
1223    #[must_use]
1224    pub fn as_slice(&self) -> &[M] {
1225        &self.requests
1226    }
1227    pub fn iter(&self) -> core::slice::Iter<'_, M> {
1228        self.requests.iter()
1229    }
1230    #[must_use]
1231    pub fn len(&self) -> usize {
1232        self.requests.len()
1233    }
1234    #[must_use]
1235    pub fn is_empty(&self) -> bool {
1236        self.requests.is_empty()
1237    }
1238    pub fn extend(&mut self, requests: impl IntoIterator<Item = M>) {
1239        self.requests.extend(requests);
1240    }
1241    #[must_use]
1242    pub fn into_requests(self) -> Vec<M> {
1243        self.requests
1244    }
1245}
1246
1247impl<M> core::ops::Index<usize> for InterpreterRequests<M> {
1248    type Output = M;
1249    fn index(&self, index: usize) -> &Self::Output {
1250        &self.requests[index]
1251    }
1252}
1253
1254impl<M> IntoIterator for InterpreterRequests<M> {
1255    type Item = M;
1256    type IntoIter = std::vec::IntoIter<M>;
1257    fn into_iter(self) -> Self::IntoIter {
1258        self.requests.into_iter()
1259    }
1260}
1261
1262impl<'a, M> IntoIterator for &'a InterpreterRequests<M> {
1263    type Item = &'a M;
1264    type IntoIter = core::slice::Iter<'a, M>;
1265    fn into_iter(self) -> Self::IntoIter {
1266        self.requests.iter()
1267    }
1268}
1269
1270impl<M> SendEffects for InterpreterRequests<M> {
1271    fn empty() -> Self {
1272        Self::new(Vec::new())
1273    }
1274    fn append(&mut self, mut other: Self) {
1275        self.requests.append(&mut other.requests);
1276    }
1277}
1278
1279impl<M> LogicalDeliveryProtocols for InterpreterRequests<M> {
1280    type Protocols = NoBirthProtocols;
1281}
1282
1283impl<Event, M> SendsFor<Event> for InterpreterRequests<M>
1284where
1285    M: InterpreterRequest,
1286    M::ReturnToEmitter: ReturnToEmitterFor<Event>,
1287{
1288}
1289
1290impl<M> SendInput<M, Own> for InterpreterRequests<M> {
1291    fn emit(&mut self, input: M) {
1292        self.requests.push(input);
1293    }
1294}
1295
1296impl<Request> SendSettlements for InterpreterRequests<Request>
1297where
1298    Request: ActionItem,
1299{
1300    type Settlements = Vec<ActionItemResult<Request>>;
1301
1302    fn unattempted(self) -> Self::Settlements {
1303        unattempted_items(self.requests)
1304    }
1305}
1306
1307impl<Interpreter, RootEvent, Path, Request> InterpretSends<Interpreter, RootEvent, Path>
1308    for InterpreterRequests<Request>
1309where
1310    Interpreter: InterpretItem<Request, RootEvent, Path>,
1311    Request: ActionItem,
1312{
1313    fn interpret(
1314        self,
1315        interpreter: &mut Interpreter,
1316    ) -> impl Future<Output = Interpretation<Self::Settlements>> + Send {
1317        interpret_items(self.requests, interpreter)
1318    }
1319}
1320
1321#[cfg(test)]
1322mod tests {
1323    use super::*;
1324
1325    #[test]
1326    fn send_accumulation_obeys_identity_and_associativity() {
1327        let values = vec![1, 2];
1328        assert_eq!(Vec::new().combine(values.clone()), values);
1329        assert_eq!(values.clone().combine(Vec::new()), values);
1330
1331        let left = vec![1].combine(vec![2]).combine(vec![3]);
1332        let right = vec![1].combine(vec![2].combine(vec![3]));
1333        assert_eq!(left, right);
1334    }
1335
1336    #[test]
1337    fn vector_and_service_lanes_emit_and_iterate_in_order() {
1338        assert!(<Vec<u8> as SendEffects>::empty().is_empty());
1339        let mut vector = Vec::new();
1340        <Vec<u8> as SendInput<u8, Own>>::emit(&mut vector, 1);
1341        assert_eq!(vector, [1]);
1342
1343        let mut services = InterpreterRequests::one(2);
1344        services.extend([4, 5]);
1345        <InterpreterRequests<u8> as SendInput<u8, Own>>::emit(&mut services, 3);
1346        assert!(!services.is_empty());
1347        assert_eq!(services.as_slice(), [2, 4, 5, 3]);
1348        assert_eq!(
1349            (&services).into_iter().copied().collect::<Vec<_>>(),
1350            [2, 4, 5, 3]
1351        );
1352        assert_eq!(services.into_iter().collect::<Vec<_>>(), [2, 4, 5, 3]);
1353
1354        let requests = InterpreterRequests::new(vec![4, 5]).into_requests();
1355        assert_eq!(requests, [4, 5]);
1356    }
1357
1358    #[test]
1359    fn source_and_interpreter_lanes_report_complete_ordered_contents() {
1360        let empty = <SourceActions<u8> as SendEffects>::empty();
1361        assert!(empty.is_empty());
1362        assert_eq!(empty.len(), 0);
1363
1364        let mut prefix = <SourceActions<u8> as SendEffects>::empty();
1365        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut prefix, 1);
1366        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut prefix, 2);
1367        let mut suffix = <SourceActions<u8> as SendEffects>::empty();
1368        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut suffix, 3);
1369        <SourceActions<u8> as SendInput<u8, Own>>::emit(&mut suffix, 4);
1370        prefix.append(suffix);
1371        assert!(!prefix.is_empty());
1372        assert_eq!(prefix.len(), 4);
1373        assert_eq!(prefix.into_items(), [1, 2, 3, 4]);
1374
1375        let requests = InterpreterRequests::new(vec![5, 6, 7]);
1376        assert_eq!(requests.len(), 3);
1377    }
1378
1379    struct Returning;
1380
1381    impl InterpreterRequest for Returning {
1382        type ReturnToEmitter = ReturnsToEmitter<u8, crate::Here>;
1383    }
1384
1385    fn lawful<Event, Effects: SendsFor<Event>>() {}
1386
1387    #[test]
1388    fn local_return_proofs_compose_through_exact_event_layers() {
1389        type Inner = crate::EventLayer<u8, crate::User<crate::MailAddr, ()>>;
1390        type Outer = crate::EventLayer<(), Inner>;
1391
1392        lawful::<Inner, InterpreterRequests<Returning>>();
1393        lawful::<Outer, SendLayer<NoSends, InterpreterRequests<Returning>>>();
1394    }
1395
1396    #[test]
1397    fn send_layer_emits_into_its_designated_owned_lane() {
1398        let mut effects = SendLayer::new(Vec::<u8>::new(), Vec::<u16>::new());
1399        <SendLayer<Vec<u8>, Vec<u16>> as SendInput<u8, Own>>::emit(&mut effects, 7);
1400        assert_eq!(effects.owned, [7]);
1401        assert!(effects.inner.is_empty());
1402    }
1403
1404    #[derive(Debug, PartialEq, Eq)]
1405    enum Seen {
1406        Inner(u8),
1407        Outer(u16),
1408    }
1409
1410    struct Trace(Vec<Seen>);
1411
1412    type TraceEvent =
1413        crate::EventLayer<u16, crate::EventLayer<u8, crate::User<crate::MailAddr, ()>>>;
1414
1415    impl ActionItem for u8 {
1416        type Accepted = ();
1417        type Rejection = crate::Never;
1418        type Prerequisite = crate::Never;
1419    }
1420
1421    impl ActionItem for u16 {
1422        type Accepted = ();
1423        type Rejection = crate::Never;
1424        type Prerequisite = crate::Never;
1425    }
1426
1427    impl InterpretItem<u8, TraceEvent, crate::Inside<crate::Here>> for Trace {
1428        fn interpret_item(
1429            &mut self,
1430            request: u8,
1431        ) -> impl Future<
1432            Output = ItemSettlement<
1433                u8,
1434                <u8 as ActionItem>::Accepted,
1435                <u8 as ActionItem>::Rejection,
1436                <u8 as ActionItem>::Prerequisite,
1437            >,
1438        > + Send {
1439            async move {
1440                self.0.push(Seen::Inner(request));
1441                ItemSettlement::Accepted(())
1442            }
1443        }
1444    }
1445
1446    impl InterpretItem<u16, TraceEvent, crate::Here> for Trace {
1447        fn interpret_item(
1448            &mut self,
1449            request: u16,
1450        ) -> impl Future<
1451            Output = ItemSettlement<
1452                u16,
1453                <u16 as ActionItem>::Accepted,
1454                <u16 as ActionItem>::Rejection,
1455                <u16 as ActionItem>::Prerequisite,
1456            >,
1457        > + Send {
1458            async move {
1459                self.0.push(Seen::Outer(request));
1460                ItemSettlement::Accepted(())
1461            }
1462        }
1463    }
1464
1465    #[tokio::test]
1466    async fn structural_interpretation_visits_every_lane_inner_to_outer() {
1467        let effects = SendLayer::new(
1468            InterpreterRequests::new(vec![3_u16, 5]),
1469            SendLayer::new(InterpreterRequests::one(2_u8), NoSends),
1470        );
1471        let mut trace = Trace(Vec::new());
1472
1473        <_ as InterpretSends<_, TraceEvent, crate::Here>>::interpret(effects, &mut trace).await;
1474
1475        assert_eq!(trace.0, [Seen::Inner(2), Seen::Outer(3), Seen::Outer(5)]);
1476    }
1477}