Skip to main content

behavior/effects/
sending.rs

1//! Typed send effects, their composition contract, and event ownership.
2
3use crate::{ComposedEvent, Delivery, InjectEvent, Inside, Protocol};
4use core::future::Future;
5
6/// Error domain shared by one concrete effect interpreter.
7pub trait SendInterpreter: Send {
8    type Error;
9}
10
11/// Static interpretation of one complete sends value at an absolute event path.
12///
13/// Implementations are monomorphized over `Interpreter`; there is no erased
14/// envelope, runtime lane lookup, or downcast. `RootEvent` is the event type
15/// ultimately enqueued for the actor and `Path` is the current send owner's
16/// absolute position in it. Composite products must visit every constituent
17/// lane exactly once without discarding either index.
18pub trait InterpretSends<Interpreter: SendInterpreter, RootEvent, Path>: Sized + Send {
19    /// Interpret every value in this product in its defined structural order.
20    /// The returned future completes each effect before beginning the next, so
21    /// an asynchronous delivery can wait for bounded-mailbox capacity without
22    /// reordering later effects or converting pressure into rejection.
23    ///
24    /// # Errors
25    /// Returns the interpreter's concrete error without consuming later lanes.
26    fn interpret(
27        self,
28        interpreter: &mut Interpreter,
29    ) -> impl Future<Output = Result<(), Interpreter::Error>> + Send;
30}
31
32/// Interpreter capability for one request at one exact root-event path.
33pub trait InterpretRequest<Request, RootEvent, Path>: SendInterpreter {
34    /// Interpret one request emitted by the actor hosted by this interpreter.
35    /// The returned future remains concrete and may await runtime capacity or
36    /// other interpreter-owned asynchronous work.
37    /// A returning implementation can require
38    /// `RootEvent: InjectEvent<ReturnedFact, Path>` and retain that exact
39    /// constructor for later completion.
40    ///
41    /// # Errors
42    /// Returns this interpreter's concrete request failure.
43    fn interpret_request(
44        &mut self,
45        request: Request,
46    ) -> impl Future<Output = Result<(), Self::Error>> + Send;
47}
48
49/// Interpreter capability for deliveries to one concrete actor protocol.
50///
51/// `P` is preserved unchanged from [`Delivery<P>`] and is the destination's
52/// canonical hosting identity. A creator-local child route changes only how
53/// the address is resolved; it does not introduce a role-keyed delivery lane.
54pub trait InterpretDelivery<P: Protocol>: SendInterpreter {
55    /// Interpret one typed delivery, awaiting bounded-mailbox capacity when
56    /// required by the concrete communication transport.
57    ///
58    /// # Errors
59    /// Returns this interpreter's concrete delivery failure.
60    fn interpret_delivery(
61        &mut self,
62        delivery: Delivery<P>,
63    ) -> impl Future<Output = Result<(), Self::Error>> + Send;
64}
65
66/// The lane owned by the current named send product.
67pub enum Own {}
68
69/// Static evidence that a sends type contains one request lane.
70///
71/// Implementations append the input exactly once to that lane and leave every
72/// other lane unchanged. `Path` distinguishes repeated request types without
73/// erasing their position or choosing a lane at runtime.
74///
75/// [`Own`] selects a named product's own semantic lane. [`SendLayer`] carries
76/// wrapper-owned and inner effects as explicit named fields; request routing
77/// remains a compile-time proof rather than a runtime lane lookup.
78pub trait SendInput<Input, Path> {
79    fn emit(&mut self, input: Input);
80}
81
82/// Send effects emitted by a pure actor transition.
83///
84/// Values compose without interpreting them. This keeps communications and
85/// interpreter requests inside the explicit [`crate::Actions`] boundary.
86pub trait SendEffects: Sized {
87    fn empty() -> Self;
88    fn append(&mut self, other: Self);
89
90    #[must_use]
91    fn combine(mut self, other: Self) -> Self {
92        self.append(other);
93        self
94    }
95
96    /// Append one request to its statically selected semantic lane.
97    fn send<Input, Path>(&mut self, input: Input)
98    where
99        Self: SendInput<Input, Path>,
100    {
101        <Self as SendInput<Input, Path>>::emit(self, input);
102    }
103
104    /// Build a send product containing one request in its selected lane.
105    #[must_use]
106    fn sending<Input, Path>(input: Input) -> Self
107    where
108        Self: SendInput<Input, Path>,
109    {
110        let mut sends = Self::empty();
111        sends.send(input);
112        sends
113    }
114}
115
116/// Proof that send effects are lawful for one complete event type.
117///
118/// Ordinary communications are independent of `Event`. Interpreter requests
119/// that return a local fact are not: their continuation must select an exact
120/// member of `Event`. Composite products implement this trait structurally,
121/// reindexing only their wrapped behavior effects through an outer event
122/// injection.
123///
124/// An un-reindexed return to the emitter cannot be paired with an added outer event
125/// layer:
126///
127/// ```compile_fail
128/// use behavior::{SendsFor, EventLayer, Here, MailAddr, ReturnsToEmitter,
129///     InterpreterRequest, InterpreterRequests, User};
130/// struct Request;
131/// impl InterpreterRequest for Request {
132///     type ReturnToEmitter = ReturnsToEmitter<u8, Here>;
133/// }
134/// fn lawful<E, F: SendsFor<E>>() {}
135/// type Inner = EventLayer<u8, User<MailAddr, ()>>;
136/// type Outer = EventLayer<(), Inner>;
137/// lawful::<Outer, InterpreterRequests<Request>>();
138/// ```
139pub trait SendsFor<Event>: SendEffects {}
140
141/// An interpreter request that produces no later fact for the emitting actor.
142pub enum NoReturnToEmitter {}
143
144/// An interpreter request whose later `Input` returns to the emitting actor at
145/// `Path`, relative to the effect lane that owns the request.
146pub struct ReturnsToEmitter<Input, Path>(core::marker::PhantomData<fn(Input, Path)>);
147
148/// Local-return contract declared by one interpreter-facing request.
149pub trait ReturnToEmitterFor<Event> {}
150
151impl<Event> ReturnToEmitterFor<Event> for NoReturnToEmitter {}
152
153impl<Event, Input, Path> ReturnToEmitterFor<Event> for ReturnsToEmitter<Input, Path> where
154    Event: InjectEvent<Input, Path>
155{
156}
157
158/// Declares only the continuation returning to the actor that emitted this
159/// interpreter request. Destinations owned by a child, parent, ancestor, or
160/// established actor are separate capabilities and are not reindexed when the
161/// emitter is wrapped.
162pub trait InterpreterRequest {
163    type ReturnToEmitter;
164}
165
166/// Send effects containing no communications or interpreter requests.
167///
168/// A behavior layer that adds an event lane but emits nothing of its own uses
169/// this named value rather than an ambiguous `()`.
170#[derive(Debug, Clone, Copy, PartialEq, Eq)]
171pub struct NoSends;
172
173impl SendEffects for NoSends {
174    fn empty() -> Self {
175        Self
176    }
177
178    fn append(&mut self, _: Self) {}
179}
180
181impl<Event> SendsFor<Event> for NoSends {}
182
183impl<Interpreter: SendInterpreter, RootEvent, Path> InterpretSends<Interpreter, RootEvent, Path>
184    for NoSends
185{
186    fn interpret(
187        self,
188        _: &mut Interpreter,
189    ) -> impl Future<Output = Result<(), Interpreter::Error>> + Send {
190        async { Ok(()) }
191    }
192}
193
194/// Send effects introduced by one wrapper around inner send effects.
195///
196/// `owned` contains effects introduced by the current behavior layer and
197/// `inner` contains effects of the wrapped interaction. The structural
198/// [`SendsFor`] implementation is the composition law:
199///
200/// ```text
201/// Event'   = OwnedEvent + InnerEvent
202/// Effects' = OwnedEffects × InnerEffects
203/// ```
204///
205/// Owned return to the emitters target `Event'`; inner return to the emitters target
206/// `InnerEvent` and are therefore lifted through the same `Inner` injection.
207/// Established actor, child, and ancestor destinations are unaffected because
208/// they are not return to the emitters.
209#[derive(Debug, Clone, Copy, PartialEq, Eq)]
210pub struct SendLayer<Owned, Inner> {
211    pub owned: Owned,
212    pub inner: Inner,
213}
214
215impl<Owned, Inner> SendLayer<Owned, Inner> {
216    #[must_use]
217    pub const fn new(owned: Owned, inner: Inner) -> Self {
218        Self { owned, inner }
219    }
220}
221
222impl<Owned: SendEffects, Inner: SendEffects> SendEffects for SendLayer<Owned, Inner> {
223    fn empty() -> Self {
224        Self::new(Owned::empty(), Inner::empty())
225    }
226
227    fn append(&mut self, other: Self) {
228        self.owned.append(other.owned);
229        self.inner.append(other.inner);
230    }
231}
232
233impl<Event, OwnedEffects, InnerEffects> SendsFor<Event> for SendLayer<OwnedEffects, InnerEffects>
234where
235    Event: ComposedEvent,
236    OwnedEffects: SendsFor<Event>,
237    InnerEffects: SendsFor<Event::Inner>,
238{
239}
240
241impl<Input, Path, Owned, Inner> SendInput<Input, Path> for SendLayer<Owned, Inner>
242where
243    Owned: SendInput<Input, Path>,
244{
245    fn emit(&mut self, input: Input) {
246        self.owned.emit(input);
247    }
248}
249
250impl<Interpreter, RootEvent, Path, Owned, Inner> InterpretSends<Interpreter, RootEvent, Path>
251    for SendLayer<Owned, Inner>
252where
253    Interpreter: SendInterpreter,
254    Interpreter: Send,
255    Owned: InterpretSends<Interpreter, RootEvent, Path> + Send,
256    Inner: InterpretSends<Interpreter, RootEvent, Inside<Path>> + Send,
257{
258    fn interpret(
259        self,
260        interpreter: &mut Interpreter,
261    ) -> impl Future<Output = Result<(), Interpreter::Error>> + Send {
262        async move {
263            // Initialization and delegated transition effects retain authored
264            // inner-to-outer order. Failure short-circuits before later effects.
265            <Inner as InterpretSends<Interpreter, RootEvent, Inside<Path>>>::interpret(
266                self.inner,
267                interpreter,
268            )
269            .await?;
270            <Owned as InterpretSends<Interpreter, RootEvent, Path>>::interpret(
271                self.owned,
272                interpreter,
273            )
274            .await
275        }
276    }
277}
278
279impl<T> SendEffects for Vec<T> {
280    fn empty() -> Self {
281        Vec::new()
282    }
283
284    fn append(&mut self, mut other: Self) {
285        Vec::append(self, &mut other);
286    }
287}
288
289impl<Event, T> SendsFor<Event> for Vec<T> {}
290
291impl<Interpreter, RootEvent, Path, P> InterpretSends<Interpreter, RootEvent, Path>
292    for Vec<Delivery<P>>
293where
294    Interpreter: InterpretDelivery<P>,
295    Interpreter: Send,
296    P: Protocol,
297    Delivery<P>: Send,
298{
299    fn interpret(
300        self,
301        interpreter: &mut Interpreter,
302    ) -> impl Future<Output = Result<(), Interpreter::Error>> + Send {
303        async move {
304            for delivery in self {
305                interpreter.interpret_delivery(delivery).await?;
306            }
307            Ok(())
308        }
309    }
310}
311
312impl<Interpreter: SendInterpreter, RootEvent, Path> InterpretSends<Interpreter, RootEvent, Path>
313    for Vec<crate::Never>
314{
315    fn interpret(
316        self,
317        _: &mut Interpreter,
318    ) -> impl Future<Output = Result<(), Interpreter::Error>> + Send {
319        async move {
320            for never in self {
321                match never {}
322            }
323            Ok(())
324        }
325    }
326}
327
328impl<T> SendInput<T, Own> for Vec<T> {
329    fn emit(&mut self, input: T) {
330        self.push(input);
331    }
332}
333
334/// Requests interpreted by the runtime local to the emitting actor.
335///
336/// Unlike [`crate::Delivery`], a interpreter request has no actor address. Its
337/// recipient is definitionally the interpreter of the actor whose transition
338/// emitted it. This distinct send lane lets interpreters route ordinary
339/// deliveries and interpreter requests with disjoint static implementations.
340#[derive(Debug, Clone, PartialEq, Eq)]
341pub struct InterpreterRequests<M> {
342    requests: Vec<M>,
343}
344
345impl<M> InterpreterRequests<M> {
346    #[must_use]
347    pub fn new(requests: Vec<M>) -> Self {
348        Self { requests }
349    }
350    #[must_use]
351    pub fn one(request: M) -> Self {
352        Self::new(vec![request])
353    }
354    #[must_use]
355    pub fn as_slice(&self) -> &[M] {
356        &self.requests
357    }
358    pub fn iter(&self) -> core::slice::Iter<'_, M> {
359        self.requests.iter()
360    }
361    #[must_use]
362    pub fn len(&self) -> usize {
363        self.requests.len()
364    }
365    #[must_use]
366    pub fn is_empty(&self) -> bool {
367        self.requests.is_empty()
368    }
369    pub fn extend(&mut self, requests: impl IntoIterator<Item = M>) {
370        self.requests.extend(requests);
371    }
372    #[must_use]
373    pub fn into_requests(self) -> Vec<M> {
374        self.requests
375    }
376}
377
378impl<M> core::ops::Index<usize> for InterpreterRequests<M> {
379    type Output = M;
380    fn index(&self, index: usize) -> &Self::Output {
381        &self.requests[index]
382    }
383}
384
385impl<M> IntoIterator for InterpreterRequests<M> {
386    type Item = M;
387    type IntoIter = std::vec::IntoIter<M>;
388    fn into_iter(self) -> Self::IntoIter {
389        self.requests.into_iter()
390    }
391}
392
393impl<'a, M> IntoIterator for &'a InterpreterRequests<M> {
394    type Item = &'a M;
395    type IntoIter = core::slice::Iter<'a, M>;
396    fn into_iter(self) -> Self::IntoIter {
397        self.requests.iter()
398    }
399}
400
401impl<M> SendEffects for InterpreterRequests<M> {
402    fn empty() -> Self {
403        Self::new(Vec::new())
404    }
405    fn append(&mut self, mut other: Self) {
406        self.requests.append(&mut other.requests);
407    }
408}
409
410impl<Event, M> SendsFor<Event> for InterpreterRequests<M>
411where
412    M: InterpreterRequest,
413    M::ReturnToEmitter: ReturnToEmitterFor<Event>,
414{
415}
416
417impl<M> SendInput<M, Own> for InterpreterRequests<M> {
418    fn emit(&mut self, input: M) {
419        self.requests.push(input);
420    }
421}
422
423impl<Interpreter, RootEvent, Path, Request> InterpretSends<Interpreter, RootEvent, Path>
424    for InterpreterRequests<Request>
425where
426    Interpreter: InterpretRequest<Request, RootEvent, Path>,
427    Interpreter: Send,
428    Request: Send,
429{
430    fn interpret(
431        self,
432        interpreter: &mut Interpreter,
433    ) -> impl Future<Output = Result<(), Interpreter::Error>> + Send {
434        async move {
435            for request in self {
436                <Interpreter as InterpretRequest<Request, RootEvent, Path>>::interpret_request(
437                    interpreter,
438                    request,
439                )
440                .await?;
441            }
442            Ok(())
443        }
444    }
445}
446
447#[cfg(test)]
448mod tests {
449    use super::*;
450
451    #[test]
452    fn send_accumulation_obeys_identity_and_associativity() {
453        let values = vec![1, 2];
454        assert_eq!(Vec::new().combine(values.clone()), values);
455        assert_eq!(values.clone().combine(Vec::new()), values);
456
457        let left = vec![1].combine(vec![2]).combine(vec![3]);
458        let right = vec![1].combine(vec![2].combine(vec![3]));
459        assert_eq!(left, right);
460    }
461
462    #[test]
463    fn vector_and_service_lanes_emit_and_iterate_in_order() {
464        assert!(<Vec<u8> as SendEffects>::empty().is_empty());
465        let mut vector = Vec::new();
466        <Vec<u8> as SendInput<u8, Own>>::emit(&mut vector, 1);
467        assert_eq!(vector, [1]);
468
469        let mut services = InterpreterRequests::one(2);
470        services.extend([4, 5]);
471        <InterpreterRequests<u8> as SendInput<u8, Own>>::emit(&mut services, 3);
472        assert!(!services.is_empty());
473        assert_eq!(services.as_slice(), [2, 4, 5, 3]);
474        assert_eq!(
475            (&services).into_iter().copied().collect::<Vec<_>>(),
476            [2, 4, 5, 3]
477        );
478        assert_eq!(services.into_iter().collect::<Vec<_>>(), [2, 4, 5, 3]);
479
480        let requests = InterpreterRequests::new(vec![4, 5]).into_requests();
481        assert_eq!(requests, [4, 5]);
482    }
483
484    struct Returning;
485
486    impl InterpreterRequest for Returning {
487        type ReturnToEmitter = ReturnsToEmitter<u8, crate::Here>;
488    }
489
490    fn lawful<Event, Effects: SendsFor<Event>>() {}
491
492    #[test]
493    fn local_return_proofs_compose_through_exact_event_layers() {
494        type Inner = crate::EventLayer<u8, crate::User<crate::MailAddr, ()>>;
495        type Outer = crate::EventLayer<(), Inner>;
496
497        lawful::<Inner, InterpreterRequests<Returning>>();
498        lawful::<Outer, SendLayer<NoSends, InterpreterRequests<Returning>>>();
499    }
500
501    #[test]
502    fn send_layer_emits_into_its_designated_owned_lane() {
503        let mut effects = SendLayer::new(Vec::<u8>::new(), Vec::<u16>::new());
504        <SendLayer<Vec<u8>, Vec<u16>> as SendInput<u8, Own>>::emit(&mut effects, 7);
505        assert_eq!(effects.owned, [7]);
506        assert!(effects.inner.is_empty());
507    }
508
509    #[derive(Debug, PartialEq, Eq)]
510    enum Seen {
511        Inner(u8),
512        Outer(u16),
513    }
514
515    struct Trace(Vec<Seen>);
516
517    type TraceEvent =
518        crate::EventLayer<u16, crate::EventLayer<u8, crate::User<crate::MailAddr, ()>>>;
519
520    impl SendInterpreter for Trace {
521        type Error = core::convert::Infallible;
522    }
523
524    impl InterpretRequest<u8, TraceEvent, crate::Inside<crate::Here>> for Trace {
525        fn interpret_request(
526            &mut self,
527            request: u8,
528        ) -> impl Future<Output = Result<(), Self::Error>> + Send {
529            async move {
530                self.0.push(Seen::Inner(request));
531                Ok(())
532            }
533        }
534    }
535
536    impl InterpretRequest<u16, TraceEvent, crate::Here> for Trace {
537        fn interpret_request(
538            &mut self,
539            request: u16,
540        ) -> impl Future<Output = Result<(), Self::Error>> + Send {
541            async move {
542                self.0.push(Seen::Outer(request));
543                Ok(())
544            }
545        }
546    }
547
548    #[tokio::test]
549    async fn structural_interpretation_visits_every_lane_inner_to_outer() {
550        let effects = SendLayer::new(
551            InterpreterRequests::new(vec![3_u16, 5]),
552            SendLayer::new(InterpreterRequests::one(2_u8), NoSends),
553        );
554        let mut trace = Trace(Vec::new());
555
556        <_ as InterpretSends<_, TraceEvent, crate::Here>>::interpret(effects, &mut trace)
557            .await
558            .unwrap();
559
560        assert_eq!(trace.0, [Seen::Inner(2), Seen::Outer(3), Seen::Outer(5)]);
561    }
562}