diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index a22a24958d80ed..0ccebbd10a3e7e 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -10,14 +10,14 @@ use crate::{ use crate::utility::{reflect_hasher, GenericTypeInfoCell, NonGenericTypeInfoCell}; use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value}; +use bevy_utils::HashSet; use bevy_utils::{Duration, Instant}; -use bevy_utils::{HashMap, HashSet}; use std::{ any::Any, borrow::Cow, collections::VecDeque, ffi::OsString, - hash::{Hash, Hasher}, + hash::{BuildHasher, Hash, Hasher}, num::{ NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, @@ -347,188 +347,216 @@ impl_reflect_for_veclike!( VecDeque:: ); -impl Map for HashMap { - fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { - key.downcast_ref::() - .and_then(|key| HashMap::get(self, key)) - .map(|value| value as &dyn Reflect) - } +macro_rules! impl_reflect_for_hashmap { + ($ty:ty) => { + impl Map for $ty + where + K: FromReflect + Eq + Hash, + V: FromReflect, + S: BuildHasher + Send + Sync + 'static, + { + fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { + key.downcast_ref::() + .and_then(|key| Self::get(self, key)) + .map(|value| value as &dyn Reflect) + } - fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect> { - key.downcast_ref::() - .and_then(move |key| HashMap::get_mut(self, key)) - .map(|value| value as &mut dyn Reflect) - } + fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect> { + key.downcast_ref::() + .and_then(move |key| Self::get_mut(self, key)) + .map(|value| value as &mut dyn Reflect) + } - fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)> { - self.iter() - .nth(index) - .map(|(key, value)| (key as &dyn Reflect, value as &dyn Reflect)) - } + fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)> { + self.iter() + .nth(index) + .map(|(key, value)| (key as &dyn Reflect, value as &dyn Reflect)) + } - fn len(&self) -> usize { - Self::len(self) - } + fn len(&self) -> usize { + Self::len(self) + } - fn iter(&self) -> MapIter { - MapIter { - map: self, - index: 0, - } - } + fn iter(&self) -> MapIter { + MapIter { + map: self, + index: 0, + } + } - fn drain(self: Box) -> Vec<(Box, Box)> { - self.into_iter() - .map(|(key, value)| { - ( - Box::new(key) as Box, - Box::new(value) as Box, - ) - }) - .collect() - } + fn drain(self: Box) -> Vec<(Box, Box)> { + self.into_iter() + .map(|(key, value)| { + ( + Box::new(key) as Box, + Box::new(value) as Box, + ) + }) + .collect() + } + + fn clone_dynamic(&self) -> DynamicMap { + let mut dynamic_map = DynamicMap::default(); + dynamic_map.set_name(self.type_name().to_string()); + for (k, v) in self { + dynamic_map.insert_boxed(k.clone_value(), v.clone_value()); + } + dynamic_map + } - fn clone_dynamic(&self) -> DynamicMap { - let mut dynamic_map = DynamicMap::default(); - dynamic_map.set_name(self.type_name().to_string()); - for (k, v) in self { - dynamic_map.insert_boxed(k.clone_value(), v.clone_value()); + fn insert_boxed( + &mut self, + key: Box, + value: Box, + ) -> Option> { + let key = K::take_from_reflect(key).unwrap_or_else(|key| { + panic!( + "Attempted to insert invalid key of type {}.", + key.type_name() + ) + }); + let value = V::take_from_reflect(value).unwrap_or_else(|value| { + panic!( + "Attempted to insert invalid value of type {}.", + value.type_name() + ) + }); + self.insert(key, value) + .map(|old_value| Box::new(old_value) as Box) + } + + fn remove(&mut self, key: &dyn Reflect) -> Option> { + let mut from_reflect = None; + key.downcast_ref::() + .or_else(|| { + from_reflect = K::from_reflect(key); + from_reflect.as_ref() + }) + .and_then(|key| self.remove(key)) + .map(|value| Box::new(value) as Box) + } } - dynamic_map - } - - fn insert_boxed( - &mut self, - key: Box, - value: Box, - ) -> Option> { - let key = K::take_from_reflect(key).unwrap_or_else(|key| { - panic!( - "Attempted to insert invalid key of type {}.", - key.type_name() - ) - }); - let value = V::take_from_reflect(value).unwrap_or_else(|value| { - panic!( - "Attempted to insert invalid value of type {}.", - value.type_name() - ) - }); - self.insert(key, value) - .map(|old_value| Box::new(old_value) as Box) - } - - fn remove(&mut self, key: &dyn Reflect) -> Option> { - let mut from_reflect = None; - key.downcast_ref::() - .or_else(|| { - from_reflect = K::from_reflect(key); - from_reflect.as_ref() - }) - .and_then(|key| self.remove(key)) - .map(|value| Box::new(value) as Box) - } -} -impl Reflect for HashMap { - fn type_name(&self) -> &str { - std::any::type_name::() - } + impl Reflect for $ty + where + K: FromReflect + Eq + Hash, + V: FromReflect, + S: BuildHasher + Send + Sync + 'static, + { + fn type_name(&self) -> &str { + std::any::type_name::() + } - fn get_type_info(&self) -> &'static TypeInfo { - ::type_info() - } + fn get_type_info(&self) -> &'static TypeInfo { + ::type_info() + } - fn into_any(self: Box) -> Box { - self - } + fn into_any(self: Box) -> Box { + self + } - fn as_any(&self) -> &dyn Any { - self - } + fn as_any(&self) -> &dyn Any { + self + } - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } - #[inline] - fn into_reflect(self: Box) -> Box { - self - } + #[inline] + fn into_reflect(self: Box) -> Box { + self + } - fn as_reflect(&self) -> &dyn Reflect { - self - } + fn as_reflect(&self) -> &dyn Reflect { + self + } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self + } - fn apply(&mut self, value: &dyn Reflect) { - map_apply(self, value); - } + fn apply(&mut self, value: &dyn Reflect) { + map_apply(self, value); + } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } + fn set(&mut self, value: Box) -> Result<(), Box> { + *self = value.take()?; + Ok(()) + } - fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Map(self) - } + fn reflect_ref(&self) -> ReflectRef { + ReflectRef::Map(self) + } - fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Map(self) - } + fn reflect_mut(&mut self) -> ReflectMut { + ReflectMut::Map(self) + } - fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Map(self) - } + fn reflect_owned(self: Box) -> ReflectOwned { + ReflectOwned::Map(self) + } - fn clone_value(&self) -> Box { - Box::new(self.clone_dynamic()) - } + fn clone_value(&self) -> Box { + Box::new(self.clone_dynamic()) + } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - map_partial_eq(self, value) - } -} + fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + map_partial_eq(self, value) + } + } -impl Typed for HashMap { - fn type_info() -> &'static TypeInfo { - static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); - CELL.get_or_insert::(|| TypeInfo::Map(MapInfo::new::())) - } -} + impl Typed for $ty + where + K: FromReflect + Eq + Hash, + V: FromReflect, + S: BuildHasher + Send + Sync + 'static, + { + fn type_info() -> &'static TypeInfo { + static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); + CELL.get_or_insert::(|| TypeInfo::Map(MapInfo::new::())) + } + } -impl GetTypeRegistration for HashMap -where - K: FromReflect + Eq + Hash, - V: FromReflect, -{ - fn get_type_registration() -> TypeRegistration { - let mut registration = TypeRegistration::of::>(); - registration.insert::(FromType::>::from_type()); - registration - } -} + impl GetTypeRegistration for $ty + where + K: FromReflect + Eq + Hash, + V: FromReflect, + S: BuildHasher + Send + Sync + 'static, + { + fn get_type_registration() -> TypeRegistration { + let mut registration = TypeRegistration::of::(); + registration.insert::(FromType::::from_type()); + registration + } + } -impl FromReflect for HashMap { - fn from_reflect(reflect: &dyn Reflect) -> Option { - if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { - let mut new_map = Self::with_capacity(ref_map.len()); - for (key, value) in ref_map.iter() { - let new_key = K::from_reflect(key)?; - let new_value = V::from_reflect(value)?; - new_map.insert(new_key, new_value); + impl FromReflect for $ty + where + K: FromReflect + Eq + Hash, + V: FromReflect, + S: BuildHasher + Default + Send + Sync + 'static, + { + fn from_reflect(reflect: &dyn Reflect) -> Option { + if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { + let mut new_map = Self::with_capacity_and_hasher(ref_map.len(), S::default()); + for (key, value) in ref_map.iter() { + let new_key = K::from_reflect(key)?; + let new_value = V::from_reflect(value)?; + new_map.insert(new_key, new_value); + } + Some(new_map) + } else { + None + } } - Some(new_map) - } else { - None } - } + }; } +impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap); +impl_reflect_for_hashmap!(std::collections::HashMap); + impl Array for [T; N] { #[inline] fn get(&self, index: usize) -> Option<&dyn Reflect> {