use std::fmt::Debug;
use async_trait::async_trait;
pub use crate::error::Error;
pub use crate::state::State;
pub use crate::task::{Task, Transition};
mod error;
mod state;
mod task;
#[async_trait]
pub trait Automaton: Debug {
fn initial_state(&self) -> State {
State::new()
}
fn initial_task(&self) -> Box<dyn Task>;
fn complete_task(&self) -> Box<dyn Task> {
Box::new(NoopTask)
}
#[cfg_attr(feature = "tracing", tracing::instrument)]
async fn execute(&self) -> Result<State, Error> {
let mut state = self.initial_state();
let mut task = self.initial_task();
loop {
task = match task.execute(&mut state).await? {
Transition::Next(task) => task,
Transition::Complete => break,
}
}
let mut complete_task = self.complete_task();
complete_task.execute(&mut state).await?;
Ok(state)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
struct NoopTask;
#[async_trait]
impl Task for NoopTask {
#[cfg_attr(feature = "tracing", tracing::instrument)]
async fn execute(&mut self, _state: &mut State) -> Result<Transition, Error> {
Ok(Transition::Complete)
}
}
#[cfg(test)]
mod tests {
use super::NoopTask;
#[test]
fn trait_send() {
fn assert_send<T: Send>() {}
assert_send::<NoopTask>();
}
#[test]
fn trait_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<NoopTask>();
}
}