use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use uuid::Uuid;
pub trait StateTrait {
fn id(&self) -> &str;
fn state_type(&self) -> &StateType;
fn parent(&self) -> Option<&str>;
fn children(&self) -> &[String];
fn initial(&self) -> Option<&str>;
fn data(&self) -> Option<&serde_json::Value>;
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum StateType {
Normal,
Compound,
Parallel,
Final,
History,
DeepHistory,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct State {
pub id: String,
pub state_type: StateType,
pub parent: Option<String>,
pub children: Vec<String>,
pub initial: Option<String>,
pub data: Option<serde_json::Value>,
#[serde(default = "Uuid::new_v4")]
pub(crate) uuid: Uuid,
}
impl Default for State {
fn default() -> Self {
Self {
id: "default".into(),
state_type: StateType::Normal,
parent: None,
children: Vec::new(),
initial: None,
data: None,
uuid: Uuid::new_v4(),
}
}
}
impl State {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
state_type: StateType::Normal,
parent: None,
children: Vec::new(),
initial: None,
data: None,
uuid: Uuid::new_v4(),
}
}
pub fn new_compound(id: impl Into<String>, initial: impl Into<String>) -> Self {
let initial = initial.into();
Self {
id: id.into(),
state_type: StateType::Compound,
parent: None,
children: Vec::new(),
initial: Some(initial),
data: None,
uuid: Uuid::new_v4(),
}
}
pub fn new_parallel(id: impl Into<String>) -> Self {
Self {
id: id.into(),
state_type: StateType::Parallel,
parent: None,
children: Vec::new(),
initial: None,
data: None,
uuid: Uuid::new_v4(),
}
}
pub fn new_final(id: impl Into<String>) -> Self {
Self {
id: id.into(),
state_type: StateType::Final,
parent: None,
children: Vec::new(),
initial: None,
data: None,
uuid: Uuid::new_v4(),
}
}
pub fn new_history(id: impl Into<String>) -> Self {
Self {
id: id.into(),
state_type: StateType::History,
parent: None,
children: Vec::new(),
initial: None,
data: None,
uuid: Uuid::new_v4(),
}
}
pub fn new_deep_history(id: impl Into<String>) -> Self {
Self {
id: id.into(),
state_type: StateType::DeepHistory,
parent: None,
children: Vec::new(),
initial: None,
data: None,
uuid: Uuid::new_v4(),
}
}
pub fn add_child(&mut self, child_id: impl Into<String>) -> &mut Self {
self.children.push(child_id.into());
self
}
pub fn with_data(&mut self, data: impl Into<serde_json::Value>) -> &mut Self {
self.data = Some(data.into());
self
}
}
impl StateTrait for State {
fn id(&self) -> &str {
&self.id
}
fn state_type(&self) -> &StateType {
&self.state_type
}
fn parent(&self) -> Option<&str> {
self.parent.as_deref()
}
fn children(&self) -> &[String] {
&self.children
}
fn initial(&self) -> Option<&str> {
self.initial.as_deref()
}
fn data(&self) -> Option<&serde_json::Value> {
self.data.as_ref()
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct StateCollection {
states: HashMap<String, State>,
}
impl StateCollection {
pub fn new() -> Self {
Self {
states: HashMap::new(),
}
}
pub fn add(&mut self, state: State) -> &mut Self {
self.states.insert(state.id.clone(), state);
self
}
pub fn get(&self, id: &str) -> Option<&State> {
self.states.get(id)
}
pub fn get_mut(&mut self, id: &str) -> Option<&mut State> {
self.states.get_mut(id)
}
pub fn contains(&self, id: &str) -> bool {
self.states.contains_key(id)
}
pub fn all(&self) -> impl Iterator<Item = &State> {
self.states.values()
}
}