Skip to main content

behavior/
transition.rs

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