From 810b445f8d2f429e9ad07625f9b67dba09783d7a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 14 Jan 2022 19:43:06 +0700 Subject: Rewrite `events` and `events_with` with a new `Runner` abstraction --- native/src/subscription.rs | 72 +++++++++++++++++++++++++++++++++------ native/src/subscription/events.rs | 35 ------------------- 2 files changed, 62 insertions(+), 45 deletions(-) delete mode 100644 native/src/subscription/events.rs (limited to 'native') diff --git a/native/src/subscription.rs b/native/src/subscription.rs index 2950879c..7a1c5852 100644 --- a/native/src/subscription.rs +++ b/native/src/subscription.rs @@ -1,8 +1,12 @@ //! Listen to external events in your application. use crate::event::{self, Event}; use crate::Hasher; + +use iced_futures::futures::{self, Stream}; use iced_futures::BoxStream; +use std::hash::Hash; + /// A request to listen to external events. /// /// Besides performing async actions on demand with [`Command`], most @@ -29,20 +33,14 @@ pub type Tracker = pub use iced_futures::subscription::Recipe; -mod events; - -use events::Events; - /// Returns a [`Subscription`] to all the runtime events. /// /// This subscription will notify your application of any [`Event`] that was /// not captured by any widget. pub fn events() -> Subscription { - Subscription::from_recipe(Events { - f: |event, status| match status { - event::Status::Ignored => Some(event), - event::Status::Captured => None, - }, + events_with(|event, status| match status { + event::Status::Ignored => Some(event), + event::Status::Captured => None, }) } @@ -60,5 +58,59 @@ pub fn events_with( where Message: 'static + Send, { - Subscription::from_recipe(Events { f }) + #[derive(Debug, Clone, Copy, Hash)] + struct Events(u64); + + let hash = { + use std::hash::Hasher as _; + + let mut hasher = Hasher::default(); + + f.hash(&mut hasher); + + hasher.finish() + }; + + Subscription::from_recipe(Runner { + initial: Events(hash), + spawn: move |_, events| { + use futures::future; + use futures::stream::StreamExt; + + events.filter_map(move |(event, status)| { + future::ready(f(event, status)) + }) + }, + }) +} + +struct Runner +where + F: FnOnce(T, EventStream) -> S, + S: Stream, +{ + initial: T, + spawn: F, +} + +impl Recipe + for Runner +where + T: Clone + Hash + 'static, + F: FnOnce(T, EventStream) -> S, + S: Stream + Send + 'static, +{ + type Output = Message; + + fn hash(&self, state: &mut Hasher) { + std::any::TypeId::of::().hash(state); + + self.initial.hash(state); + } + + fn stream(self: Box, input: EventStream) -> BoxStream { + use futures::stream::StreamExt; + + (self.spawn)(self.initial, input).boxed() + } } diff --git a/native/src/subscription/events.rs b/native/src/subscription/events.rs deleted file mode 100644 index ca143bb3..00000000 --- a/native/src/subscription/events.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::event::{self, Event}; -use crate::subscription::{EventStream, Recipe}; -use crate::Hasher; -use iced_futures::futures::future; -use iced_futures::futures::StreamExt; -use iced_futures::BoxStream; - -pub struct Events { - pub(super) f: fn(Event, event::Status) -> Option, -} - -impl Recipe for Events -where - Message: 'static + Send, -{ - type Output = Message; - - fn hash(&self, state: &mut Hasher) { - use std::hash::Hash; - - struct Marker; - std::any::TypeId::of::().hash(state); - self.f.hash(state); - } - - fn stream( - self: Box, - event_stream: EventStream, - ) -> BoxStream { - let stream = event_stream.filter_map(move |(event, status)| { - future::ready((self.f)(event, status)) - }); - iced_futures::boxed_stream(stream) - } -} -- cgit