command_engine/shared/
command.rs

1use super::*;
2
3/// Each type implementing `Command` trait must also implement `CommandInfo` which is used only to
4/// retrieve information about the Command.
5pub trait CommandInfo {
6    fn caller(&self) -> &'static str;
7}
8
9#[cfg(feature = "async")]
10mod command_async {
11    use super::*;
12    use std::future::Future;
13    use std::pin::Pin;
14    use std::task::{Context, Poll};
15
16    /// Example:
17    /// ```rust
18    /// use command_engine::{Command, CommandInfo, Instruction, OutputFuture, IntoOutputFuture};
19    ///
20    /// struct MyCommand1;
21    ///
22    /// impl CommandInfo for MyCommand1 {
23    ///     fn caller(&self) -> &'static str {
24    ///         "command1"
25    ///     }
26    /// }
27    ///
28    /// impl Command for MyCommand1 {
29    ///     type Output = ();
30    ///
31    ///     fn on_execute<'a>(&self, _ins: Instruction<'a>) -> OutputFuture<'a, Self::Output> {
32    ///         async move {
33    ///             ()
34    ///         }.output_future()
35    ///     }
36    /// }
37    /// ```
38    pub trait Command: CommandInfo + Send + Sync + 'static {
39        type Output;
40
41        fn on_execute<'a>(&self, ins: Instruction<'a>) -> OutputFuture<'a, Self::Output>;
42    }
43
44    pub struct OutputFuture<'a, Output> {
45        future: Pin<Box<dyn Future<Output=Output> + Send + 'a>>,
46    }
47
48    impl<'a, Output> Future for OutputFuture<'a, Output> {
49        type Output = Output;
50
51        fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
52            self.future.as_mut().poll(cx)
53        }
54    }
55
56    pub trait IntoOutputFuture<'a, Output> {
57        fn output_future(self) -> OutputFuture<'a, Output>;
58    }
59
60    impl<'a, F: Future<Output=Output> + Send + 'a, Output> IntoOutputFuture<'a, Output> for F {
61        fn output_future(self) -> OutputFuture<'a, Output> {
62            OutputFuture {
63                future: Box::pin(self),
64            }
65        }
66    }
67}
68
69#[cfg(not(feature = "async"))]
70mod command_sync {
71    use super::*;
72
73    /// Example:
74    /// ```rust
75    /// use command_engine::{Command, CommandInfo, Instruction};
76    ///
77    /// struct MyCommand1;
78    ///
79    /// impl CommandInfo for MyCommand1 {
80    ///     fn caller(&self) -> &'static str {
81    ///         "command1"
82    ///     }
83    /// }
84    ///
85    /// impl Command for MyCommand1 {
86    ///     type Output = ();
87    ///
88    ///     fn on_execute(&self, _ins: Instruction) -> Self::Output {
89    ///         ()
90    ///     }
91    /// }
92    /// ```
93    pub trait Command: CommandInfo + 'static {
94        type Output;
95
96        fn on_execute(&self, ins: Instruction) -> Self::Output;
97    }
98}
99
100#[cfg(feature = "async")]
101pub use command_async::*;
102
103#[cfg(not(feature = "async"))]
104pub use command_sync::*;
105