From fac90e8152402dc5d233f0fed55daf761289bb23 Mon Sep 17 00:00:00 2001 From: Aceeri Date: Sun, 25 Dec 2022 00:39:27 +0000 Subject: [PATCH] Rework manual event iterator so we can actually name the type (#5735) # Objective - Be able to name the type that `ManualEventReader::iter/iter_with_id` returns and `EventReader::iter/iter_with_id` by proxy. Currently for the purpose of https://github.com/bevyengine/bevy/pull/5719 ## Solution - Create a custom `Iterator` type. --- crates/bevy_ecs/src/event.rs | 195 +++++++++++++++++++++++------------ 1 file changed, 128 insertions(+), 67 deletions(-) diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index b7ea293b211584..2b641bf48216b7 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -4,8 +4,7 @@ use crate as bevy_ecs; use crate::system::{Local, Res, ResMut, Resource, SystemParam}; use bevy_utils::tracing::trace; use std::ops::{Deref, DerefMut}; -use std::{fmt, hash::Hash, marker::PhantomData}; - +use std::{fmt, hash::Hash, iter::Chain, marker::PhantomData, slice::Iter}; /// A type that can be stored in an [`Events`] resource /// You can conveniently access events using the [`EventReader`] and [`EventWriter`] system parameter. /// @@ -194,18 +193,13 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> { /// Iterates over the events this [`EventReader`] has not seen yet. This updates the /// [`EventReader`]'s event counter, which means subsequent event reads will not include events /// that happened before now. - pub fn iter(&mut self) -> impl DoubleEndedIterator + ExactSizeIterator { - self.iter_with_id().map(|(event, _id)| event) + pub fn iter(&mut self) -> ManualEventIterator<'_, E> { + self.reader.iter(&self.events) } /// Like [`iter`](Self::iter), except also returning the [`EventId`] of the events. - pub fn iter_with_id( - &mut self, - ) -> impl DoubleEndedIterator)> + ExactSizeIterator)> - { - self.reader.iter_with_id(&self.events).inspect(|(_, id)| { - trace!("EventReader::iter() -> {}", id); - }) + pub fn iter_with_id(&mut self) -> ManualEventIteratorWithId<'_, E> { + self.reader.iter_with_id(&self.events) } /// Determines the number of events available to be read from this [`EventReader`] without consuming any. @@ -337,34 +331,16 @@ impl Default for ManualEventReader { #[allow(clippy::len_without_is_empty)] // Check fails since the is_empty implementation has a signature other than `(&self) -> bool` impl ManualEventReader { /// See [`EventReader::iter`] - pub fn iter<'a>( - &'a mut self, - events: &'a Events, - ) -> impl DoubleEndedIterator + ExactSizeIterator { - self.iter_with_id(events).map(|(e, _)| e) + pub fn iter<'a>(&'a mut self, events: &'a Events) -> ManualEventIterator<'a, E> { + self.iter_with_id(events).without_id() } /// See [`EventReader::iter_with_id`] pub fn iter_with_id<'a>( &'a mut self, events: &'a Events, - ) -> impl DoubleEndedIterator)> - + ExactSizeIterator)> { - let a_index = (self.last_event_count).saturating_sub(events.events_a.start_event_count); - let b_index = (self.last_event_count).saturating_sub(events.events_b.start_event_count); - let a = events.events_a.get(a_index..).unwrap_or_default(); - let b = events.events_b.get(b_index..).unwrap_or_default(); - - let unread_count = a.len() + b.len(); - // Ensure `len` is implemented correctly - debug_assert_eq!(unread_count, self.len(events)); - self.last_event_count = events.event_count - unread_count; - // Iterate the oldest first, then the newer events - let iterator = a.iter().chain(b.iter()); - iterator - .map(|e| (&e.event, e.event_id)) - .with_exact_size(unread_count) - .inspect(move |(_, id)| self.last_event_count = (id.id + 1).max(self.last_event_count)) + ) -> ManualEventIteratorWithId<'a, E> { + ManualEventIteratorWithId::new(self, events) } /// See [`EventReader::len`] @@ -392,57 +368,114 @@ impl ManualEventReader { } } -trait IteratorExt { - fn with_exact_size(self, len: usize) -> ExactSize - where - Self: Sized, - { - ExactSize::new(self, len) +pub struct ManualEventIterator<'a, E: Event> { + iter: ManualEventIteratorWithId<'a, E>, +} + +impl<'a, E: Event> Iterator for ManualEventIterator<'a, E> { + type Item = &'a E; + fn next(&mut self) -> Option { + self.iter.next().map(|(event, _)| event) + } + + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() } } -impl IteratorExt for I where I: Iterator {} -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[derive(Clone)] -struct ExactSize { - iter: I, - len: usize, +impl<'a, E: Event> ExactSizeIterator for ManualEventIterator<'a, E> { + fn len(&self) -> usize { + self.iter.len() + } } -impl ExactSize { - fn new(iter: I, len: usize) -> Self { - ExactSize { iter, len } + +impl<'a, E: Event> DoubleEndedIterator for ManualEventIterator<'a, E> { + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|(event, _)| event) } } -impl Iterator for ExactSize { - type Item = I::Item; +#[derive(Debug)] +pub struct ManualEventIteratorWithId<'a, E: Event> { + reader: &'a mut ManualEventReader, + chain: Chain>, Iter<'a, EventInstance>>, + unread: usize, +} + +fn event_trace(id: EventId) { + trace!("EventReader::iter() -> {}", id); +} - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|e| { - self.len -= 1; - e - }) +impl<'a, E: Event> ManualEventIteratorWithId<'a, E> { + pub fn new(reader: &'a mut ManualEventReader, events: &'a Events) -> Self { + let a_index = (reader.last_event_count).saturating_sub(events.events_a.start_event_count); + let b_index = (reader.last_event_count).saturating_sub(events.events_b.start_event_count); + let a = events.events_a.get(a_index..).unwrap_or_default(); + let b = events.events_b.get(b_index..).unwrap_or_default(); + + let unread_count = a.len() + b.len(); + // Ensure `len` is implemented correctly + debug_assert_eq!(unread_count, reader.len(events)); + reader.last_event_count = events.event_count - unread_count; + // Iterate the oldest first, then the newer events + let chain = a.iter().chain(b.iter()); + + Self { + reader, + chain, + unread: unread_count, + } + } + + /// Iterate over only the events. + pub fn without_id(self) -> ManualEventIterator<'a, E> { + ManualEventIterator { iter: self } + } +} + +impl<'a, E: Event> Iterator for ManualEventIteratorWithId<'a, E> { + type Item = (&'a E, EventId); + fn next(&mut self) -> Option { + match self + .chain + .next() + .map(|instance| (&instance.event, instance.event_id)) + { + Some(item) => { + event_trace(item.1); + self.reader.last_event_count += 1; + self.unread -= 1; + Some(item) + } + None => None, + } } - #[inline] fn size_hint(&self) -> (usize, Option) { - (self.len, Some(self.len)) + self.chain.size_hint() } } -impl DoubleEndedIterator for ExactSize { - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|e| { - self.len -= 1; - e - }) +impl<'a, E: Event> DoubleEndedIterator for ManualEventIteratorWithId<'a, E> { + fn next_back(&mut self) -> Option { + match self + .chain + .next_back() + .map(|instance| (&instance.event, instance.event_id)) + { + Some(item) => { + event_trace(item.1); + self.unread -= 1; + Some(item) + } + None => None, + } } } -impl ExactSizeIterator for ExactSize { + +impl<'a, E: Event> ExactSizeIterator for ManualEventIteratorWithId<'a, E> { fn len(&self) -> usize { - self.len + self.unread } } @@ -548,6 +581,34 @@ impl Events { ) -> impl DoubleEndedIterator + ExactSizeIterator { self.events_b.iter().map(|i| &i.event) } + + /// Get a specific event by id if it still exists in the events buffer. + pub fn get_event(&self, id: usize) -> Option<(&E, EventId)> { + if id < self.oldest_id() { + return None; + } + + let sequence = self.sequence(id); + let index = id.saturating_sub(sequence.start_event_count); + + sequence + .get(index) + .map(|instance| (&instance.event, instance.event_id)) + } + + /// Oldest id still in the events buffer. + pub fn oldest_id(&self) -> usize { + self.events_a.start_event_count + } + + /// Which event buffer is this event id a part of. + fn sequence(&self, id: usize) -> &EventSequence { + if id < self.events_b.start_event_count { + &self.events_a + } else { + &self.events_b + } + } } impl std::iter::Extend for Events {