Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Rework manual event iterator so we can actually name the type #5735

Closed
wants to merge 13 commits into from
195 changes: 128 additions & 67 deletions crates/bevy_ecs/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<E>`] resource
/// You can conveniently access events using the [`EventReader`] and [`EventWriter`] system parameter.
///
Expand Down Expand Up @@ -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<Item = &E> + ExactSizeIterator<Item = &E> {
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<Item = (&E, EventId<E>)> + ExactSizeIterator<Item = (&E, EventId<E>)>
{
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.
Expand Down Expand Up @@ -337,34 +331,16 @@ impl<E: Event> Default for ManualEventReader<E> {
#[allow(clippy::len_without_is_empty)] // Check fails since the is_empty implementation has a signature other than `(&self) -> bool`
impl<E: Event> ManualEventReader<E> {
/// See [`EventReader::iter`]
pub fn iter<'a>(
&'a mut self,
events: &'a Events<E>,
) -> impl DoubleEndedIterator<Item = &'a E> + ExactSizeIterator<Item = &'a E> {
self.iter_with_id(events).map(|(e, _)| e)
pub fn iter<'a>(&'a mut self, events: &'a Events<E>) -> 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<E>,
) -> impl DoubleEndedIterator<Item = (&'a E, EventId<E>)>
+ ExactSizeIterator<Item = (&'a E, EventId<E>)> {
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`]
Expand Down Expand Up @@ -392,57 +368,114 @@ impl<E: Event> ManualEventReader<E> {
}
}

trait IteratorExt {
fn with_exact_size(self, len: usize) -> ExactSize<Self>
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::Item> {
self.iter.next().map(|(event, _)| event)
}

fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<I> IteratorExt for I where I: Iterator {}

#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone)]
struct ExactSize<I> {
iter: I,
len: usize,
impl<'a, E: Event> ExactSizeIterator for ManualEventIterator<'a, E> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl<I> ExactSize<I> {
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::Item> {
self.iter.next_back().map(|(event, _)| event)
}
}

impl<I: Iterator> Iterator for ExactSize<I> {
type Item = I::Item;
#[derive(Debug)]
pub struct ManualEventIteratorWithId<'a, E: Event> {
reader: &'a mut ManualEventReader<E>,
chain: Chain<Iter<'a, EventInstance<E>>, Iter<'a, EventInstance<E>>>,
unread: usize,
}

fn event_trace<E: Event>(id: EventId<E>) {
trace!("EventReader::iter() -> {}", id);
}

#[inline]
fn next(&mut self) -> Option<I::Item> {
self.iter.next().map(|e| {
self.len -= 1;
e
})
impl<'a, E: Event> ManualEventIteratorWithId<'a, E> {
pub fn new(reader: &'a mut ManualEventReader<E>, events: &'a Events<E>) -> 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<E>);
fn next(&mut self) -> Option<Self::Item> {
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<usize>) {
(self.len, Some(self.len))
self.chain.size_hint()
}
}

impl<I: DoubleEndedIterator> DoubleEndedIterator for ExactSize<I> {
#[inline]
fn next_back(&mut self) -> Option<I::Item> {
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<Self::Item> {
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<I: Iterator> ExactSizeIterator for ExactSize<I> {

impl<'a, E: Event> ExactSizeIterator for ManualEventIteratorWithId<'a, E> {
fn len(&self) -> usize {
self.len
self.unread
}
}

Expand Down Expand Up @@ -548,6 +581,34 @@ impl<E: Event> Events<E> {
) -> impl DoubleEndedIterator<Item = &E> + ExactSizeIterator<Item = &E> {
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<E>)> {
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<E> {
if id < self.events_b.start_event_count {
&self.events_a
} else {
&self.events_b
}
}
}

impl<E: Event> std::iter::Extend<E> for Events<E> {
Expand Down