flowstate 0.8.2

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

use flowstate::{AsyncWorkflow, AsyncWorkflowState, prelude::*};

struct BasicWorkflow<State> {
    _state: State,
}

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

impl<State: flowstate::AsyncState> AsyncWorkflow for BasicWorkflow<State> {
    fn workflow_name(&self) -> String {
        type_name::<Self>().to_string()
    }

    fn state(&self) -> &dyn flowstate::AsyncState {
        &self._state
    }
}

#[async_state]
trait BasicWorkflowState: AsyncWorkflow {
    fn state_name(&self) -> String {
        self.state().name()
    }

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

#[async_state]
impl<State> AsyncWorkflowState<'static, WorkflowResult> for BasicWorkflow<State>
where
    State: flowstate::AsyncState + Send,
    BasicWorkflow<State>: BasicWorkflowState,
{
    fn name(&self) -> String {
        self.state_name()
    }

    async fn next(self: Box<Self>) -> AsyncTransition<'static, WorkflowResult> {
        BasicWorkflowState::next(self).await
    }
}

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

struct StateA;

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

#[async_state]
impl BasicWorkflowState for BasicWorkflow<StateA> {
    async fn next(self: Box<Self>) -> AsyncTransition<'static, WorkflowResult> {
        self.transition(StateB)
    }
}

struct StateB;

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

#[async_state]
impl BasicWorkflowState for BasicWorkflow<StateB> {
    async fn next(self: Box<Self>) -> AsyncTransition<'static, WorkflowResult> {
        self.finish(WorkflowResult)
    }
}

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

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