intrepid_core/system/
open.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use tower::Service;

use crate::{ActionContext, Frame, FrameFuture, Handler};

use super::{
    direct::Direct, dispatch::Dispatch, routed::Routed, Stateful, StatelessSystem, System,
};

/// A system that is still being initialized.
#[derive(Clone, Copy, Default)]
pub struct Open;

/// A system that is still being initialized. Its status is open because its state is not yet
/// determined. This is where systems begin, and most constructor types are defined here because
/// that enables us to pre-define the opening status.
///
pub type OpenSystem<State> = System<Open, State>;

impl<State> OpenSystem<State>
where
    State: Clone + Send + Sync + 'static,
{
    /// Create a new directed system.
    pub fn direct() -> Self {
        Self::Direct(Direct::init())
    }

    /// Create a new dispatched system.
    pub fn dispatch() -> Self {
        Self::Dispatch(Dispatch::init())
    }

    /// Create a new routed system.
    pub fn routed() -> Self {
        Self::Routed(Routed::init())
    }

    /// Transition to a stateful system with a given state.
    pub fn with_state(&self, state: State) -> System<Stateful<State>, State> {
        match self {
            Self::Direct(system) => System::Direct(system.with_state(state)),
            Self::Dispatch(system) => System::Dispatch(system.with_state(state)),
            Self::Routed(system) => System::Routed(system.with_state(state)),
        }
    }

    fn handle_frame_with_state(&self, frame: Frame, state: State) -> FrameFuture {
        match self {
            Self::Direct(system) => system.handle_frame_with_state(frame, state),
            Self::Dispatch(system) => system.handle_frame_with_state(frame, state),
            Self::Routed(system) => system.handle_frame_with_state(frame, state),
        }
    }
}

impl OpenSystem<()> {
    /// If we know that the state is empty, we know that we can transition to a stateless system.
    /// Transition to a stateless system.
    pub fn without_state(self) -> StatelessSystem {
        match self {
            Self::Direct(system) => System::Direct(system.without_state()),
            Self::Dispatch(system) => System::Dispatch(system.without_state()),
            Self::Routed(system) => System::Routed(system.without_state()),
        }
    }

    /// Call the system with a frame.
    pub fn handle_frame(self, frame: Frame) -> FrameFuture {
        self.handle_frame_with_state(frame, ())
    }
}

impl<State> Handler<Frame, State> for OpenSystem<State>
where
    State: Clone + Send + Sync + 'static,
{
    type Future = FrameFuture;

    fn invoke(&self, frame: impl Into<Frame>, state: State) -> Self::Future {
        self.handle_frame_with_state(frame.into(), state)
    }

    fn context(&self) -> ActionContext<State> {
        match self {
            Self::Direct(system) => system.action_context(),
            Self::Dispatch(system) => system.action_context(),
            Self::Routed(system) => system.action_context(),
        }
    }
}

impl<IntoFrame> Service<IntoFrame> for System<Open, ()>
where
    IntoFrame: Into<Frame> + Clone + Send + 'static,
{
    type Response = Frame;
    type Error = crate::Error;
    type Future = FrameFuture;

    fn poll_ready(
        &mut self,
        _: &mut std::task::Context<'_>,
    ) -> std::task::Poll<Result<(), Self::Error>> {
        std::task::Poll::Ready(Ok(()))
    }

    fn call(&mut self, frame: IntoFrame) -> Self::Future {
        let frame: Frame = frame.into();
        let instance = self.clone();

        instance.handle_frame(frame)
    }
}