use serde::{Deserialize, Serialize};
use std::fmt::Debug;
pub trait State:
Clone + PartialEq + Debug + Serialize + for<'de> Deserialize<'de> + Send + Sync
{
fn name(&self) -> &str;
fn is_final(&self) -> bool {
false
}
fn is_error(&self) -> bool {
false
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
enum TestState {
Initial,
Processing,
Complete,
Failed,
}
impl State for TestState {
fn name(&self) -> &str {
match self {
Self::Initial => "Initial",
Self::Processing => "Processing",
Self::Complete => "Complete",
Self::Failed => "Failed",
}
}
fn is_final(&self) -> bool {
matches!(self, Self::Complete | Self::Failed)
}
fn is_error(&self) -> bool {
matches!(self, Self::Failed)
}
}
#[test]
fn state_name_returns_correct_value() {
assert_eq!(TestState::Initial.name(), "Initial");
assert_eq!(TestState::Processing.name(), "Processing");
assert_eq!(TestState::Complete.name(), "Complete");
assert_eq!(TestState::Failed.name(), "Failed");
}
#[test]
fn is_final_identifies_terminal_states() {
assert!(!TestState::Initial.is_final());
assert!(!TestState::Processing.is_final());
assert!(TestState::Complete.is_final());
assert!(TestState::Failed.is_final());
}
#[test]
fn is_error_identifies_error_states() {
assert!(!TestState::Initial.is_error());
assert!(!TestState::Processing.is_error());
assert!(!TestState::Complete.is_error());
assert!(TestState::Failed.is_error());
}
#[test]
fn state_trait_methods_work() {
let state = TestState::Initial;
assert_eq!(state.name(), "Initial");
assert!(!state.is_final());
assert!(!state.is_error());
let complete = TestState::Complete;
assert!(complete.is_final());
assert!(!complete.is_error());
let failed = TestState::Failed;
assert!(failed.is_final());
assert!(failed.is_error());
}
#[test]
fn state_serializes_correctly() {
let state = TestState::Initial;
let json = serde_json::to_string(&state).unwrap();
let deserialized: TestState = serde_json::from_str(&json).unwrap();
assert_eq!(state, deserialized);
}
#[test]
fn state_is_cloneable() {
let state = TestState::Processing;
let cloned = state.clone();
assert_eq!(state, cloned);
}
#[test]
fn state_is_comparable() {
let state1 = TestState::Processing;
let state2 = TestState::Processing;
let state3 = TestState::Complete;
assert_eq!(state1, state2);
assert_ne!(state1, state3);
}
}