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*/