flowstate 0.5.0

Workflow runtime powered by finite state machines.
Documentation
use std::any::type_name;

use flowstate::{WorkflowState, prelude::*};

struct BasicWorkflow<State> {
    _state: State,
}

impl BasicWorkflow<StateA> {
    fn init() -> Self {
        Self { _state: StateA }
    }
}

impl<State: flowstate::State> Workflow for BasicWorkflow<State> {
    fn state(&self) -> &dyn flowstate::State {
        &self._state
    }
}

trait BasicWorkflowState: Workflow {
    fn state_name(&self) -> String {
        self.state().name()
    }

    fn next(self: Box<Self>) -> Transition<'static, WorkflowResult>;
}

impl<State> WorkflowState<'static, WorkflowResult> for BasicWorkflow<State>
where
    State: flowstate::State,
    BasicWorkflow<State>: BasicWorkflowState,
{
    fn name(&self) -> String {
        self.state_name()
    }

    fn next(self: Box<Self>) -> Transition<'static, WorkflowResult> {
        BasicWorkflowState::next(self)
    }
}

impl<State> BasicWorkflow<State> {
    fn transition<NewState>(self, next_state: NewState) -> Transition<'static, WorkflowResult>
    where
        BasicWorkflow<NewState>: WorkflowState<'static, WorkflowResult> + 'static,
    {
        Transition::Continue(Box::new(BasicWorkflow { _state: next_state }))
    }
}

struct StateA;

impl State for StateA {
    fn name(&self) -> String {
        type_name::<StateA>().to_string()
    }
}

impl BasicWorkflowState for BasicWorkflow<StateA> {
    fn next(self: Box<Self>) -> Transition<'static, WorkflowResult> {
        self.transition(StateB)
    }
}

struct StateB;

impl State for StateB {
    fn name(&self) -> String {
        type_name::<StateB>().to_string()
    }
}

impl BasicWorkflowState for BasicWorkflow<StateB> {
    fn next(self: Box<Self>) -> Transition<'static, WorkflowResult> {
        self.finish(WorkflowResult)
    }
}

#[derive(Debug, PartialEq)]
struct WorkflowResult;

#[test]
fn test_basic_workflow_manual_impls() {
    let workflow = BasicWorkflow::init();
    let result = workflow.run();
    assert_eq!(result, WorkflowResult);
}