use crate::{Context, Event};
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ActionType {
Entry,
Exit,
Transition,
}
#[derive(Serialize, Deserialize)]
pub struct Action {
pub name: String,
pub action_type: ActionType,
#[serde(skip)]
pub(crate) executor: Option<Box<dyn Fn(&mut Context, &Event) + Send + Sync>>,
}
impl Clone for Action {
fn clone(&self) -> Self {
Self {
name: self.name.clone(),
action_type: self.action_type,
executor: None,
}
}
}
impl fmt::Debug for Action {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Action")
.field("name", &self.name)
.field("action_type", &self.action_type)
.field(
"executor",
&format_args!(
"{}",
if self.executor.is_some() {
"Some(Fn)"
} else {
"None"
}
),
)
.finish()
}
}
impl Action {
pub fn new<F>(name: impl Into<String>, action_type: ActionType, executor: F) -> Self
where
F: Fn(&mut Context, &Event) + Send + Sync + 'static,
{
Self {
name: name.into(),
action_type,
executor: Some(Box::new(executor)),
}
}
pub fn entry<F>(name: impl Into<String>, executor: F) -> Self
where
F: Fn(&mut Context, &Event) + Send + Sync + 'static,
{
Self::new(name, ActionType::Entry, executor)
}
pub fn exit<F>(name: impl Into<String>, executor: F) -> Self
where
F: Fn(&mut Context, &Event) + Send + Sync + 'static,
{
Self::new(name, ActionType::Exit, executor)
}
pub fn transition<F>(name: impl Into<String>, executor: F) -> Self
where
F: Fn(&mut Context, &Event) + Send + Sync + 'static,
{
Self::new(name, ActionType::Transition, executor)
}
pub fn named(name: impl Into<String>, action_type: ActionType) -> Self {
Self {
name: name.into(),
action_type,
executor: None,
}
}
pub fn execute(&self, context: &mut Context, event: &Event) {
if let Some(executor) = &self.executor {
executor(context, event);
} else {
}
}
}
impl fmt::Display for Action {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Action({}, {:?})", self.name, self.action_type)
}
}
pub trait IntoAction {
fn into_action(self, action_type: ActionType) -> Action;
}
impl IntoAction for Action {
fn into_action(self, _action_type: ActionType) -> Action {
self
}
}
impl<F> IntoAction for (&str, F)
where
F: Fn(&mut Context, &Event) + Send + Sync + 'static,
{
fn into_action(self, action_type: ActionType) -> Action {
Action::new(self.0, action_type, self.1)
}
}