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
114impl<S, F, A: Address, M, O, Br: BirthMode, E> Handler<O, Br, E> for FoldFn<S, A, M, O, Br, E, F>
115where
116    F: FnMut(&mut S, A, M) -> Acted<A, Never, Vec<Delivery<A, O>>, Br, E>,
117{
118    type Addr = A;
119    type Msg = M;
120
121    fn receive(&mut self, from: A, message: M) -> Acted<A, Never, Vec<Delivery<A, O>>, Br, E> {
122        (self.transition)(&mut self.state, from, message)
123    }
124}
125
126impl<S, F, A: Address, M, O, Br: BirthMode, E> Pure<FoldFn<S, A, M, O, Br, E, F>, O, Br, E>
127where
128    F: FnMut(&mut S, A, M) -> Acted<A, Never, Vec<Delivery<A, O>>, Br, E>,
129{
130    #[must_use]
131    pub fn from_fn(state: S, transition: F) -> Self {
132        Self::new(FoldFn {
133            state,
134            transition,
135            marker: PhantomData,
136        })
137    }
138}
139
140impl<S, O, Br, E> Behavior for Pure<S, O, Br, E>
141where
142    S: Handler<O, Br, E>,
143    Br: BirthMode,
144{
145    type Addr = S::Addr;
146    type Msg = S::Msg;
147    type Event = User<S::Addr, S::Msg>;
148    type Sends = Vec<Delivery<S::Addr, O>>;
149    type Ph = Never;
150    type Error = E;
151    type Birth = Br;
152
153    fn init(&mut self) -> StateActed<S::Addr, O, Br, E> {
154        Ok(Actions::cont())
155    }
156
157    fn transition(&mut self, event: Self::Event) -> StateActed<S::Addr, O, Br, E> {
158        self.state.receive(event.from, event.message)
159    }
160}