diff options
Diffstat (limited to '')
-rw-r--r-- | futures/src/command/web.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/futures/src/command/web.rs b/futures/src/command/web.rs new file mode 100644 index 00000000..11b46b90 --- /dev/null +++ b/futures/src/command/web.rs @@ -0,0 +1,101 @@ +use futures::future::{Future, FutureExt}; +use std::pin::Pin; + +/// A collection of async operations. +/// +/// You should be able to turn a future easily into a [`Command`], either by +/// using the `From` trait or [`Command::perform`]. +/// +/// [`Command`]: struct.Command.html +pub struct Command<T> { + futures: Vec<Pin<Box<dyn Future<Output = T> + 'static>>>, +} + +impl<T> Command<T> { + /// Creates an empty [`Command`]. + /// + /// In other words, a [`Command`] that does nothing. + /// + /// [`Command`]: struct.Command.html + pub fn none() -> Self { + Self { + futures: Vec::new(), + } + } + + /// Creates a [`Command`] that performs the action of the given future. + /// + /// [`Command`]: struct.Command.html + pub fn perform<A>( + future: impl Future<Output = T> + 'static, + f: impl Fn(T) -> A + 'static, + ) -> Command<A> { + Command { + futures: vec![future.map(f).boxed_local()], + } + } + + /// Applies a transformation to the result of a [`Command`]. + /// + /// [`Command`]: struct.Command.html + pub fn map<A>( + mut self, + f: impl Fn(T) -> A + 'static + Send + Sync + Unpin, + ) -> Command<A> + where + T: 'static, + { + let f = std::sync::Arc::new(f); + + Command { + futures: self + .futures + .drain(..) + .map(|future| { + let f = f.clone(); + + future.map(move |result| f(result)).boxed_local() + }) + .collect(), + } + } + + /// Creates a [`Command`] that performs the actions of all the given + /// commands. + /// + /// Once this command is run, all the commands will be executed at once. + /// + /// [`Command`]: struct.Command.html + pub fn batch(commands: impl IntoIterator<Item = Command<T>>) -> Self { + Self { + futures: commands + .into_iter() + .flat_map(|command| command.futures) + .collect(), + } + } + + /// Converts a [`Command`] into its underlying list of futures. + /// + /// [`Command`]: struct.Command.html + pub fn futures(self) -> Vec<Pin<Box<dyn Future<Output = T> + 'static>>> { + self.futures + } +} + +impl<T, A> From<A> for Command<T> +where + A: Future<Output = T> + 'static, +{ + fn from(future: A) -> Self { + Self { + futures: vec![future.boxed_local()], + } + } +} + +impl<T> std::fmt::Debug for Command<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Command").finish() + } +} |