diff options
Diffstat (limited to 'futures')
| -rw-r--r-- | futures/Cargo.toml | 5 | ||||
| -rw-r--r-- | futures/src/command.rs | 52 | ||||
| -rw-r--r-- | futures/src/lib.rs | 7 | ||||
| -rw-r--r-- | futures/src/time.rs | 70 | 
4 files changed, 132 insertions, 2 deletions
| diff --git a/futures/Cargo.toml b/futures/Cargo.toml index e0815d9d..275d0391 100644 --- a/futures/Cargo.toml +++ b/futures/Cargo.toml @@ -1,6 +1,6 @@  [package]  name = "iced_futures" -version = "0.1.1" +version = "0.1.2"  authors = ["Héctor Ramón Jiménez <hector0193@gmail.com>"]  edition = "2018"  description = "Commands, subscriptions, and runtimes for Iced" @@ -22,11 +22,12 @@ version = "0.3"  [target.'cfg(not(target_arch = "wasm32"))'.dependencies.tokio]  version = "0.2"  optional = true -features = ["rt-core", "rt-threaded"] +features = ["rt-core", "rt-threaded", "time", "stream"]  [target.'cfg(not(target_arch = "wasm32"))'.dependencies.async-std]  version = "1.0"  optional = true +features = ["unstable"]  [target.'cfg(target_arch = "wasm32")'.dependencies]  wasm-bindgen-futures = "0.4" diff --git a/futures/src/command.rs b/futures/src/command.rs index d4f99b82..063e9b68 100644 --- a/futures/src/command.rs +++ b/futures/src/command.rs @@ -27,6 +27,7 @@ impl<T> Command<T> {      /// Creates a [`Command`] that performs the action of the given future.      ///      /// [`Command`]: struct.Command.html +    #[cfg(not(target_arch = "wasm32"))]      pub fn perform<A>(          future: impl Future<Output = T> + 'static + Send,          f: impl Fn(T) -> A + 'static + Send, @@ -36,9 +37,23 @@ impl<T> Command<T> {          }      } +    /// Creates a [`Command`] that performs the action of the given future. +    /// +    /// [`Command`]: struct.Command.html +    #[cfg(target_arch = "wasm32")] +    pub fn perform<A>( +        future: impl Future<Output = T> + 'static, +        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 +    #[cfg(not(target_arch = "wasm32"))]      pub fn map<A>(          mut self,          f: impl Fn(T) -> A + 'static + Send + Sync, @@ -62,6 +77,30 @@ impl<T> Command<T> {          }      } +    /// Applies a transformation to the result of a [`Command`]. +    /// +    /// [`Command`]: struct.Command.html +    #[cfg(target_arch = "wasm32")] +    pub fn map<A>(mut self, f: impl Fn(T) -> A + 'static) -> Command<A> +    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<A> +                }) +                .collect(), +        } +    } +      /// Creates a [`Command`] that performs the actions of all the given      /// commands.      /// @@ -85,6 +124,7 @@ impl<T> Command<T> {      }  } +#[cfg(not(target_arch = "wasm32"))]  impl<T, A> From<A> for Command<T>  where      A: Future<Output = T> + 'static + Send, @@ -96,6 +136,18 @@ where      }  } +#[cfg(target_arch = "wasm32")] +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() diff --git a/futures/src/lib.rs b/futures/src/lib.rs index 966a9cdc..46fc59fc 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -14,6 +14,13 @@ mod runtime;  pub mod executor;  pub mod subscription; +#[cfg(all( +    any(feature = "tokio", feature = "async-std"), +    not(target_arch = "wasm32") +))] +#[cfg_attr(docsrs, doc(cfg(any(feature = "tokio", feature = "async-std"))))] +pub mod time; +  pub use command::Command;  pub use executor::Executor;  pub use runtime::Runtime; diff --git a/futures/src/time.rs b/futures/src/time.rs new file mode 100644 index 00000000..e87b4a83 --- /dev/null +++ b/futures/src/time.rs @@ -0,0 +1,70 @@ +//! Listen and react to time. +use crate::subscription::{self, Subscription}; + +/// Returns a [`Subscription`] that produces messages at a set interval. +/// +/// The first message is produced after a `duration`, and then continues to +/// produce more messages every `duration` after that. +/// +/// [`Subscription`]: ../subscription/struct.Subscription.html +pub fn every<H: std::hash::Hasher, E>( +    duration: std::time::Duration, +) -> Subscription<H, E, std::time::Instant> { +    Subscription::from_recipe(Every(duration)) +} + +struct Every(std::time::Duration); + +#[cfg(feature = "async-std")] +impl<H, E> subscription::Recipe<H, E> for Every +where +    H: std::hash::Hasher, +{ +    type Output = std::time::Instant; + +    fn hash(&self, state: &mut H) { +        use std::hash::Hash; + +        std::any::TypeId::of::<Self>().hash(state); +        self.0.hash(state); +    } + +    fn stream( +        self: Box<Self>, +        _input: futures::stream::BoxStream<'static, E>, +    ) -> futures::stream::BoxStream<'static, Self::Output> { +        use futures::stream::StreamExt; + +        async_std::stream::interval(self.0) +            .map(|_| std::time::Instant::now()) +            .boxed() +    } +} + +#[cfg(all(feature = "tokio", not(feature = "async-std")))] +impl<H, E> subscription::Recipe<H, E> for Every +where +    H: std::hash::Hasher, +{ +    type Output = std::time::Instant; + +    fn hash(&self, state: &mut H) { +        use std::hash::Hash; + +        std::any::TypeId::of::<Self>().hash(state); +        self.0.hash(state); +    } + +    fn stream( +        self: Box<Self>, +        _input: futures::stream::BoxStream<'static, E>, +    ) -> futures::stream::BoxStream<'static, Self::Output> { +        use futures::stream::StreamExt; + +        let start = tokio::time::Instant::now() + self.0; + +        tokio::time::interval_at(start, self.0) +            .map(|_| std::time::Instant::now()) +            .boxed() +    } +} | 
