intrepid_core/
system.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
mod direct;
mod dispatch;
mod dispatchable;
mod open;
mod routed;
mod stateful;
mod stateless;

use direct::Direct;
use dispatch::Dispatch;
use routed::Routed;

pub use open::*;
pub use stateful::*;
pub use stateless::*;

use crate::{ActionContext, Handler};

#[derive(Clone)]
/// A system is a collection of actions that can be invoked as services.
pub enum System<Status, State> {
    /// An unordered system that invokes all actions.
    Direct(Direct<Status, State>),
    /// A system that routes frames to actions fully matching patterns.
    Dispatch(Dispatch<Status, State>),
    /// A system that routes frames to matching patterns.
    Routed(Routed<Status, State>),
}

impl<Status, State> System<Status, State>
where
    State: Clone + Send + Sync + 'static,
{
    /// Add a frame handler to the system. This is a no-op for systems that do not support
    /// wildcard routing or only support specific patterns.
    pub fn on_frame<ActionHandler, Args>(self, action: ActionHandler) -> Self
    where
        ActionHandler: Handler<Args, State> + Clone + Send + Sync + 'static,
        Args: Clone + Send + Sync + 'static,
    {
        match self {
            Self::Direct(system) => Self::Direct(system.on_frame(action)),
            _ => self,
        }
    }

    /// Add a uri bound or path bound handler to the system.
    ///
    /// - Dispatch systems will match the pattern exactly.
    /// - Routed systems will match the pattern as a path fragment.
    pub fn on<ActionHandler, Args>(self, pattern: impl AsRef<str>, action: ActionHandler) -> Self
    where
        ActionHandler: Handler<Args, State> + Clone + Send + Sync + 'static,
        Args: Clone + Send + Sync + 'static,
    {
        match self {
            Self::Dispatch(system) => Self::Dispatch(system.on(pattern, action)),
            Self::Routed(system) => Self::Routed(system.on(pattern, action)),
            _ => self,
        }
    }

    /// Get the routes for this system, if any.
    pub fn routes(&self) -> Option<Vec<String>> {
        match self {
            Self::Routed(system) => Some(system.routes()),
            _ => None,
        }
    }

    /// Get the action context for this system.
    pub fn action_context(&self) -> ActionContext<State> {
        match self {
            Self::Direct(system) => system.action_context(),
            Self::Dispatch(system) => system.action_context(),
            Self::Routed(system) => system.action_context(),
        }
    }
}