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