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    fn init(&mut self) -> BehaviorActed<Self>;
56
57    /// Fold exactly one event into explicit actions and the next behavior.
58    fn transition(&mut self, event: Self::Event) -> BehaviorActed<Self>;
59
60    /// Fold one user communication through the composed protocol.
61    fn receive(&mut self, from: Self::Addr, message: Self::Msg) -> BehaviorActed<Self>
62    where
63        Self: Sized,
64    {
65        self.transition(Self::Event::user(from, message))
66    }
67
68    /// Inject one supported semantic input and fold it through this behavior.
69    ///
70    /// This method exists only when the concrete composed protocol proves that
71    /// it contains `Input`; unsupported lanes therefore fail to compile.
72    fn on<Input>(&mut self, input: Input) -> BehaviorActed<Self>
73    where
74        Self: Sized,
75        Self::Event: EventInput<Input>,
76    {
77        self.transition(Self::Event::inject(input))
78    }
79}
80
81pub struct Pure<S: Handler<O, Br, E>, O = Never, Br: BirthMode = NoBirths, E = Never> {
82    state: S,
83    marker: PhantomData<fn(O, Br, E)>,
84}
85
86impl<S: Handler<O, Br, E>, O, Br: BirthMode, E> Pure<S, O, Br, E> {
87    #[must_use]
88    pub fn new(state: S) -> Self {
89        Self {
90            state,
91            marker: PhantomData,
92        }
93    }
94    #[must_use]
95    pub fn state(&self) -> &S {
96        &self.state
97    }
98}
99
100pub struct FoldFn<
101    S,
102    A: Address,
103    M,
104    O = Never,
105    Br: BirthMode = NoBirths,
106    E = Never,
107    F = fn(&mut S, A, M) -> Acted<A, Never, Vec<Delivery<A, O>>, Br, E>,
108> {
109    pub state: S,
110    pub transition: F,
111    marker: PhantomData<fn(A, M, O, Br, E)>,
112}
113
114/// A concrete behavior defined by initialization and user-event folds.
115///
116/// Each function is invoked exactly once for its corresponding input and its
117/// returned [`Actions`] value is preserved unchanged. This adapter adds no
118/// event routing or effect interpretation; those remain the responsibility of
119/// concrete behavior wrappers and the runtime interpreter.
120pub struct BehaviorFn<S, A: Address, M, Sends, Br: BirthMode, E, I, F> {
121    state: S,
122    initialize: I,
123    transition: F,
124    marker: PhantomData<fn(A, M, Sends, Br, E)>,
125}
126
127impl<S, A: Address, M, Sends, Br: BirthMode, E, I, F> BehaviorFn<S, A, M, Sends, Br, E, I, F>
128where
129    Sends: SendAlgebra,
130    I: FnMut(&mut S) -> Acted<A, Never, Sends, Br, E>,
131    F: FnMut(&mut S, A, M) -> Acted<A, Never, Sends, Br, E>,
132{
133    #[must_use]
134    pub fn new(state: S, initialize: I, transition: F) -> Self {
135        Self {
136            state,
137            initialize,
138            transition,
139            marker: PhantomData,
140        }
141    }
142
143    #[must_use]
144    pub fn state(&self) -> &S {
145        &self.state
146    }
147}
148
149impl<S, A: Address, M, Sends, Br: BirthMode, E, I, F> Behavior
150    for BehaviorFn<S, A, M, Sends, Br, E, I, F>
151where
152    Sends: SendAlgebra,
153    I: FnMut(&mut S) -> Acted<A, Never, Sends, Br, E>,
154    F: FnMut(&mut S, A, M) -> Acted<A, Never, Sends, Br, E>,
155{
156    type Addr = A;
157    type Msg = M;
158    type Event = User<A, M>;
159    type Sends = Sends;
160    type Ph = Never;
161    type Error = E;
162    type Birth = Br;
163
164    fn init(&mut self) -> BehaviorActed<Self> {
165        (self.initialize)(&mut self.state)
166    }
167
168    fn transition(&mut self, event: Self::Event) -> BehaviorActed<Self> {
169        (self.transition)(&mut self.state, event.from, event.message)
170    }
171}
172
173impl<S, F, A: Address, M, O, Br: BirthMode, E> Handler<O, Br, E> for FoldFn<S, A, M, O, Br, E, F>
174where
175    F: FnMut(&mut S, A, M) -> Acted<A, Never, Vec<Delivery<A, O>>, Br, E>,
176{
177    type Addr = A;
178    type Msg = M;
179
180    fn receive(&mut self, from: A, message: M) -> Acted<A, Never, Vec<Delivery<A, O>>, Br, E> {
181        (self.transition)(&mut self.state, from, message)
182    }
183}
184
185impl<S, F, A: Address, M, O, Br: BirthMode, E> Pure<FoldFn<S, A, M, O, Br, E, F>, O, Br, E>
186where
187    F: FnMut(&mut S, A, M) -> Acted<A, Never, Vec<Delivery<A, O>>, Br, E>,
188{
189    #[must_use]
190    pub fn from_fn(state: S, transition: F) -> Self {
191        Self::new(FoldFn {
192            state,
193            transition,
194            marker: PhantomData,
195        })
196    }
197}
198
199impl<S, O, Br, E> Behavior for Pure<S, O, Br, E>
200where
201    S: Handler<O, Br, E>,
202    Br: BirthMode,
203{
204    type Addr = S::Addr;
205    type Msg = S::Msg;
206    type Event = User<S::Addr, S::Msg>;
207    type Sends = Vec<Delivery<S::Addr, O>>;
208    type Ph = Never;
209    type Error = E;
210    type Birth = Br;
211
212    fn init(&mut self) -> StateActed<S::Addr, O, Br, E> {
213        Ok(Actions::cont())
214    }
215
216    fn transition(&mut self, event: Self::Event) -> StateActed<S::Addr, O, Br, E> {
217        self.state.receive(event.from, event.message)
218    }
219}