mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 05:03:47 +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)]
|
#[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]
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue