diff options
author | 2020-03-26 14:54:47 +0100 | |
---|---|---|
committer | 2020-03-26 14:54:47 +0100 | |
commit | 138110f5967899365bb4e1409651dec43a46d123 (patch) | |
tree | bdfc34e2c43be95b060abd2a2c7f9e82ea6bcfd6 /futures/src/command.rs | |
parent | ec1f34ccea92b049a462664703351fe7e094fb02 (diff) | |
download | iced-138110f5967899365bb4e1409651dec43a46d123.tar.gz iced-138110f5967899365bb4e1409651dec43a46d123.tar.bz2 iced-138110f5967899365bb4e1409651dec43a46d123.zip |
Simplify `iced_futures::Command` implementation
Diffstat (limited to 'futures/src/command.rs')
-rw-r--r-- | futures/src/command.rs | 107 |
1 files changed, 99 insertions, 8 deletions
diff --git a/futures/src/command.rs b/futures/src/command.rs index 26f58fde..535ae4f7 100644 --- a/futures/src/command.rs +++ b/futures/src/command.rs @@ -1,11 +1,102 @@ -#[cfg(not(target_arch = "wasm32"))] -mod native; +use crate::BoxFuture; +use futures::future::{Future, FutureExt}; -#[cfg(not(target_arch = "wasm32"))] -pub use native::Command; +/// 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<BoxFuture<T>>, +} -#[cfg(target_arch = "wasm32")] -mod web; +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(), + } + } -#[cfg(target_arch = "wasm32")] -pub use web::Command; + /// 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 + Send, + f: impl Fn(T) -> A + 'static + Send, + ) -> Command<A> { + Command { + futures: vec![Box::pin(future.map(f))], + } + } + + /// 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, + ) -> Command<A> + where + T: 'static, + { + let f = std::sync::Arc::new(f); + + Command { + futures: self + .futures + .drain(..) + .map(|future| { + let f = f.clone(); + + Box::pin(future.map(move |result| f(result))) + as BoxFuture<A> + }) + .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<BoxFuture<T>> { + self.futures + } +} + +impl<T, A> From<A> for Command<T> +where + A: Future<Output = T> + 'static + Send, +{ + fn from(future: A) -> Self { + Self { + futures: vec![future.boxed()], + } + } +} + +impl<T> std::fmt::Debug for Command<T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Command").finish() + } +} |