crb 0.0.38

CRB | Composable Runtime Blocks
Documentation
use anyhow::{Error, Result};
use async_trait::async_trait;
use crb::agent::{Address, Agent, AgentSession, DoAsync, Next, Standalone};

enum State {
    First,
    Second,
    Third,
}

impl State {
    fn next(&self) -> Next<Task> {
        match self {
            State::First => Next::do_async(First),
            State::Second => Next::do_async(Second),
            State::Third => Next::do_async(Third),
        }
    }
}

struct Task {
    state: State,
}

impl Standalone for Task {}

impl Agent for Task {
    type Context = AgentSession<Self>;
    type Link = Address<Self>;

    fn begin(&mut self) -> Next<Self> {
        self.state.next()
    }
}

struct First;

#[async_trait]
impl DoAsync<First> for Task {
    async fn once(&mut self, _: &mut First) -> Result<Next<Self>> {
        self.state = State::Second;
        Ok(self.state.next())
    }
}

struct Second;

#[async_trait]
impl DoAsync<Second> for Task {
    async fn once(&mut self, _: &mut Second) -> Result<Next<Self>> {
        self.state = State::Third;
        Ok(self.state.next())
    }
}

struct Third;

#[async_trait]
impl DoAsync<Third> for Task {
    async fn once(&mut self, _: &mut Third) -> Result<Next<Self>> {
        Ok(Next::done())
    }
}

#[tokio::test]
async fn test_fsm() -> Result<(), Error> {
    let state = State::First;
    let mut addr = Task { state }.spawn();
    addr.join().await?;
    Ok(())
}