diff options
author | 2020-01-20 09:49:17 +0100 | |
---|---|---|
committer | 2020-01-20 09:49:17 +0100 | |
commit | f14009601e270e43bdf29b8f4842cf136fbbd8b9 (patch) | |
tree | fabfb4d9dced45d28b9fb65be629b40ecda3b402 /futures/src | |
parent | 03da887339e3d0590dc84238431b61c211f7cf7e (diff) | |
download | iced-f14009601e270e43bdf29b8f4842cf136fbbd8b9.tar.gz iced-f14009601e270e43bdf29b8f4842cf136fbbd8b9.tar.bz2 iced-f14009601e270e43bdf29b8f4842cf136fbbd8b9.zip |
Write documentation for `iced_futures`
Diffstat (limited to 'futures/src')
-rw-r--r-- | futures/src/executor.rs | 13 | ||||
-rw-r--r-- | futures/src/executor/async_std.rs | 2 | ||||
-rw-r--r-- | futures/src/executor/null.rs | 2 | ||||
-rw-r--r-- | futures/src/executor/thread_pool.rs | 1 | ||||
-rw-r--r-- | futures/src/executor/tokio.rs | 1 | ||||
-rw-r--r-- | futures/src/lib.rs | 6 | ||||
-rw-r--r-- | futures/src/runtime.rs | 45 | ||||
-rw-r--r-- | futures/src/subscription.rs | 39 | ||||
-rw-r--r-- | futures/src/subscription/tracker.rs | 36 |
9 files changed, 126 insertions, 19 deletions
diff --git a/futures/src/executor.rs b/futures/src/executor.rs index b2ff043e..c2b9cc72 100644 --- a/futures/src/executor.rs +++ b/futures/src/executor.rs @@ -29,13 +29,26 @@ pub use wasm_bindgen::WasmBindgen; use futures::Future; +/// A type that can run futures. pub trait Executor: Sized { + /// Creates a new [`Executor`]. + /// + /// [`Executor`]: trait.Executor.html fn new() -> Result<Self, futures::io::Error> where Self: Sized; + /// Spawns a future in the [`Executor`]. + /// + /// [`Executor`]: trait.Executor.html fn spawn(&self, future: impl Future<Output = ()> + Send + 'static); + /// Runs the given closure inside the [`Executor`]. + /// + /// Some executors, like `tokio`, require some global state to be in place + /// before creating futures. This method can be leveraged to set up this + /// global state, call a function, restore the state, and obtain the result + /// of the call. fn enter<R>(&self, f: impl FnOnce() -> R) -> R { f() } diff --git a/futures/src/executor/async_std.rs b/futures/src/executor/async_std.rs index b056b23d..641dfbd2 100644 --- a/futures/src/executor/async_std.rs +++ b/futures/src/executor/async_std.rs @@ -2,6 +2,8 @@ use crate::Executor; use futures::Future; +/// A type representing the `async-std` runtime. +#[derive(Debug)] pub struct AsyncStd; impl Executor for AsyncStd { diff --git a/futures/src/executor/null.rs b/futures/src/executor/null.rs index 722073bb..6d5cf982 100644 --- a/futures/src/executor/null.rs +++ b/futures/src/executor/null.rs @@ -2,6 +2,8 @@ use crate::Executor; use futures::Future; +/// An executor that drops all the futures, instead of spawning them. +#[derive(Debug)] pub struct Null; impl Executor for Null { diff --git a/futures/src/executor/thread_pool.rs b/futures/src/executor/thread_pool.rs index 6393d0d5..09cb4d21 100644 --- a/futures/src/executor/thread_pool.rs +++ b/futures/src/executor/thread_pool.rs @@ -2,6 +2,7 @@ use crate::Executor; use futures::Future; +/// A thread pool for futures. pub type ThreadPool = futures::executor::ThreadPool; impl Executor for futures::executor::ThreadPool { diff --git a/futures/src/executor/tokio.rs b/futures/src/executor/tokio.rs index aafa7e7b..4c609686 100644 --- a/futures/src/executor/tokio.rs +++ b/futures/src/executor/tokio.rs @@ -2,6 +2,7 @@ use crate::Executor; use futures::Future; +/// The `tokio` runtime. pub type Tokio = tokio::runtime::Runtime; impl Executor for Tokio { diff --git a/futures/src/lib.rs b/futures/src/lib.rs index 832a50f6..4872df10 100644 --- a/futures/src/lib.rs +++ b/futures/src/lib.rs @@ -1,3 +1,9 @@ +//! Asynchronous tasks for GUI programming, inspired by Elm. +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![deny(unused_results)] +#![deny(unsafe_code)] +#![deny(rust_2018_idioms)] pub use futures; mod command; diff --git a/futures/src/runtime.rs b/futures/src/runtime.rs index a508c46e..9fd9899a 100644 --- a/futures/src/runtime.rs +++ b/futures/src/runtime.rs @@ -4,6 +4,15 @@ use crate::{subscription, Command, Executor, Subscription}; use futures::Sink; use std::marker::PhantomData; +/// A batteries-included runtime of commands and subscriptions. +/// +/// If you have an [`Executor`], a [`Runtime`] can be leveraged to run any +/// [`Command`] or [`Subscription`] and get notified of the results! +/// +/// [`Runtime`]: struct.Runtime.html +/// [`Executor`]: executor/trait.Executor.html +/// [`Command`]: struct.Command.html +/// [`Subscription`]: subscription/struct.Subscription.html #[derive(Debug)] pub struct Runtime<Hasher, Event, Executor, Sender, Message> { executor: Executor, @@ -25,6 +34,13 @@ where + 'static, Message: Send + 'static, { + /// Creates a new empty [`Runtime`]. + /// + /// You need to provide: + /// - an [`Executor`] to spawn futures + /// - a `Sender` implementing `Sink` to receive the results + /// + /// [`Runtime`]: struct.Runtime.html pub fn new(executor: Executor, sender: Sender) -> Self { Self { executor, @@ -34,10 +50,24 @@ where } } + /// Runs the given closure inside the [`Executor`] of the [`Runtime`]. + /// + /// See [`Executor::enter`] to learn more. + /// + /// [`Executor`]: executor/trait.Executor.html + /// [`Runtime`]: struct.Runtime.html + /// [`Executor::enter`]: executor/trait.Executor.html#method.enter pub fn enter<R>(&self, f: impl FnOnce() -> R) -> R { self.executor.enter(f) } + /// Spawns a [`Command`] in the [`Runtime`]. + /// + /// The resulting `Message` will be forwarded to the `Sender` of the + /// [`Runtime`]. + /// + /// [`Command`]: struct.Command.html + /// [`Runtime`]: struct.Runtime.html pub fn spawn(&mut self, command: Command<Message>) { use futures::{FutureExt, SinkExt}; @@ -56,6 +86,14 @@ where } } + /// Tracks a [`Subscription`] in the [`Runtime`]. + /// + /// It will spawn new streams or close old ones as necessary! See + /// [`Tracker::update`] to learn more about this! + /// + /// [`Subscription`]: subscription/struct.Subscription.html + /// [`Runtime`]: struct.Runtime.html + /// [`Tracker::update`]: subscription/struct.Tracker.html#method.update pub fn track( &mut self, subscription: Subscription<Hasher, Event, Message>, @@ -68,6 +106,13 @@ where } } + /// Broadcasts an event to all the subscriptions currently alive in the + /// [`Runtime`]. + /// + /// See [`Tracker::broadcast`] to learn more. + /// + /// [`Runtime`]: struct.Runtime.html + /// [`Tracker::broadcast`]: subscription/struct.Tracker.html#method.broadcast pub fn broadcast(&mut self, event: Event) { self.subscriptions.broadcast(event); } diff --git a/futures/src/subscription.rs b/futures/src/subscription.rs index 87e51e48..b68444cd 100644 --- a/futures/src/subscription.rs +++ b/futures/src/subscription.rs @@ -16,16 +16,16 @@ use futures::stream::BoxStream; /// For instance, you can use a [`Subscription`] to listen to a WebSocket /// connection, keyboard presses, mouse events, time ticks, etc. /// -/// This type is normally aliased by runtimes with a specific `Input` and/or +/// This type is normally aliased by runtimes with a specific `Event` and/or /// `Hasher`. /// /// [`Command`]: ../struct.Command.html /// [`Subscription`]: struct.Subscription.html -pub struct Subscription<Hasher, Input, Output> { - recipes: Vec<Box<dyn Recipe<Hasher, Input, Output = Output>>>, +pub struct Subscription<Hasher, Event, Output> { + recipes: Vec<Box<dyn Recipe<Hasher, Event, Output = Output>>>, } -impl<H, I, O> Subscription<H, I, O> +impl<H, E, O> Subscription<H, E, O> where H: std::hash::Hasher, { @@ -43,7 +43,7 @@ where /// [`Subscription`]: struct.Subscription.html /// [`Recipe`]: trait.Recipe.html pub fn from_recipe( - recipe: impl Recipe<H, I, Output = O> + 'static, + recipe: impl Recipe<H, E, Output = O> + 'static, ) -> Self { Self { recipes: vec![Box::new(recipe)], @@ -55,7 +55,7 @@ where /// /// [`Subscription`]: struct.Subscription.html pub fn batch( - subscriptions: impl IntoIterator<Item = Subscription<H, I, O>>, + subscriptions: impl IntoIterator<Item = Subscription<H, E, O>>, ) -> Self { Self { recipes: subscriptions @@ -68,7 +68,7 @@ where /// Returns the different recipes of the [`Subscription`]. /// /// [`Subscription`]: struct.Subscription.html - pub fn recipes(self) -> Vec<Box<dyn Recipe<H, I, Output = O>>> { + pub fn recipes(self) -> Vec<Box<dyn Recipe<H, E, Output = O>>> { self.recipes } @@ -78,10 +78,10 @@ where pub fn map<A>( mut self, f: impl Fn(O) -> A + Send + Sync + 'static, - ) -> Subscription<H, I, A> + ) -> Subscription<H, E, A> where H: 'static, - I: 'static, + E: 'static, O: 'static, A: 'static, { @@ -93,7 +93,7 @@ where .drain(..) .map(|recipe| { Box::new(Map::new(recipe, function.clone())) - as Box<dyn Recipe<H, I, Output = A>> + as Box<dyn Recipe<H, E, Output = A>> }) .collect(), } @@ -114,7 +114,7 @@ impl<I, O, H> std::fmt::Debug for Subscription<I, O, H> { /// /// [`Subscription`]: struct.Subscription.html /// [`Recipe`]: trait.Recipe.html -pub trait Recipe<Hasher: std::hash::Hasher, Input> { +pub trait Recipe<Hasher: std::hash::Hasher, Event> { /// The events that will be produced by a [`Subscription`] with this /// [`Recipe`]. /// @@ -133,31 +133,32 @@ pub trait Recipe<Hasher: std::hash::Hasher, Input> { /// Executes the [`Recipe`] and produces the stream of events of its /// [`Subscription`]. /// - /// It receives some generic `Input`, which is normally defined by runtimes. + /// It receives some stream of generic events, which is normally defined by + /// shells. /// /// [`Subscription`]: struct.Subscription.html /// [`Recipe`]: trait.Recipe.html fn stream( self: Box<Self>, - input: BoxStream<'static, Input>, + input: BoxStream<'static, Event>, ) -> BoxStream<'static, Self::Output>; } -struct Map<Hasher, Input, A, B> { - recipe: Box<dyn Recipe<Hasher, Input, Output = A>>, +struct Map<Hasher, Event, A, B> { + recipe: Box<dyn Recipe<Hasher, Event, Output = A>>, mapper: std::sync::Arc<dyn Fn(A) -> B + Send + Sync>, } -impl<H, I, A, B> Map<H, I, A, B> { +impl<H, E, A, B> Map<H, E, A, B> { fn new( - recipe: Box<dyn Recipe<H, I, Output = A>>, + recipe: Box<dyn Recipe<H, E, Output = A>>, mapper: std::sync::Arc<dyn Fn(A) -> B + Send + Sync + 'static>, ) -> Self { Map { recipe, mapper } } } -impl<H, I, A, B> Recipe<H, I> for Map<H, I, A, B> +impl<H, E, A, B> Recipe<H, E> for Map<H, E, A, B> where A: 'static, B: 'static, @@ -174,7 +175,7 @@ where fn stream( self: Box<Self>, - input: BoxStream<'static, I>, + input: BoxStream<'static, E>, ) -> futures::stream::BoxStream<'static, Self::Output> { use futures::StreamExt; diff --git a/futures/src/subscription/tracker.rs b/futures/src/subscription/tracker.rs index a942b619..c8a1ee18 100644 --- a/futures/src/subscription/tracker.rs +++ b/futures/src/subscription/tracker.rs @@ -4,6 +4,11 @@ use futures::{future::BoxFuture, sink::Sink}; use std::collections::HashMap; use std::marker::PhantomData; +/// A registry of subscription streams. +/// +/// If you have an application that continuously returns a [`Subscription`], +/// you can use a [`Tracker`] to keep track of the different recipes and keep +/// its executions alive. #[derive(Debug)] pub struct Tracker<Hasher, Event> { subscriptions: HashMap<u64, Execution<Event>>, @@ -21,6 +26,9 @@ where Hasher: std::hash::Hasher + Default, Event: 'static + Send + Clone, { + /// Creates a new empty [`Tracker`]. + /// + /// [`Tracker`]: struct.Tracker.html pub fn new() -> Self { Self { subscriptions: HashMap::new(), @@ -28,6 +36,26 @@ where } } + /// Updates the [`Tracker`] with the given [`Subscription`]. + /// + /// A [`Subscription`] can cause new streams to be spawned or old streams + /// to be closed. + /// + /// The [`Tracker`] keeps track of these streams between calls to this + /// method: + /// + /// - If the provided [`Subscription`] contains a new [`Recipe`] that is + /// currently not being run, it will spawn a new stream and keep it alive. + /// - On the other hand, if a [`Recipe`] is currently in execution and the + /// provided [`Subscription`] does not contain it anymore, then the + /// [`Tracker`] will close and drop the relevant stream. + /// + /// It returns a list of futures that need to be spawned to materialize + /// the [`Tracker`] changes. + /// + /// [`Tracker`]: struct.Tracker.html + /// [`Subscription`]: struct.Subscription.html + /// [`Recipe`]: trait.Recipe.html pub fn update<Message, Receiver>( &mut self, subscription: Subscription<Hasher, Event, Message>, @@ -96,6 +124,14 @@ where futures } + /// Broadcasts an event to the subscriptions currently alive. + /// + /// A subscription's [`Recipe::stream`] always receives a stream of events + /// as input. This stream can be used by some subscription to listen to + /// shell events. + /// + /// This method publishes the given event to all the subscription streams + /// currently open. pub fn broadcast(&mut self, event: Event) { self.subscriptions .values_mut() |