behavior/calculus/behavior.rs
1//! Pure behavior folds from one typed event to explicit transition actions.
2
3use super::user_event::UserEvent;
4use crate::actor::{Address, BirthMode};
5use crate::effects::{Acted, Actions, SendAlgebra};
6
7/// The only successful effect shape admitted by a [`Behavior`] implementation.
8pub type BehaviorActed<B> = Acted<
9 <B as Behavior>::Addr,
10 <B as Behavior>::Ph,
11 <B as Behavior>::Sends,
12 <B as Behavior>::Birth,
13 <B as Behavior>::Error,
14>;
15
16/// Crate-minted capability for defining one initialization fold.
17///
18/// The constructor is private: only the lifecycle boundary can issue this
19/// capability, exactly once for an owned behavior value.
20pub struct InitializationTurn {
21 #[allow(dead_code, reason = "private field prevents external construction")]
22 private: (),
23}
24
25impl InitializationTurn {
26 pub(crate) const fn new() -> Self {
27 Self { private: () }
28 }
29}
30
31/// Crate-minted capability for defining one active mailbox fold.
32///
33/// Values can only be issued by an initialized [`crate::Active`] behavior or
34/// by a concrete core wrapper delegating the same active turn inward.
35pub struct ActiveTurn {
36 #[allow(dead_code, reason = "private field prevents external construction")]
37 private: (),
38}
39
40impl ActiveTurn {
41 pub(crate) const fn new() -> Self {
42 Self { private: () }
43 }
44}
45
46/// A composed pure behavior. `Event` is the complete accepted protocol;
47/// every successful transition returns the declared [`Actions`] value.
48pub trait Behavior {
49 type Addr: Address;
50 type Msg;
51 type Event: UserEvent<Addr = Self::Addr, Message = Self::Msg>;
52 type Sends: SendAlgebra;
53 type Ph;
54 type Error;
55 type Birth: BirthMode;
56
57 /// Produce initialization actions before the first event is accepted.
58 ///
59 /// # Errors
60 ///
61 /// Returns the behavior's declared controlled initialization failure.
62 fn init(&mut self, _turn: InitializationTurn) -> BehaviorActed<Self>
63 where
64 Self: Sized,
65 {
66 Ok(Actions::cont())
67 }
68
69 /// Fold exactly one event into explicit actions and the next behavior.
70 ///
71 /// # Errors
72 ///
73 /// Returns the behavior's declared controlled transition failure.
74 fn transition(&mut self, _turn: ActiveTurn, event: Self::Event) -> BehaviorActed<Self>;
75}
76
77/// Static projection from a composed behavior to its authored base behavior.
78///
79/// Wrappers preserve this associated type, so inspection never depends on
80/// wrapper nesting depth or a positional path.
81pub trait BehaviorBase {
82 type Base;
83
84 fn base(&self) -> &Self::Base;
85}
86
87/// Fold one event through an inner behavior owned by a semantic wrapper.
88///
89/// This is Bombay's derived, canonical boundary for wrapper composition; it is
90/// not an additional actor-model operation. It invokes the inner deterministic
91/// fold exactly once and returns its complete typed action value without
92/// inspecting or transforming it. It does not execute a runtime turn,
93/// interpret effects, or provide an alternate actor executor; top-level runtime
94/// transitions remain the responsibility of the runtime's machine adapter.
95///
96/// # Errors
97///
98/// Returns the inner behavior's controlled transition failure unchanged.
99pub(crate) fn initialize<B: Behavior>(behavior: &mut B) -> BehaviorActed<B> {
100 B::init(behavior, InitializationTurn::new())
101}
102
103pub(crate) fn delegate_transition<B: Behavior>(
104 behavior: &mut B,
105 event: B::Event,
106) -> BehaviorActed<B> {
107 B::transition(behavior, ActiveTurn::new(), event)
108}