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