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
|
use crate::{AnyOutput, ChainProcess, Grouped, ProgramCollect};
/// Represents a type that can be routed within a group.
///
/// Used to indicate that a group member can be routed into another [`ChainProcess`]
/// within the execution logic of a [`Chain`](https://docs.rs/mingling/latest/mingling/trait.Chain.html).
///
/// # Blanket impl
///
/// When a type implements [`Grouped`], it automatically gets a corresponding [`Routable`]
/// implementation, meaning all types deriving [`Grouped`] can flow through the program loop.
///
/// # Reference
///
/// You can use the [`routeify`](https://docs.rs/mingling/latest/mingling/macros/attr.routeify.html)
/// macro and the [`route!`](https://docs.rs/mingling/latest/mingling/macros/macro.route.html) macro
/// to build flexible program execution logic.
///
/// # Example
///
/// ```
/// # use mingling_core::Routable;
/// # use mingling_core::ChainProcess;
/// # use mingling_core::MockProgramCollect as ThisProgram;
/// # use mingling_core::Grouped;
/// # unsafe impl Grouped<ThisProgram> for Foo {
/// # fn member_id() -> ThisProgram {
/// # ThisProgram::Foo
/// # }
/// # }
/// struct Foo;
///
/// // With `Grouped` implemented, the type automatically implements `Routable`
/// // and can be converted into a `ChainProcess` via `to_chain` / `to_render`:
/// fn takes_chain<T: Routable<ThisProgram>>(value: T) -> ChainProcess<ThisProgram> {
/// value.to_chain()
/// }
///
/// # fn main() {
/// # takes_chain(Foo);
/// # }
/// ```
pub trait Routable<Group>
where
Self: Sized + 'static,
{
/// Converts the current type into a [`ChainProcess`] that can be used for execution in a program chain (`Chain`).
///
/// # Return value
///
/// Returns a [`ChainProcess`] wrapping the current value,
/// which will be scheduled for execution in the program chain.
///
/// # Example
///
/// ```
/// # use mingling_core::{Grouped, ChainProcess};
/// # use mingling_core::MockProgramCollect as ThisProgram;
/// # unsafe impl Grouped<ThisProgram> for StateMyType {
/// # fn member_id() -> ThisProgram {
/// # ThisProgram::Foo
/// # }
/// # }
/// use mingling_core::Routable;
///
/// struct StateMyType;
///
/// let my_type = StateMyType;
/// let process: ChainProcess<ThisProgram> = my_type.to_chain();
/// ```
fn to_chain(self) -> ChainProcess<Group>;
/// Converts the current type into a [`ChainProcess`] that can be used for the rendering pipeline.
///
/// # Return value
///
/// Returns a [`ChainProcess`] wrapping the current value,
/// which will be scheduled for execution in the rendering pipeline.
///
/// # Example
///
/// ```
/// # use mingling_core::{Grouped, ChainProcess};
/// # use mingling_core::MockProgramCollect as ThisProgram;
/// # unsafe impl Grouped<ThisProgram> for StateMyType {
/// # fn member_id() -> ThisProgram {
/// # ThisProgram::Foo
/// # }
/// # }
/// use mingling_core::Routable;
///
/// struct StateMyType;
///
/// let my_type = StateMyType;
/// let process: ChainProcess<ThisProgram> = my_type.to_render();
/// ```
fn to_render(self) -> ChainProcess<Group>;
}
impl<T, C> Routable<C> for T
where
C: ProgramCollect<Enum = C>,
T: Grouped<C> + Send,
{
fn to_chain(self) -> ChainProcess<C> {
AnyOutput::new(self).route_chain()
}
fn to_render(self) -> ChainProcess<C> {
AnyOutput::new(self).route_renderer()
}
}
|