diff options
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/command.rs | 100 | ||||
-rw-r--r-- | core/src/lib.rs | 12 | ||||
-rw-r--r-- | core/src/subscription.rs | 183 |
3 files changed, 0 insertions, 295 deletions
diff --git a/core/src/command.rs b/core/src/command.rs deleted file mode 100644 index e7885fb8..00000000 --- a/core/src/command.rs +++ /dev/null @@ -1,100 +0,0 @@ -use futures::future::{BoxFuture, 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`]. -/// -/// [`Command`]: struct.Command.html -pub struct Command<T> { - futures: Vec<BoxFuture<'static, T>>, -} - -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(), - } - } - - /// 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![future.map(f).boxed()], - } - } - - /// 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(); - - future.map(move |result| f(result)).boxed() - }) - .collect(), - } - } - - /// Creates a [`Command`] that performs the actions of all the given - /// commands. - /// - /// Once this command is run, all the commands will be exectued 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<'static, 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() - } -} diff --git a/core/src/lib.rs b/core/src/lib.rs index 821b09c1..51863327 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -32,15 +32,3 @@ pub use length::Length; pub use point::Point; pub use rectangle::Rectangle; pub use vector::Vector; - -#[cfg(feature = "command")] -mod command; - -#[cfg(feature = "command")] -pub use command::Command; - -#[cfg(feature = "subscription")] -pub mod subscription; - -#[cfg(feature = "subscription")] -pub use subscription::Subscription; diff --git a/core/src/subscription.rs b/core/src/subscription.rs deleted file mode 100644 index d9e7e388..00000000 --- a/core/src/subscription.rs +++ /dev/null @@ -1,183 +0,0 @@ -//! Listen to external events in your application. - -/// A request to listen to external events. -/// -/// Besides performing async actions on demand with [`Command`], most -/// applications also need to listen to external events passively. -/// -/// A [`Subscription`] is normally provided to some runtime, like a [`Command`], -/// and it will generate events as long as the user keeps requesting it. -/// -/// 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 -/// `Hasher`. -/// -/// [`Command`]: ../struct.Command.html -/// [`Subscription`]: struct.Subscription.html -pub struct Subscription<Hasher, Input, Output> { - recipes: Vec<Box<dyn Recipe<Hasher, Input, Output = Output>>>, -} - -impl<H, I, O> Subscription<H, I, O> -where - H: std::hash::Hasher, -{ - /// Returns an empty [`Subscription`] that will not produce any output. - /// - /// [`Subscription`]: struct.Subscription.html - pub fn none() -> Self { - Self { - recipes: Vec::new(), - } - } - - /// Creates a [`Subscription`] from a [`Recipe`] describing it. - /// - /// [`Subscription`]: struct.Subscription.html - /// [`Recipe`]: trait.Recipe.html - pub fn from_recipe( - recipe: impl Recipe<H, I, Output = O> + 'static, - ) -> Self { - Self { - recipes: vec![Box::new(recipe)], - } - } - - /// Batches all the provided subscriptions and returns the resulting - /// [`Subscription`]. - /// - /// [`Subscription`]: struct.Subscription.html - pub fn batch( - subscriptions: impl IntoIterator<Item = Subscription<H, I, O>>, - ) -> Self { - Self { - recipes: subscriptions - .into_iter() - .flat_map(|subscription| subscription.recipes) - .collect(), - } - } - - /// Returns the different recipes of the [`Subscription`]. - /// - /// [`Subscription`]: struct.Subscription.html - pub fn recipes(self) -> Vec<Box<dyn Recipe<H, I, Output = O>>> { - self.recipes - } - - /// Transforms the [`Subscription`] output with the given function. - /// - /// [`Subscription`]: struct.Subscription.html - pub fn map<A>( - mut self, - f: impl Fn(O) -> A + Send + Sync + 'static, - ) -> Subscription<H, I, A> - where - H: 'static, - I: 'static, - O: 'static, - A: 'static, - { - let function = std::sync::Arc::new(f); - - Subscription { - recipes: self - .recipes - .drain(..) - .map(|recipe| { - Box::new(Map::new(recipe, function.clone())) - as Box<dyn Recipe<H, I, Output = A>> - }) - .collect(), - } - } -} - -impl<I, O, H> std::fmt::Debug for Subscription<I, O, H> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Subscription").finish() - } -} - -/// The description of a [`Subscription`]. -/// -/// A [`Recipe`] is the internal definition of a [`Subscription`]. It is used -/// by runtimes to run and identify subscriptions. You can use it to create your -/// own! -/// -/// [`Subscription`]: struct.Subscription.html -/// [`Recipe`]: trait.Recipe.html -pub trait Recipe<Hasher: std::hash::Hasher, Input> { - /// The events that will be produced by a [`Subscription`] with this - /// [`Recipe`]. - /// - /// [`Subscription`]: struct.Subscription.html - /// [`Recipe`]: trait.Recipe.html - type Output; - - /// Hashes the [`Recipe`]. - /// - /// This is used by runtimes to uniquely identify a [`Subscription`]. - /// - /// [`Subscription`]: struct.Subscription.html - /// [`Recipe`]: trait.Recipe.html - fn hash(&self, state: &mut Hasher); - - /// Executes the [`Recipe`] and produces the stream of events of its - /// [`Subscription`]. - /// - /// It receives some generic `Input`, which is normally defined by runtimes. - /// - /// [`Subscription`]: struct.Subscription.html - /// [`Recipe`]: trait.Recipe.html - fn stream( - self: Box<Self>, - input: Input, - ) -> futures::stream::BoxStream<'static, Self::Output>; -} - -struct Map<Hasher, Input, A, B> { - recipe: Box<dyn Recipe<Hasher, Input, Output = A>>, - mapper: std::sync::Arc<dyn Fn(A) -> B + Send + Sync>, -} - -impl<H, I, A, B> Map<H, I, A, B> { - fn new( - recipe: Box<dyn Recipe<H, I, 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> -where - A: 'static, - B: 'static, - H: std::hash::Hasher, -{ - type Output = B; - - fn hash(&self, state: &mut H) { - use std::hash::Hash; - - std::any::TypeId::of::<B>().hash(state); - self.recipe.hash(state); - } - - fn stream( - self: Box<Self>, - input: I, - ) -> futures::stream::BoxStream<'static, Self::Output> { - use futures::StreamExt; - - let mapper = self.mapper; - - self.recipe - .stream(input) - .map(move |element| mapper(element)) - .boxed() - } -} |