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