Skip to content

Commit 486ce72

Browse files
committed
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 #5719 ## Solution - Create a custom `Iterator` type.
1 parent c94af99 commit 486ce72

File tree

1 file changed

+128
-67
lines changed

1 file changed

+128
-67
lines changed

crates/bevy_ecs/src/event.rs

Lines changed: 128 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ use crate as bevy_ecs;
44
use crate::system::{Local, Res, ResMut, Resource, SystemParam};
55
use bevy_utils::tracing::trace;
66
use std::ops::{Deref, DerefMut};
7-
use std::{fmt, hash::Hash, marker::PhantomData};
8-
7+
use std::{fmt, hash::Hash, iter::Chain, marker::PhantomData, slice::Iter};
98
/// A type that can be stored in an [`Events<E>`] resource
109
/// You can conveniently access events using the [`EventReader`] and [`EventWriter`] system parameter.
1110
///
@@ -194,18 +193,13 @@ impl<'w, 's, E: Event> EventReader<'w, 's, E> {
194193
/// Iterates over the events this [`EventReader`] has not seen yet. This updates the
195194
/// [`EventReader`]'s event counter, which means subsequent event reads will not include events
196195
/// that happened before now.
197-
pub fn iter(&mut self) -> impl DoubleEndedIterator<Item = &E> + ExactSizeIterator<Item = &E> {
198-
self.iter_with_id().map(|(event, _id)| event)
196+
pub fn iter(&mut self) -> ManualEventIterator<'_, E> {
197+
self.reader.iter(&self.events)
199198
}
200199

201200
/// Like [`iter`](Self::iter), except also returning the [`EventId`] of the events.
202-
pub fn iter_with_id(
203-
&mut self,
204-
) -> impl DoubleEndedIterator<Item = (&E, EventId<E>)> + ExactSizeIterator<Item = (&E, EventId<E>)>
205-
{
206-
self.reader.iter_with_id(&self.events).inspect(|(_, id)| {
207-
trace!("EventReader::iter() -> {}", id);
208-
})
201+
pub fn iter_with_id(&mut self) -> ManualEventIteratorWithId<'_, E> {
202+
self.reader.iter_with_id(&self.events)
209203
}
210204

211205
/// Determines the number of events available to be read from this [`EventReader`] without consuming any.
@@ -337,34 +331,16 @@ impl<E: Event> Default for ManualEventReader<E> {
337331
#[allow(clippy::len_without_is_empty)] // Check fails since the is_empty implementation has a signature other than `(&self) -> bool`
338332
impl<E: Event> ManualEventReader<E> {
339333
/// See [`EventReader::iter`]
340-
pub fn iter<'a>(
341-
&'a mut self,
342-
events: &'a Events<E>,
343-
) -> impl DoubleEndedIterator<Item = &'a E> + ExactSizeIterator<Item = &'a E> {
344-
self.iter_with_id(events).map(|(e, _)| e)
334+
pub fn iter<'a>(&'a mut self, events: &'a Events<E>) -> ManualEventIterator<'a, E> {
335+
self.iter_with_id(events).without_id()
345336
}
346337

347338
/// See [`EventReader::iter_with_id`]
348339
pub fn iter_with_id<'a>(
349340
&'a mut self,
350341
events: &'a Events<E>,
351-
) -> impl DoubleEndedIterator<Item = (&'a E, EventId<E>)>
352-
+ ExactSizeIterator<Item = (&'a E, EventId<E>)> {
353-
let a_index = (self.last_event_count).saturating_sub(events.events_a.start_event_count);
354-
let b_index = (self.last_event_count).saturating_sub(events.events_b.start_event_count);
355-
let a = events.events_a.get(a_index..).unwrap_or_default();
356-
let b = events.events_b.get(b_index..).unwrap_or_default();
357-
358-
let unread_count = a.len() + b.len();
359-
// Ensure `len` is implemented correctly
360-
debug_assert_eq!(unread_count, self.len(events));
361-
self.last_event_count = events.event_count - unread_count;
362-
// Iterate the oldest first, then the newer events
363-
let iterator = a.iter().chain(b.iter());
364-
iterator
365-
.map(|e| (&e.event, e.event_id))
366-
.with_exact_size(unread_count)
367-
.inspect(move |(_, id)| self.last_event_count = (id.id + 1).max(self.last_event_count))
342+
) -> ManualEventIteratorWithId<'a, E> {
343+
ManualEventIteratorWithId::new(self, events)
368344
}
369345

370346
/// See [`EventReader::len`]
@@ -392,57 +368,114 @@ impl<E: Event> ManualEventReader<E> {
392368
}
393369
}
394370

395-
trait IteratorExt {
396-
fn with_exact_size(self, len: usize) -> ExactSize<Self>
397-
where
398-
Self: Sized,
399-
{
400-
ExactSize::new(self, len)
371+
pub struct ManualEventIterator<'a, E: Event> {
372+
iter: ManualEventIteratorWithId<'a, E>,
373+
}
374+
375+
impl<'a, E: Event> Iterator for ManualEventIterator<'a, E> {
376+
type Item = &'a E;
377+
fn next(&mut self) -> Option<Self::Item> {
378+
self.iter.next().map(|(event, _)| event)
379+
}
380+
381+
fn size_hint(&self) -> (usize, Option<usize>) {
382+
self.iter.size_hint()
401383
}
402384
}
403-
impl<I> IteratorExt for I where I: Iterator {}
404385

405-
#[must_use = "iterators are lazy and do nothing unless consumed"]
406-
#[derive(Clone)]
407-
struct ExactSize<I> {
408-
iter: I,
409-
len: usize,
386+
impl<'a, E: Event> ExactSizeIterator for ManualEventIterator<'a, E> {
387+
fn len(&self) -> usize {
388+
self.iter.len()
389+
}
410390
}
411-
impl<I> ExactSize<I> {
412-
fn new(iter: I, len: usize) -> Self {
413-
ExactSize { iter, len }
391+
392+
impl<'a, E: Event> DoubleEndedIterator for ManualEventIterator<'a, E> {
393+
fn next_back(&mut self) -> Option<Self::Item> {
394+
self.iter.next_back().map(|(event, _)| event)
414395
}
415396
}
416397

417-
impl<I: Iterator> Iterator for ExactSize<I> {
418-
type Item = I::Item;
398+
#[derive(Debug)]
399+
pub struct ManualEventIteratorWithId<'a, E: Event> {
400+
reader: &'a mut ManualEventReader<E>,
401+
chain: Chain<Iter<'a, EventInstance<E>>, Iter<'a, EventInstance<E>>>,
402+
unread: usize,
403+
}
404+
405+
fn event_trace<E: Event>(id: EventId<E>) {
406+
trace!("EventReader::iter() -> {}", id);
407+
}
419408

420-
#[inline]
421-
fn next(&mut self) -> Option<I::Item> {
422-
self.iter.next().map(|e| {
423-
self.len -= 1;
424-
e
425-
})
409+
impl<'a, E: Event> ManualEventIteratorWithId<'a, E> {
410+
pub fn new(reader: &'a mut ManualEventReader<E>, events: &'a Events<E>) -> Self {
411+
let a_index = (reader.last_event_count).saturating_sub(events.events_a.start_event_count);
412+
let b_index = (reader.last_event_count).saturating_sub(events.events_b.start_event_count);
413+
let a = events.events_a.get(a_index..).unwrap_or_default();
414+
let b = events.events_b.get(b_index..).unwrap_or_default();
415+
416+
let unread_count = a.len() + b.len();
417+
// Ensure `len` is implemented correctly
418+
debug_assert_eq!(unread_count, reader.len(events));
419+
reader.last_event_count = events.event_count - unread_count;
420+
// Iterate the oldest first, then the newer events
421+
let chain = a.iter().chain(b.iter());
422+
423+
Self {
424+
reader,
425+
chain,
426+
unread: unread_count,
427+
}
428+
}
429+
430+
/// Iterate over only the events.
431+
pub fn without_id(self) -> ManualEventIterator<'a, E> {
432+
ManualEventIterator { iter: self }
433+
}
434+
}
435+
436+
impl<'a, E: Event> Iterator for ManualEventIteratorWithId<'a, E> {
437+
type Item = (&'a E, EventId<E>);
438+
fn next(&mut self) -> Option<Self::Item> {
439+
match self
440+
.chain
441+
.next()
442+
.map(|instance| (&instance.event, instance.event_id))
443+
{
444+
Some(item) => {
445+
event_trace(item.1);
446+
self.reader.last_event_count += 1;
447+
self.unread -= 1;
448+
Some(item)
449+
}
450+
None => None,
451+
}
426452
}
427453

428-
#[inline]
429454
fn size_hint(&self) -> (usize, Option<usize>) {
430-
(self.len, Some(self.len))
455+
self.chain.size_hint()
431456
}
432457
}
433458

434-
impl<I: DoubleEndedIterator> DoubleEndedIterator for ExactSize<I> {
435-
#[inline]
436-
fn next_back(&mut self) -> Option<I::Item> {
437-
self.iter.next_back().map(|e| {
438-
self.len -= 1;
439-
e
440-
})
459+
impl<'a, E: Event> DoubleEndedIterator for ManualEventIteratorWithId<'a, E> {
460+
fn next_back(&mut self) -> Option<Self::Item> {
461+
match self
462+
.chain
463+
.next_back()
464+
.map(|instance| (&instance.event, instance.event_id))
465+
{
466+
Some(item) => {
467+
event_trace(item.1);
468+
self.unread -= 1;
469+
Some(item)
470+
}
471+
None => None,
472+
}
441473
}
442474
}
443-
impl<I: Iterator> ExactSizeIterator for ExactSize<I> {
475+
476+
impl<'a, E: Event> ExactSizeIterator for ManualEventIteratorWithId<'a, E> {
444477
fn len(&self) -> usize {
445-
self.len
478+
self.unread
446479
}
447480
}
448481

@@ -548,6 +581,34 @@ impl<E: Event> Events<E> {
548581
) -> impl DoubleEndedIterator<Item = &E> + ExactSizeIterator<Item = &E> {
549582
self.events_b.iter().map(|i| &i.event)
550583
}
584+
585+
/// Get a specific event by id if it still exists in the events buffer.
586+
pub fn get_event(&self, id: usize) -> Option<(&E, EventId<E>)> {
587+
if id < self.oldest_id() {
588+
return None;
589+
}
590+
591+
let sequence = self.sequence(id);
592+
let index = id.saturating_sub(sequence.start_event_count);
593+
594+
sequence
595+
.get(index)
596+
.map(|instance| (&instance.event, instance.event_id))
597+
}
598+
599+
/// Oldest id still in the events buffer.
600+
pub fn oldest_id(&self) -> usize {
601+
self.events_a.start_event_count
602+
}
603+
604+
/// Which event buffer is this event id a part of.
605+
fn sequence(&self, id: usize) -> &EventSequence<E> {
606+
if id < self.events_b.start_event_count {
607+
&self.events_a
608+
} else {
609+
&self.events_b
610+
}
611+
}
551612
}
552613

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

0 commit comments

Comments
 (0)