rustate/
logic.rs

1use crate::actor::ActorError;
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4use std::fmt::Debug;
5
6/// Defines the core logic for state transitions, actions, and guards within an actor.
7///
8/// This trait encapsulates the behavior of a state machine. It determines how the actor
9/// moves between states and updates its context based on incoming events.
10///
11/// Typically, the `create_machine` macro (planned for Phase 2) will automatically generate
12/// a struct implementing this trait based on a declarative state machine definition.
13/// Manual implementation is possible but the macro approach is generally preferred for
14/// consistency and reduced boilerplate.
15#[async_trait]
16pub trait ActorLogic: Send + Sync + 'static {
17    /// The type representing the actor's context (extended state).
18    /// This is the data the state machine holds and potentially modifies during transitions.
19    /// Context must be serializable, deserializable, cloneable, debuggable, sendable, and syncable.
20    type Context: Send + Sync + Clone + Debug + Serialize + for<'de> Deserialize<'de>;
21
22    /// The type representing the events that the actor logic processes.
23    /// This should typically match the `Event` type defined in the corresponding `Actor` trait implementation.
24    /// Events must be debuggable, sendable, syncable, serializable, and deserializable.
25    type Event: Send + Sync + Debug + Serialize + for<'de> Deserialize<'de>;
26
27    /// The type representing the possible states of the actor (usually an enum).
28    /// State must be serializable, deserializable, cloneable, debuggable, equatable, sendable, and syncable.
29    type State: Send + Sync + Clone + Debug + PartialEq + Eq + Serialize + for<'de> Deserialize<'de>;
30
31    /// Returns the initial state and initial context for the state machine.
32    ///
33    /// This is called when the actor associated with this logic is started.
34    fn initial(&self) -> (Self::State, Self::Context);
35
36    /// Executes a state transition based on the current state, context, and a received event.
37    ///
38    /// This is the core method where the state machine's transition rules are applied.
39    /// It may involve evaluating guards, executing actions, and determining the next state.
40    ///
41    /// # Arguments
42    ///
43    /// * `state` - The current state of the machine.
44    /// * `context` - The current context (data) associated with the state.
45    /// * `event` - The event that triggered the potential transition.
46    ///
47    /// # Returns
48    ///
49    /// A `Result` containing:
50    /// * `Ok((Self::State, Self::Context))` - The new state and potentially updated context after the transition.
51    /// * `Err(ActorError)` - If an error occurred during the transition logic (e.g., an action failed).
52    ///
53    /// If no transition is defined for the given event in the current state (or if a guard condition fails),
54    /// this method should typically return `Ok((state, context))` (the current state and context unchanged).
55    /// A specific `ActorError` variant could potentially be used to indicate "no transition occurred",
56    /// but returning the current state is often sufficient.
57    async fn transition(
58        &self,
59        state: Self::State,
60        context: Self::Context,
61        event: Self::Event,
62    ) -> Result<(Self::State, Self::Context), ActorError>;
63
64    // --- Potential Future Enhancements ---
65
66    // /// Executes actions upon entering a state.
67    // async fn on_entry(&self, state: &Self::State, context: &mut Self::Context) -> Result<(), ActorError> { Ok(()) }
68
69    // /// Executes actions upon exiting a state.
70    // async fn on_exit(&self, state: &Self::State, context: &mut Self::Context) -> Result<(), ActorError> { Ok(()) }
71
72    // /// Evaluates guard conditions before executing a transition.
73    // async fn check_guard(&self, state: &Self::State, context: &Self::Context, event: &Self::Event) -> bool { true }
74
75    // /// Executes actions associated with a specific transition.
76    // async fn execute_action(&self, state: &Self::State, context: &mut Self::Context, event: &Self::Event) -> Result<(), ActorError> { Ok(()) }
77}
78
79// --- Example Dummy Implementation ---
80/*
81struct MyMachineLogic;
82
83#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
84enum MyState { Idle, Processing }
85
86#[async_trait]
87impl ActorLogic for MyMachineLogic {
88    type Context = i32;
89    type Event = String;
90    type State = MyState;
91
92    fn initial(&self) -> (Self::State, Self::Context) {
93        (MyState::Idle, 0)
94    }
95
96    async fn transition(&self, state: Self::State, context: Self::Context, event: Self::Event)
97        -> Result<(Self::State, Self::Context), ActorError>
98    {
99        println!("Transitioning from {:?} with context {} on event \"{}\"", state, context, event);
100        match (state, event.as_str()) {
101            (MyState::Idle, "START") => Ok((MyState::Processing, context + 1)),
102            (MyState::Processing, "STOP") => Ok((MyState::Idle, context)),
103            (s, _) => Ok((s, context)), // No change for other events
104        }
105    }
106}
107*/