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:
ira 2023-02-05 15:18:19 +00:00
parent 386763ecda
commit 32023a5f6a
3 changed files with 8 additions and 33 deletions

View file

@ -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)] #[derive(Debug)]
pub struct ManualEventIteratorWithId<'a, E: Event> { pub struct ManualEventIteratorWithId<'a, E: Event> {
reader: &'a mut ManualEventReader<E>, 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> { impl<'a, E: Event> ExactSizeIterator for ManualEventIteratorWithId<'a, E> {
fn len(&self) -> usize { fn len(&self) -> usize {
self.unread self.unread
@ -577,9 +554,7 @@ impl<E: Event> Events<E> {
/// between the last `update()` call and your call to `iter_current_update_events`. /// 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 /// 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. /// happen after this call and before the next `update()` call will be dropped.
pub fn iter_current_update_events( pub fn iter_current_update_events(&self) -> impl ExactSizeIterator<Item = &E> {
&self,
) -> impl DoubleEndedIterator<Item = &E> + ExactSizeIterator<Item = &E> {
self.events_b.iter().map(|i| &i.event) self.events_b.iter().map(|i| &i.event)
} }
@ -837,8 +812,10 @@ mod tests {
assert_eq!(iter.len(), 3); assert_eq!(iter.len(), 3);
iter.next(); iter.next();
assert_eq!(iter.len(), 2); assert_eq!(iter.len(), 2);
iter.next_back(); iter.next();
assert_eq!(iter.len(), 1); assert_eq!(iter.len(), 1);
iter.next();
assert_eq!(iter.len(), 0);
} }
#[test] #[test]

View file

@ -772,7 +772,7 @@ impl World {
/// Returns an iterator of entities that had components of type `T` removed /// Returns an iterator of entities that had components of type `T` removed
/// since the last call to [`World::clear_trackers`]. /// 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 self.components
.get_id(TypeId::of::<T>()) .get_id(TypeId::of::<T>())
.map(|component_id| self.removed_with_id(component_id)) .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 /// Returns an iterator of entities that had components with the given `component_id` removed
/// since the last call to [`World::clear_trackers`]. /// since the last call to [`World::clear_trackers`].
pub fn removed_with_id( pub fn removed_with_id(&self, component_id: ComponentId) -> impl Iterator<Item = Entity> + '_ {
&self,
component_id: ComponentId,
) -> impl DoubleEndedIterator<Item = Entity> + '_ {
self.removed_components self.removed_components
.get(component_id) .get(component_id)
.map(|removed| removed.iter_current_update_events().cloned()) .map(|removed| removed.iter_current_update_events().cloned())

View file

@ -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); update_changed(&mut flex_surface, scale_factor, full_node_query);
} else { } else {
update_changed(&mut flex_surface, scale_factor, node_query); update_changed(&mut flex_surface, scale_factor, node_query);