Skip to main content

behavior/calculus/
behavior.rs

1//! Pure behavior folds from one typed event to explicit transition actions.
2
3use core::marker::PhantomData;
4
5use super::user_event::{EventInput, User, UserEvent};
6use crate::actor::{Address, BirthMode, NoBirths};
7use crate::effects::{Acted, Actions, SendAlgebra};
8use crate::next::Never;
9
10pub type StateActed<A, Sends, Birth, Err> = Acted<A, Never, Sends, Birth, Err>;
11
12/// The only successful effect shape admitted by a [`Behavior`] implementation.
13pub type BehaviorActed<B> = Acted<
14    <B as Behavior>::Addr,
15    <B as Behavior>::Ph,
16    <B as Behavior>::Sends,
17    <B as Behavior>::Birth,
18    <B as Behavior>::Error,
19>;
20
21pub trait Handler<Sends = Vec<Never>, Birth = NoBirths, Err = Never>
22where
23    Sends: SendAlgebra,
24    Birth: BirthMode,
25{
26    type Addr: Address;
27    type Msg;
28
29    /// Fold a user message into Bombay's typed actor transition effects.
30    ///
31    /// # Errors
32    /// Returns the state's declared controlled failure.
33    #[allow(
34        clippy::type_complexity,
35        reason = "the alias exposes all state protocol seats"
36    )]
37    fn receive(
38        &mut self,
39        from: Self::Addr,
40        message: Self::Msg,
41    ) -> StateActed<Self::Addr, Sends, Birth, Err>;
42}
43
44/// A composed pure behavior. `Event` is the complete accepted protocol;
45/// every successful transition returns the declared [`Actions`] value.
46pub trait Behavior {
47    type Addr: Address;
48    type Msg;
49    type Event: UserEvent<Addr = Self::Addr, Message = Self::Msg>;
50    type Sends: SendAlgebra;
51    type Ph;
52    type Error;
53    type Birth: BirthMode;
54
55    /// Produce initialization actions before the first event is accepted.
56    ///
57    /// # Errors
58    ///
59    /// Returns the behavior's declared controlled initialization failure.
60    fn init(&mut self) -> BehaviorActed<Self>;
61
62    /// Fold exactly one event into explicit actions and the next behavior.
63    ///
64    /// # Errors
65    ///
66    /// Returns the behavior's declared controlled transition failure.
67    fn transition(&mut self, event: Self::Event) -> BehaviorActed<Self>;
68
69    /// Fold one user communication through the composed protocol.
70    ///
71    /// # Errors
72    ///
73    /// Returns the behavior's declared controlled transition failure.
74    fn receive(&mut self, from: Self::Addr, message: Self::Msg) -> BehaviorActed<Self>
75    where
76        Self: Sized,
77    {
78        self.transition(Self::Event::user(from, message))
79    }
80
81    /// Inject one supported semantic input and fold it through this behavior.
82    ///
83    /// This method exists only when the concrete composed protocol proves that
84    /// it contains `Input`; unsupported lanes therefore fail to compile.
85    ///
86    /// # Errors
87    ///
88    /// Returns the behavior's declared controlled transition failure.
89    fn on<Input>(&mut self, input: Input) -> BehaviorActed<Self>
90    where
91        Self: Sized,
92        Self::Event: EventInput<Input>,
93    {
94        self.transition(Self::Event::inject(input))
95    }
96}
97
98/// Fold one event through an inner behavior owned by a semantic wrapper.
99///
100/// This is Bombay's derived, canonical boundary for wrapper composition; it is
101/// not an additional actor-model operation. It invokes the inner deterministic
102/// fold exactly once and returns its complete typed action value without
103/// inspecting or transforming it. It does not execute a runtime turn,
104/// interpret effects, or provide an alternate actor executor; top-level runtime
105/// transitions remain the responsibility of the runtime's machine adapter.
106///
107/// # Errors
108///
109/// Returns the inner behavior's controlled transition failure unchanged.
110pub fn delegate_transition<B: Behavior>(behavior: &mut B, event: B::Event) -> BehaviorActed<B> {
111    behavior.transition(event)
112}
113
114pub struct Pure<S, Sends = Vec<Never>, Br: BirthMode = NoBirths, E = Never>
115where
116    S: Handler<Sends, Br, E>,
117    Sends: SendAlgebra,
118{
119    state: S,
120    marker: PhantomData<fn(Sends, Br, E)>,
121}
122
123impl<S, Sends, Br, E> Pure<S, Sends, Br, E>
124where
125    S: Handler<Sends, Br, E>,
126    Sends: SendAlgebra,
127    Br: BirthMode,
128{
129    #[must_use]
130    pub fn new(state: S) -> Self {
131        Self {
132            state,
133            marker: PhantomData,
134        }
135    }
136    #[must_use]
137    pub fn state(&self) -> &S {
138        &self.state
139    }
140}
141
142pub struct FoldFn<
143    S,
144    A: Address,
145    M,
146    Sends = Vec<Never>,
147    Br: BirthMode = NoBirths,
148    E = Never,
149    F = fn(&mut S, A, M) -> Acted<A, Never, Sends, Br, E>,
150> {
151    pub state: S,
152    pub transition: F,
153    #[allow(
154        clippy::type_complexity,
155        reason = "the marker retains the complete inferred behavior signature"
156    )]
157    marker: PhantomData<fn(A, M, Sends, Br, E)>,
158}
159
160/// A concrete behavior defined by initialization and user-event folds.
161///
162/// Each function is invoked exactly once for its corresponding input and its
163/// returned [`Actions`] value is preserved unchanged. This adapter adds no
164/// event routing or effect interpretation; those remain the responsibility of
165/// concrete behavior wrappers and the runtime interpreter.
166pub struct BehaviorFn<S, A: Address, M, Sends, Br: BirthMode, E, I, F> {
167    state: S,
168    initialize: I,
169    transition: F,
170    #[allow(
171        clippy::type_complexity,
172        reason = "the marker retains the complete inferred behavior signature"
173    )]
174    marker: PhantomData<fn(A, M, Sends, Br, E)>,
175}
176
177impl<S, A: Address, M, Sends, Br: BirthMode, E, I, F> BehaviorFn<S, A, M, Sends, Br, E, I, F>
178where
179    Sends: SendAlgebra,
180    I: FnMut(&mut S) -> Acted<A, Never, Sends, Br, E>,
181    F: FnMut(&mut S, A, M) -> Acted<A, Never, Sends, Br, E>,
182{
183    #[must_use]
184    pub fn new(state: S, initialize: I, transition: F) -> Self {
185        Self {
186            state,
187            initialize,
188            transition,
189            marker: PhantomData,
190        }
191    }
192
193    #[must_use]
194    pub fn state(&self) -> &S {
195        &self.state
196    }
197}
198
199impl<S, A: Address, M, Sends, Br: BirthMode, E, I, F> Behavior
200    for BehaviorFn<S, A, M, Sends, Br, E, I, F>
201where
202    Sends: SendAlgebra,
203    I: FnMut(&mut S) -> Acted<A, Never, Sends, Br, E>,
204    F: FnMut(&mut S, A, M) -> Acted<A, Never, Sends, Br, E>,
205{
206    type Addr = A;
207    type Msg = M;
208    type Event = User<A, M>;
209    type Sends = Sends;
210    type Ph = Never;
211    type Error = E;
212    type Birth = Br;
213
214    fn init(&mut self) -> BehaviorActed<Self> {
215        (self.initialize)(&mut self.state)
216    }
217
218    fn transition(&mut self, event: Self::Event) -> BehaviorActed<Self> {
219        (self.transition)(&mut self.state, event.from, event.message)
220    }
221}
222
223impl<S, F, A: Address, M, Sends, Br: BirthMode, E> Handler<Sends, Br, E>
224    for FoldFn<S, A, M, Sends, Br, E, F>
225where
226    Sends: SendAlgebra,
227    F: FnMut(&mut S, A, M) -> Acted<A, Never, Sends, Br, E>,
228{
229    type Addr = A;
230    type Msg = M;
231
232    fn receive(&mut self, from: A, message: M) -> Acted<A, Never, Sends, Br, E> {
233        (self.transition)(&mut self.state, from, message)
234    }
235}
236
237impl<S, F, A: Address, M, Sends, Br: BirthMode, E>
238    Pure<FoldFn<S, A, M, Sends, Br, E, F>, Sends, Br, E>
239where
240    Sends: SendAlgebra,
241    F: FnMut(&mut S, A, M) -> Acted<A, Never, Sends, Br, E>,
242{
243    #[must_use]
244    pub fn from_fn(state: S, transition: F) -> Self {
245        Self::new(FoldFn {
246            state,
247            transition,
248            marker: PhantomData,
249        })
250    }
251}
252
253impl<S, Sends, Br, E> Behavior for Pure<S, Sends, Br, E>
254where
255    S: Handler<Sends, Br, E>,
256    Sends: SendAlgebra,
257    Br: BirthMode,
258{
259    type Addr = S::Addr;
260    type Msg = S::Msg;
261    type Event = User<S::Addr, S::Msg>;
262    type Sends = Sends;
263    type Ph = Never;
264    type Error = E;
265    type Birth = Br;
266
267    fn init(&mut self) -> StateActed<S::Addr, Sends, Br, E> {
268        Ok(Actions::cont())
269    }
270
271    fn transition(&mut self, event: Self::Event) -> StateActed<S::Addr, Sends, Br, E> {
272        self.state.receive(event.from, event.message)
273    }
274}