1use core::fmt::{Debug, Formatter};
5
6use bevy_platform::collections::HashTable;
7use bevy_reflect_derive::impl_type_path;
8
9use crate::{
10 generics::impl_generic_info_methods, type_info::impl_type_methods, ApplyError, Generics,
11 MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type,
12 TypeInfo, TypePath,
13};
14use alloc::{boxed::Box, format, vec::Vec};
15
16pub trait Map: PartialReflect {
52 fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect>;
56
57 fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect>;
61
62 fn len(&self) -> usize;
64
65 fn is_empty(&self) -> bool {
67 self.len() == 0
68 }
69
70 fn iter(&self) -> Box<dyn Iterator<Item = (&dyn PartialReflect, &dyn PartialReflect)> + '_>;
72
73 fn drain(&mut self) -> Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)>;
77
78 fn retain(&mut self, f: &mut dyn FnMut(&dyn PartialReflect, &mut dyn PartialReflect) -> bool);
82
83 fn to_dynamic_map(&self) -> DynamicMap {
85 let mut map = DynamicMap::default();
86 map.set_represented_type(self.get_represented_type_info());
87 for (key, value) in self.iter() {
88 map.insert_boxed(key.to_dynamic(), value.to_dynamic());
89 }
90 map
91 }
92
93 fn insert_boxed(
98 &mut self,
99 key: Box<dyn PartialReflect>,
100 value: Box<dyn PartialReflect>,
101 ) -> Option<Box<dyn PartialReflect>>;
102
103 fn remove(&mut self, key: &dyn PartialReflect) -> Option<Box<dyn PartialReflect>>;
108
109 fn get_represented_map_info(&self) -> Option<&'static MapInfo> {
111 self.get_represented_type_info()?.as_map().ok()
112 }
113}
114
115#[derive(#[automatically_derived]
impl ::core::clone::Clone for MapInfo {
#[inline]
fn clone(&self) -> MapInfo {
MapInfo {
ty: ::core::clone::Clone::clone(&self.ty),
generics: ::core::clone::Clone::clone(&self.generics),
key_info: ::core::clone::Clone::clone(&self.key_info),
key_ty: ::core::clone::Clone::clone(&self.key_ty),
value_info: ::core::clone::Clone::clone(&self.value_info),
value_ty: ::core::clone::Clone::clone(&self.value_ty),
docs: ::core::clone::Clone::clone(&self.docs),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for MapInfo {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["ty", "generics", "key_info", "key_ty", "value_info",
"value_ty", "docs"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.ty, &self.generics, &self.key_info, &self.key_ty,
&self.value_info, &self.value_ty, &&self.docs];
::core::fmt::Formatter::debug_struct_fields_finish(f, "MapInfo",
names, values)
}
}Debug)]
117pub struct MapInfo {
118 ty: Type,
119 generics: Generics,
120 key_info: fn() -> Option<&'static TypeInfo>,
121 key_ty: Type,
122 value_info: fn() -> Option<&'static TypeInfo>,
123 value_ty: Type,
124 #[cfg(feature = "reflect_documentation")]
125 docs: Option<&'static str>,
126}
127
128impl MapInfo {
129 pub fn new<
131 TMap: Map + TypePath,
132 TKey: Reflect + MaybeTyped + TypePath,
133 TValue: Reflect + MaybeTyped + TypePath,
134 >() -> Self {
135 Self {
136 ty: Type::of::<TMap>(),
137 generics: Generics::new(),
138 key_info: TKey::maybe_type_info,
139 key_ty: Type::of::<TKey>(),
140 value_info: TValue::maybe_type_info,
141 value_ty: Type::of::<TValue>(),
142 #[cfg(feature = "reflect_documentation")]
143 docs: None,
144 }
145 }
146
147 #[cfg(feature = "reflect_documentation")]
149 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
150 Self { docs, ..self }
151 }
152
153 pub fn ty(&self) -> &crate::type_info::Type { { &self.ty } }
pub fn type_id(&self) -> ::core::any::TypeId { self.ty().id() }
pub fn type_path(&self) -> &'static str { self.ty().path() }
pub fn type_path_table(&self) -> &crate::type_path::TypePathTable {
&self.ty().type_path_table()
}
pub fn is<T: ::core::any::Any>(&self) -> bool { self.ty().is::<T>() }impl_type_methods!(ty);
154
155 pub fn key_info(&self) -> Option<&'static TypeInfo> {
160 (self.key_info)()
161 }
162
163 pub fn key_ty(&self) -> Type {
167 self.key_ty
168 }
169
170 pub fn value_info(&self) -> Option<&'static TypeInfo> {
175 (self.value_info)()
176 }
177
178 pub fn value_ty(&self) -> Type {
182 self.value_ty
183 }
184
185 #[cfg(feature = "reflect_documentation")]
187 pub fn docs(&self) -> Option<&'static str> {
188 self.docs
189 }
190
191 pub fn generics(&self) -> &crate::generics::Generics { &self.generics }
pub fn with_generics(mut self, generics: crate::generics::Generics) -> Self {
self.generics = generics;
self
}impl_generic_info_methods!(generics);
192}
193
194#[macro_export]
197macro_rules! hash_error {
198 ( $key:expr ) => {{
199 let type_path = (*$key).reflect_type_path();
200 if !$key.is_dynamic() {
201 format!(
202 "the given key of type `{}` does not support hashing",
203 type_path
204 )
205 } else {
206 match (*$key).get_represented_type_info() {
207 None => format!("the dynamic type `{}` does not support hashing", type_path),
209 Some(s) => format!(
211 "the dynamic type `{}` (representing `{}`) does not support hashing",
212 type_path,
213 s.type_path()
214 ),
215 }
216 }
217 }}
218}
219
220#[derive(#[automatically_derived]
impl ::core::default::Default for DynamicMap {
#[inline]
fn default() -> DynamicMap {
DynamicMap {
represented_type: ::core::default::Default::default(),
hash_table: ::core::default::Default::default(),
}
}
}Default)]
222pub struct DynamicMap {
223 represented_type: Option<&'static TypeInfo>,
224 hash_table: HashTable<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
225}
226
227impl DynamicMap {
228 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
236 if let Some(represented_type) = represented_type {
237 if !#[allow(non_exhaustive_omitted_patterns)] match represented_type {
TypeInfo::Map(_) => true,
_ => false,
} {
{
::core::panicking::panic_fmt(format_args!("expected TypeInfo::Map but received: {0:?}",
represented_type));
}
};assert!(
238 matches!(represented_type, TypeInfo::Map(_)),
239 "expected TypeInfo::Map but received: {represented_type:?}"
240 );
241 }
242
243 self.represented_type = represented_type;
244 }
245
246 pub fn insert<K: PartialReflect, V: PartialReflect>(&mut self, key: K, value: V) {
248 self.insert_boxed(Box::new(key), Box::new(value));
249 }
250
251 fn internal_hash(value: &dyn PartialReflect) -> u64 {
252 value.reflect_hash().expect(&{
let type_path = (*value).reflect_type_path();
if !value.is_dynamic() {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the given key of type `{0}` does not support hashing",
type_path))
})
} else {
match (*value).get_represented_type_info() {
None =>
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the dynamic type `{0}` does not support hashing",
type_path))
}),
Some(s) =>
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the dynamic type `{0}` (representing `{1}`) does not support hashing",
type_path, s.type_path()))
}),
}
}
}hash_error!(value))
253 }
254
255 fn internal_eq(
256 key: &dyn PartialReflect,
257 ) -> impl FnMut(&(Box<dyn PartialReflect>, Box<dyn PartialReflect>)) -> bool + '_ {
258 |(other, _)| {
259 key
260 .reflect_partial_eq(&**other)
261 .expect("underlying type does not reflect `PartialEq` and hence doesn't support equality checks")
262 }
263 }
264}
265
266impl Map for DynamicMap {
267 fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> {
268 self.hash_table
269 .find(Self::internal_hash(key), Self::internal_eq(key))
270 .map(|(_, value)| &**value)
271 }
272
273 fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect> {
274 self.hash_table
275 .find_mut(Self::internal_hash(key), Self::internal_eq(key))
276 .map(|(_, value)| &mut **value)
277 }
278
279 fn len(&self) -> usize {
280 self.hash_table.len()
281 }
282
283 fn iter(&self) -> Box<dyn Iterator<Item = (&dyn PartialReflect, &dyn PartialReflect)> + '_> {
284 let iter = self.hash_table.iter().map(|(k, v)| (&**k, &**v));
285 Box::new(iter)
286 }
287
288 fn drain(&mut self) -> Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
289 self.hash_table.drain().collect()
290 }
291
292 fn retain(&mut self, f: &mut dyn FnMut(&dyn PartialReflect, &mut dyn PartialReflect) -> bool) {
293 self.hash_table
294 .retain(move |(key, value)| f(&**key, &mut **value));
295 }
296
297 fn insert_boxed(
298 &mut self,
299 key: Box<dyn PartialReflect>,
300 value: Box<dyn PartialReflect>,
301 ) -> Option<Box<dyn PartialReflect>> {
302 match (&key.reflect_partial_eq(&*key), &Some(true)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::Some(format_args!("keys inserted in `Map`-like types are expected to reflect `PartialEq`")));
}
}
};assert_eq!(
303 key.reflect_partial_eq(&*key),
304 Some(true),
305 "keys inserted in `Map`-like types are expected to reflect `PartialEq`"
306 );
307
308 let hash = Self::internal_hash(&*key);
309 let eq = Self::internal_eq(&*key);
310 match self.hash_table.find_mut(hash, eq) {
311 Some((_, old)) => Some(core::mem::replace(old, value)),
312 None => {
313 self.hash_table.insert_unique(
314 Self::internal_hash(key.as_ref()),
315 (key, value),
316 |(key, _)| Self::internal_hash(&**key),
317 );
318 None
319 }
320 }
321 }
322
323 fn remove(&mut self, key: &dyn PartialReflect) -> Option<Box<dyn PartialReflect>> {
324 let hash = Self::internal_hash(key);
325 let eq = Self::internal_eq(key);
326 match self.hash_table.find_entry(hash, eq) {
327 Ok(entry) => {
328 let ((_, old_value), _) = entry.remove();
329 Some(old_value)
330 }
331 Err(_) => None,
332 }
333 }
334}
335
336impl PartialReflect for DynamicMap {
337 #[inline]
338 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
339 self.represented_type
340 }
341
342 #[inline]
343 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
344 self
345 }
346
347 #[inline]
348 fn as_partial_reflect(&self) -> &dyn PartialReflect {
349 self
350 }
351
352 #[inline]
353 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
354 self
355 }
356
357 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
358 Err(self)
359 }
360
361 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
362 None
363 }
364
365 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
366 None
367 }
368
369 fn apply(&mut self, value: &dyn PartialReflect) {
370 map_apply(self, value);
371 }
372
373 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
374 map_try_apply(self, value)
375 }
376
377 fn reflect_kind(&self) -> ReflectKind {
378 ReflectKind::Map
379 }
380
381 fn reflect_ref(&self) -> ReflectRef<'_> {
382 ReflectRef::Map(self)
383 }
384
385 fn reflect_mut(&mut self) -> ReflectMut<'_> {
386 ReflectMut::Map(self)
387 }
388
389 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
390 ReflectOwned::Map(self)
391 }
392
393 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
394 map_partial_eq(self, value)
395 }
396
397 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
398 f.write_fmt(format_args!("DynamicMap("))write!(f, "DynamicMap(")?;
399 map_debug(self, f)?;
400 f.write_fmt(format_args!(")"))write!(f, ")")
401 }
402
403 #[inline]
404 fn is_dynamic(&self) -> bool {
405 true
406 }
407}
408
409const _: () =
{
#[allow(deprecated, reason =
"derives on a deprecated type shouldn't be considered a usage")]
impl bevy_reflect::TypePath for DynamicMap where {
fn type_path() -> &'static str { "bevy_reflect::DynamicMap" }
fn short_type_path() -> &'static str { "DynamicMap" }
fn type_ident() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("DynamicMap")
}
fn crate_name() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_reflect")
}
fn module_path() -> ::core::option::Option<&'static str> {
::core::option::Option::Some("bevy_reflect")
}
}
};impl_type_path!((in bevy_reflect) DynamicMap);
410
411impl Debug for DynamicMap {
412 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
413 self.debug(f)
414 }
415}
416
417impl FromIterator<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)> for DynamicMap {
418 fn from_iter<I: IntoIterator<Item = (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>>(
419 items: I,
420 ) -> Self {
421 let mut map = Self::default();
422 for (key, value) in items.into_iter() {
423 map.insert_boxed(key, value);
424 }
425 map
426 }
427}
428
429impl<K: Reflect, V: Reflect> FromIterator<(K, V)> for DynamicMap {
430 fn from_iter<I: IntoIterator<Item = (K, V)>>(items: I) -> Self {
431 let mut map = Self::default();
432 for (key, value) in items.into_iter() {
433 map.insert(key, value);
434 }
435 map
436 }
437}
438
439impl IntoIterator for DynamicMap {
440 type Item = (Box<dyn PartialReflect>, Box<dyn PartialReflect>);
441 type IntoIter = bevy_platform::collections::hash_table::IntoIter<Self::Item>;
442
443 fn into_iter(self) -> Self::IntoIter {
444 self.hash_table.into_iter()
445 }
446}
447
448impl<'a> IntoIterator for &'a DynamicMap {
449 type Item = (&'a dyn PartialReflect, &'a dyn PartialReflect);
450 type IntoIter = core::iter::Map<
451 bevy_platform::collections::hash_table::Iter<
452 'a,
453 (Box<dyn PartialReflect>, Box<dyn PartialReflect>),
454 >,
455 fn(&'a (Box<dyn PartialReflect>, Box<dyn PartialReflect>)) -> Self::Item,
456 >;
457
458 fn into_iter(self) -> Self::IntoIter {
459 self.hash_table
460 .iter()
461 .map(|(k, v)| (k.as_ref(), v.as_ref()))
462 }
463}
464
465#[inline]
475pub fn map_partial_eq<M: Map + ?Sized>(a: &M, b: &dyn PartialReflect) -> Option<bool> {
476 let ReflectRef::Map(map) = b.reflect_ref() else {
477 return Some(false);
478 };
479
480 if a.len() != map.len() {
481 return Some(false);
482 }
483
484 for (key, value) in a.iter() {
485 if let Some(map_value) = map.get(key) {
486 let eq_result = value.reflect_partial_eq(map_value);
487 if let failed @ (Some(false) | None) = eq_result {
488 return failed;
489 }
490 } else {
491 return Some(false);
492 }
493 }
494
495 Some(true)
496}
497
498#[inline]
509pub fn map_partial_cmp<M: Map + ?Sized>(
510 a: &M,
511 b: &dyn PartialReflect,
512) -> Option<::core::cmp::Ordering> {
513 let ReflectRef::Map(map) = b.reflect_ref() else {
514 return None;
515 };
516
517 let mut a_iter = a.iter();
518 let mut b_iter = map.iter();
519
520 loop {
521 match (a_iter.next(), b_iter.next()) {
522 (Some((a_k, a_v)), Some((b_k, b_v))) => {
523 match a_k.reflect_partial_cmp(b_k) {
524 None => return None,
525 Some(core::cmp::Ordering::Equal) => {}
526 Some(ord) => return Some(ord),
527 }
528
529 match a_v.reflect_partial_cmp(b_v) {
530 None => return None,
531 Some(core::cmp::Ordering::Equal) => {}
532 Some(ord) => return Some(ord),
533 }
534 }
535 (None, None) => return Some(::core::cmp::Ordering::Equal),
536 (None, Some(_)) => return Some(::core::cmp::Ordering::Less),
537 (Some(_), None) => return Some(::core::cmp::Ordering::Greater),
538 }
539 }
540}
541
542#[inline]
560pub fn map_debug(dyn_map: &dyn Map, f: &mut Formatter<'_>) -> core::fmt::Result {
561 let mut debug = f.debug_map();
562 for (key, value) in dyn_map.iter() {
563 debug.entry(&key as &dyn Debug, &value as &dyn Debug);
564 }
565 debug.finish()
566}
567
568#[inline]
577pub fn map_apply<M: Map>(a: &mut M, b: &dyn PartialReflect) {
578 if let Err(err) = map_try_apply(a, b) {
579 { ::core::panicking::panic_fmt(format_args!("{0}", err)); };panic!("{err}");
580 }
581}
582
583#[inline]
594pub fn map_try_apply<M: Map>(a: &mut M, b: &dyn PartialReflect) -> Result<(), ApplyError> {
595 let map_value = b.reflect_ref().as_map()?;
596
597 for (key, b_value) in map_value.iter() {
598 if let Some(a_value) = a.get_mut(key) {
599 a_value.try_apply(b_value)?;
600 } else {
601 a.insert_boxed(key.to_dynamic(), b_value.to_dynamic());
602 }
603 }
604 a.retain(&mut |key, _| map_value.get(key).is_some());
605
606 Ok(())
607}
608
609#[cfg(test)]
610mod tests {
611
612 use crate::PartialReflect;
613
614 use super::{DynamicMap, Map};
615
616 #[test]
617 fn remove() {
618 let mut map = DynamicMap::default();
619 map.insert(0, 0);
620 map.insert(1, 1);
621
622 assert_eq!(map.remove(&0).unwrap().try_downcast_ref(), Some(&0));
623 assert!(map.get(&0).is_none());
624 assert_eq!(map.get(&1).unwrap().try_downcast_ref(), Some(&1));
625
626 assert_eq!(map.remove(&1).unwrap().try_downcast_ref(), Some(&1));
627 assert!(map.get(&1).is_none());
628
629 assert!(map.remove(&1).is_none());
630 assert!(map.get(&1).is_none());
631 }
632
633 #[test]
634 fn apply() {
635 let mut map_a = DynamicMap::default();
636 map_a.insert(0, 0);
637 map_a.insert(1, 1);
638
639 let mut map_b = DynamicMap::default();
640 map_b.insert(10, 10);
641 map_b.insert(1, 5);
642
643 map_a.apply(&map_b);
644
645 assert!(map_a.get(&0).is_none());
646 assert_eq!(map_a.get(&1).unwrap().try_downcast_ref(), Some(&5));
647 assert_eq!(map_a.get(&10).unwrap().try_downcast_ref(), Some(&10));
648 }
649}