diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index e970b0f67d..4637d48169 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -374,6 +374,12 @@ macro_rules! impl_reflect_for_hashmap { .map(|(key, value)| (key as &dyn Reflect, value as &dyn Reflect)) } + fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)> { + self.iter_mut() + .nth(index) + .map(|(key, value)| (key as &dyn Reflect, value as &mut dyn Reflect)) + } + fn len(&self) -> usize { Self::len(self) } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index d7ba2665fe..4dfedd2dbc 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -52,6 +52,9 @@ pub trait Map: Reflect { /// Returns the key-value pair at `index` by reference, or `None` if out of bounds. fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)>; + /// Returns the key-value pair at `index` by reference where the value is a mutable reference, or `None` if out of bounds. + fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)>; + /// Returns the number of elements in the map. fn len(&self) -> usize; @@ -254,6 +257,12 @@ impl Map for DynamicMap { .map(|(key, value)| (&**key, &**value)) } + fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)> { + self.values + .get_mut(index) + .map(|(key, value)| (&**key, &mut **value)) + } + fn insert_boxed( &mut self, key: Box, @@ -496,6 +505,8 @@ pub fn map_apply(a: &mut M, b: &dyn Reflect) { #[cfg(test)] mod tests { use super::DynamicMap; + use super::Map; + use crate::reflect::Reflect; #[test] fn test_into_iter() { @@ -516,4 +527,58 @@ mod tests { assert_eq!(expected[index], value); } } + + #[test] + fn test_map_get_at() { + let values = ["first", "second", "third"]; + let mut map = DynamicMap::default(); + map.insert(0usize, values[0].to_string()); + map.insert(1usize, values[1].to_string()); + map.insert(1usize, values[2].to_string()); + + let (key_r, value_r) = map.get_at(1).expect("Item wasn't found"); + let value = value_r + .downcast_ref::() + .expect("Couldn't downcast to String"); + let key = key_r + .downcast_ref::() + .expect("Couldn't downcast to usize"); + assert_eq!(key, &1usize); + assert_eq!(value, &values[2].to_owned()); + + assert!(map.get_at(2).is_none()); + map.remove(&1usize as &dyn Reflect); + assert!(map.get_at(1).is_none()); + } + + #[test] + fn test_map_get_at_mut() { + let values = ["first", "second", "third"]; + let mut map = DynamicMap::default(); + map.insert(0usize, values[0].to_string()); + map.insert(1usize, values[1].to_string()); + map.insert(1usize, values[2].to_string()); + + let (key_r, value_r) = map.get_at_mut(1).expect("Item wasn't found"); + let value = value_r + .downcast_mut::() + .expect("Couldn't downcast to String"); + let key = key_r + .downcast_ref::() + .expect("Couldn't downcast to usize"); + assert_eq!(key, &1usize); + assert_eq!(value, &mut values[2].to_owned()); + + *value = values[0].to_owned(); + + assert_eq!( + map.get(&1usize as &dyn Reflect) + .expect("Item wasn't found") + .downcast_ref::() + .expect("Couldn't downcast to String"), + &values[0].to_owned() + ); + + assert!(map.get_at(2).is_none()); + } }