From 76698ff2b5753e637b14533650c0d28e681be3c5 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 Sep 2021 19:21:49 +0700 Subject: Make `Command` implementations platform-specific This allows us to introduce a platform-specific `Action` to both `iced_native` and `iced_web` and remove the `Clipboard` from `Application::update` to maintain purity. Additionally, this should let us implement further actions to let users query and modify the shell environment (e.g. window, clipboard, and more!) --- futures/src/command.rs | 138 ------------------------------------------------- 1 file changed, 138 deletions(-) delete mode 100644 futures/src/command.rs (limited to 'futures/src/command.rs') diff --git a/futures/src/command.rs b/futures/src/command.rs deleted file mode 100644 index b06ab3f8..00000000 --- a/futures/src/command.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::BoxFuture; -use futures::future::{Future, FutureExt}; - -/// 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`]. -pub struct Command { - futures: Vec>, -} - -impl Command { - /// Creates an empty [`Command`]. - /// - /// In other words, a [`Command`] that does nothing. - pub fn none() -> Self { - Self { - futures: Vec::new(), - } - } - - /// Creates a [`Command`] that performs the action of the given future. - #[cfg(not(target_arch = "wasm32"))] - pub fn perform( - future: impl Future + 'static + Send, - f: impl Fn(T) -> A + 'static + Send, - ) -> Command { - Command { - futures: vec![Box::pin(future.map(f))], - } - } - - /// Creates a [`Command`] that performs the action of the given future. - #[cfg(target_arch = "wasm32")] - pub fn perform( - future: impl Future + 'static, - f: impl Fn(T) -> A + 'static + Send, - ) -> Command { - Command { - futures: vec![Box::pin(future.map(f))], - } - } - - /// Applies a transformation to the result of a [`Command`]. - #[cfg(not(target_arch = "wasm32"))] - pub fn map( - mut self, - f: impl Fn(T) -> A + 'static + Send + Sync, - ) -> Command - 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 - }) - .collect(), - } - } - - /// Applies a transformation to the result of a [`Command`]. - #[cfg(target_arch = "wasm32")] - pub fn map(mut self, f: impl Fn(T) -> A + 'static) -> Command - where - T: 'static, - { - let f = std::rc::Rc::new(f); - - Command { - futures: self - .futures - .drain(..) - .map(|future| { - let f = f.clone(); - - Box::pin(future.map(move |result| f(result))) - as BoxFuture - }) - .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. - pub fn batch(commands: impl IntoIterator>) -> Self { - Self { - futures: commands - .into_iter() - .flat_map(|command| command.futures) - .collect(), - } - } - - /// Converts a [`Command`] into its underlying list of futures. - pub fn futures(self) -> Vec> { - self.futures - } -} - -#[cfg(not(target_arch = "wasm32"))] -impl From for Command -where - A: Future + 'static + Send, -{ - fn from(future: A) -> Self { - Self { - futures: vec![future.boxed()], - } - } -} - -#[cfg(target_arch = "wasm32")] -impl From for Command -where - A: Future + 'static, -{ - fn from(future: A) -> Self { - Self { - futures: vec![future.boxed_local()], - } - } -} - -impl std::fmt::Debug for Command { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Command").finish() - } -} -- cgit From 6fce35393fb2dc3dcbc5f423fa8472f5ce1f7027 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 2 Sep 2021 15:50:00 +0700 Subject: Hide implementation details of `Command` in `iced_futures` --- futures/src/command.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 futures/src/command.rs (limited to 'futures/src/command.rs') diff --git a/futures/src/command.rs b/futures/src/command.rs new file mode 100644 index 00000000..d8adfe49 --- /dev/null +++ b/futures/src/command.rs @@ -0,0 +1,69 @@ +/// A set of asynchronous actions to be performed by some runtime. +#[derive(Debug)] +pub struct Command(Internal); + +#[derive(Debug)] +enum Internal { + None, + Single(T), + Batch(Vec), +} + +impl Command { + /// Creates an empty [`Command`]. + /// + /// In other words, a [`Command`] that does nothing. + pub const fn none() -> Self { + Self(Internal::None) + } + + /// Creates a [`Command`] that performs a single [`Action`]. + pub const fn single(action: T) -> Self { + Self(Internal::Single(action)) + } + + /// 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. + pub fn batch(commands: impl IntoIterator>) -> Self { + let mut batch = Vec::new(); + + for Command(command) in commands { + match command { + Internal::None => {} + Internal::Single(command) => batch.push(command), + Internal::Batch(commands) => batch.extend(commands), + } + } + + Self(Internal::Batch(batch)) + } + + /// Applies a transformation to the result of a [`Command`]. + pub fn map(self, f: impl Fn(T) -> A) -> Command + where + T: 'static, + { + let Command(command) = self; + + match command { + Internal::None => Command::none(), + Internal::Single(action) => Command::single(f(action)), + Internal::Batch(batch) => { + Command(Internal::Batch(batch.into_iter().map(f).collect())) + } + } + } + + /// Returns all of the actions of the [`Command`]. + pub fn actions(self) -> Vec { + let Command(command) = self; + + match command { + Internal::None => Vec::new(), + Internal::Single(action) => vec![action], + Internal::Batch(batch) => batch, + } + } +} -- cgit