Skip to content

Commit

Permalink
Implement len and is_empty for EventReaders (#2969)
Browse files Browse the repository at this point in the history
# Objective

Provide a non-consuming method of checking if there are events in an `EventReader`.

Fixes #2967

## Solution

Implements the `len` and `is_empty` functions for `EventReader` and `ManualEventReader`, giving users the ability to check for the presence of new events without consuming any.
  • Loading branch information
GarettCooper committed Feb 3, 2022
1 parent af22cc1 commit 57dbd20
Showing 1 changed file with 87 additions and 1 deletion.
88 changes: 87 additions & 1 deletion crates/bevy_ecs/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ impl<T> Default for ManualEventReader<T> {
}
}

impl<T> ManualEventReader<T> {
#[allow(clippy::len_without_is_empty)] // Check fails since the is_empty implementation has a signature other than `(&self) -> bool`
impl<T: Resource> ManualEventReader<T> {
/// See [`EventReader::iter`]
pub fn iter<'a>(&'a mut self, events: &'a Events<T>) -> impl DoubleEndedIterator<Item = &'a T> {
internal_event_reader(&mut self.last_event_count, events).map(|(e, _)| e)
Expand All @@ -205,6 +206,16 @@ impl<T> ManualEventReader<T> {
) -> impl DoubleEndedIterator<Item = (&'a T, EventId<T>)> {
internal_event_reader(&mut self.last_event_count, events)
}

/// See [`EventReader::len`]
pub fn len(&self, events: &Events<T>) -> usize {
events.event_reader_len(self.last_event_count)
}

/// See [`EventReader::is_empty`]
pub fn is_empty(&self, events: &Events<T>) -> bool {
self.len(events) == 0
}
}

/// Like [`iter_with_id`](EventReader::iter_with_id) except not emitting any traces for read
Expand Down Expand Up @@ -253,6 +264,16 @@ impl<'w, 's, T: Resource> EventReader<'w, 's, T> {
(event, id)
})
}

/// Determines the number of events available to be read from this EventReader without consuming any.
pub fn len(&self) -> usize {
self.events.event_reader_len(self.last_event_count.0)
}

/// Determines if are any events available to be read without consuming any.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}

impl<T: Resource> Events<T> {
Expand Down Expand Up @@ -365,6 +386,29 @@ impl<T: Resource> Events<T> {
State::B => self.events_b.iter().map(map_instance_event),
}
}

/// Determines how many events are in the reader after the given `last_event_count` parameter
fn event_reader_len(&self, last_event_count: usize) -> usize {
let a_count = if last_event_count <= self.a_start_event_count {
self.events_a.len()
} else {
self.events_a
.len()
.checked_sub(last_event_count - self.a_start_event_count)
.unwrap_or_default()
};

let b_count = if last_event_count <= self.b_start_event_count {
self.events_b.len()
} else {
self.events_b
.len()
.checked_sub(last_event_count - self.b_start_event_count)
.unwrap_or_default()
};

a_count + b_count
}
}

impl<T> std::iter::Extend<T> for Events<T> {
Expand Down Expand Up @@ -566,4 +610,46 @@ mod tests {
events.update();
assert!(events.is_empty());
}

#[test]
fn test_event_reader_len_empty() {
let events = Events::<TestEvent>::default();
assert_eq!(events.get_reader().len(&events), 0);
assert!(events.get_reader().is_empty(&events));
}

#[test]
fn test_event_reader_len_filled() {
let mut events = Events::<TestEvent>::default();
events.send(TestEvent { i: 0 });
assert_eq!(events.get_reader().len(&events), 1);
assert!(!events.get_reader().is_empty(&events));
}

#[test]
fn test_event_reader_len_current() {
let mut events = Events::<TestEvent>::default();
events.send(TestEvent { i: 0 });
let reader = events.get_reader_current();
assert!(reader.is_empty(&events));
events.send(TestEvent { i: 0 });
assert_eq!(reader.len(&events), 1);
assert!(!reader.is_empty(&events));
}

#[test]
fn test_event_reader_len_update() {
let mut events = Events::<TestEvent>::default();
events.send(TestEvent { i: 0 });
events.send(TestEvent { i: 0 });
let reader = events.get_reader();
assert_eq!(reader.len(&events), 2);
events.update();
events.send(TestEvent { i: 0 });
assert_eq!(reader.len(&events), 3);
events.update();
assert_eq!(reader.len(&events), 1);
events.update();
assert!(reader.is_empty(&events));
}
}

0 comments on commit 57dbd20

Please sign in to comment.