Add get_at_mut to bevy_reflect::Map trait (#8691)

# Objective

Fixes #8596 

## Solution

Change interface of the trait Map. Adjust implementations of this trait

---

## Changelog

### Changed
- Interface of Map trait

### Added
- `Map::get_at_mut`

## Migration Guide

Every implementor of Map trait would need to implement `get_at_mut`.
Which, judging by changes in this PR, should be fairly trivial.
This commit is contained in:
Егор Куклин 2023-06-02 19:24:40 +07:00 committed by GitHub
parent fb148f7d65
commit 6b4c7d5d88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 0 deletions

View file

@ -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)
}

View file

@ -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<dyn Reflect>,
@ -496,6 +505,8 @@ pub fn map_apply<M: Map>(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::<String>()
.expect("Couldn't downcast to String");
let key = key_r
.downcast_ref::<usize>()
.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::<String>()
.expect("Couldn't downcast to String");
let key = key_r
.downcast_ref::<usize>()
.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::<String>()
.expect("Couldn't downcast to String"),
&values[0].to_owned()
);
assert!(map.get_at(2).is_none());
}
}