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}