summaryrefslogtreecommitdiffstats
path: root/futures
diff options
context:
space:
mode:
Diffstat (limited to 'futures')
-rw-r--r--futures/Cargo.toml5
-rw-r--r--futures/src/command.rs52
-rw-r--r--futures/src/lib.rs7
-rw-r--r--futures/src/time.rs70
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()
+ }
+}