mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 20:53:53 +00:00
Remove broken DoubleEndedIterator
impls on event iterators (#7469)
The `DoubleEndedIterator` impls produce incorrect results on subsequent calls to `iter()` if the iterator is only partially consumed. The following code shows what happens ```rust fn next_back_is_bad() { let mut events = Events::<TestEvent>::default(); events.send(TestEvent { i: 0 }); events.send(TestEvent { i: 1 }); events.send(TestEvent { i: 2 }); let mut reader = events.get_reader(); let mut iter = reader.iter(&events); assert_eq!(iter.next_back(), Some(&TestEvent { i: 2 })); assert_eq!(iter.next(), Some(&TestEvent { i: 0 })); let mut iter = reader.iter(&events); // `i: 2` event is returned twice! The `i: 1` event is missed. assert_eq!(iter.next(), Some(&TestEvent { i: 2 })); assert_eq!(iter.next(), None); } ``` I don't think this can be fixed without adding some very convoluted bookkeeping. ## Migration Guide `ManualEventIterator` and `ManualEventIteratorWithId` are no longer `DoubleEndedIterator`s. Co-authored-by: devil-ira <justthecooldude@gmail.com>
This commit is contained in:
parent
386763ecda
commit
32023a5f6a
3 changed files with 8 additions and 33 deletions
|
@ -390,12 +390,6 @@ impl<'a, E: Event> ExactSizeIterator for ManualEventIterator<'a, E> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Event> DoubleEndedIterator for ManualEventIterator<'a, E> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.iter.next_back().map(|(event, _)| event)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ManualEventIteratorWithId<'a, E: Event> {
|
||||
reader: &'a mut ManualEventReader<E>,
|
||||
|
@ -457,23 +451,6 @@ impl<'a, E: Event> Iterator for ManualEventIteratorWithId<'a, 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<'a, E: Event> ExactSizeIterator for ManualEventIteratorWithId<'a, E> {
|
||||
fn len(&self) -> usize {
|
||||
self.unread
|
||||
|
@ -577,9 +554,7 @@ impl<E: Event> Events<E> {
|
|||
/// between the last `update()` call and your call to `iter_current_update_events`.
|
||||
/// If events happen outside that window, they will not be handled. For example, any events that
|
||||
/// happen after this call and before the next `update()` call will be dropped.
|
||||
pub fn iter_current_update_events(
|
||||
&self,
|
||||
) -> impl DoubleEndedIterator<Item = &E> + ExactSizeIterator<Item = &E> {
|
||||
pub fn iter_current_update_events(&self) -> impl ExactSizeIterator<Item = &E> {
|
||||
self.events_b.iter().map(|i| &i.event)
|
||||
}
|
||||
|
||||
|
@ -837,8 +812,10 @@ mod tests {
|
|||
assert_eq!(iter.len(), 3);
|
||||
iter.next();
|
||||
assert_eq!(iter.len(), 2);
|
||||
iter.next_back();
|
||||
iter.next();
|
||||
assert_eq!(iter.len(), 1);
|
||||
iter.next();
|
||||
assert_eq!(iter.len(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -772,7 +772,7 @@ impl World {
|
|||
|
||||
/// Returns an iterator of entities that had components of type `T` removed
|
||||
/// since the last call to [`World::clear_trackers`].
|
||||
pub fn removed<T: Component>(&self) -> impl DoubleEndedIterator<Item = Entity> + '_ {
|
||||
pub fn removed<T: Component>(&self) -> impl Iterator<Item = Entity> + '_ {
|
||||
self.components
|
||||
.get_id(TypeId::of::<T>())
|
||||
.map(|component_id| self.removed_with_id(component_id))
|
||||
|
@ -782,10 +782,7 @@ impl World {
|
|||
|
||||
/// Returns an iterator of entities that had components with the given `component_id` removed
|
||||
/// since the last call to [`World::clear_trackers`].
|
||||
pub fn removed_with_id(
|
||||
&self,
|
||||
component_id: ComponentId,
|
||||
) -> impl DoubleEndedIterator<Item = Entity> + '_ {
|
||||
pub fn removed_with_id(&self, component_id: ComponentId) -> impl Iterator<Item = Entity> + '_ {
|
||||
self.removed_components
|
||||
.get(component_id)
|
||||
.map(|removed| removed.iter_current_update_events().cloned())
|
||||
|
|
|
@ -270,7 +270,8 @@ pub fn flex_node_system(
|
|||
}
|
||||
}
|
||||
|
||||
if scale_factor_events.iter().next_back().is_some() || ui_scale.is_changed() {
|
||||
if !scale_factor_events.is_empty() || ui_scale.is_changed() {
|
||||
scale_factor_events.clear();
|
||||
update_changed(&mut flex_surface, scale_factor, full_node_query);
|
||||
} else {
|
||||
update_changed(&mut flex_surface, scale_factor, node_query);
|
||||
|
|
Loading…
Reference in a new issue