crb_morph/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use async_trait::async_trait;
use crb_runtime::kit::{Context, InteractiveRuntime, Interruptor, Runtime};

pub trait MorphContext: Context + 'static {
    fn morph(&mut self, next: impl Morph<Context = Self>);
    fn next_state(&mut self) -> Option<Box<dyn Morph<Context = Self>>>;
}

pub struct MorphSession {
    next_state: Option<Box<dyn Morph<Context = Self>>>,
}

impl MorphContext for MorphSession {
    fn morph(&mut self, next: impl Morph<Context = Self>) {
        self.next_state = Some(Box::new(next));
    }

    fn next_state(&mut self) -> Option<Box<dyn Morph<Context = Self>>> {
        self.next_state.take()
    }
}

impl Context for MorphSession {
    type Address = ();

    fn address(&self) -> &Self::Address {
        &()
    }
}

pub trait Morph: Send + 'static {
    // TODO:
    // type Message; ? and the `send` method that expects `impl Into<Morph::Message>`
    // Routing? call the method only if that is implemented for a particular state?
    type Context;
}

pub struct MorphRuntime<C> {
    context: C,
    morphed: Box<dyn Morph<Context = C>>,
}

#[async_trait]
impl<C: MorphContext> InteractiveRuntime for MorphRuntime<C> {
    type Context = C;

    fn address(&self) -> <Self::Context as Context>::Address {
        self.context.address().clone()
    }
}

#[async_trait]
impl<C: MorphContext> Runtime for MorphRuntime<C> {
    fn get_interruptor(&mut self) -> Interruptor {
        todo!()
    }

    async fn routine(&mut self) {
        loop {
            if let Some(morphed) = self.context.next_state() {
                self.morphed = morphed;
            }
        }
    }
}