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, ty::impl_type_methods, ApplyError, Generics, MaybeTyped,
11 PartialReflect, Reflect, ReflectCloneError, ReflectKind, ReflectMut, ReflectOwned, ReflectRef,
12 Type, TypeInfo, TypePath,
13};
14use alloc::{boxed::Box, vec::Vec};
15
16#[rust_analyzer::completions(ignore_flyimport_methods)]
53pub trait Map: PartialReflect {
54 fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect>;
58
59 fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect>;
63
64 fn len(&self) -> usize;
66
67 fn is_empty(&self) -> bool {
69 self.len() == 0
70 }
71
72 fn iter(&self) -> Box<dyn Iterator<Item = (&dyn PartialReflect, &dyn PartialReflect)> + '_>;
74
75 fn drain(&mut self) -> Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)>;
79
80 fn retain(&mut self, f: &mut dyn FnMut(&dyn PartialReflect, &mut dyn PartialReflect) -> bool);
84
85 fn to_dynamic_map(&self) -> Result<DynamicMap, ReflectCloneError> {
89 let mut map = DynamicMap::default();
90 map.set_represented_type(self.get_represented_type_info());
91 for (key, value) in self.iter() {
92 map.insert_boxed(key.to_dynamic()?, value.to_dynamic()?);
93 }
94 Ok(map)
95 }
96
97 fn insert_boxed(
102 &mut self,
103 key: Box<dyn PartialReflect>,
104 value: Box<dyn PartialReflect>,
105 ) -> Option<Box<dyn PartialReflect>>;
106
107 fn remove(&mut self, key: &dyn PartialReflect) -> Option<Box<dyn PartialReflect>>;
112
113 fn get_represented_map_info(&self) -> Option<&'static MapInfo> {
115 self.get_represented_type_info()?.as_map().ok()
116 }
117}
118
119#[derive(Clone, Debug)]
121pub struct MapInfo {
122 ty: Type,
123 generics: Generics,
124 key_info: fn() -> Option<&'static TypeInfo>,
125 key_ty: Type,
126 value_info: fn() -> Option<&'static TypeInfo>,
127 value_ty: Type,
128 #[cfg(feature = "reflect_documentation")]
129 docs: Option<&'static str>,
130}
131
132impl MapInfo {
133 pub fn new<
135 TMap: Map + TypePath,
136 TKey: Reflect + MaybeTyped + TypePath,
137 TValue: Reflect + MaybeTyped + TypePath,
138 >() -> Self {
139 Self {
140 ty: Type::of::<TMap>(),
141 generics: Generics::new(),
142 key_info: TKey::maybe_type_info,
143 key_ty: Type::of::<TKey>(),
144 value_info: TValue::maybe_type_info,
145 value_ty: Type::of::<TValue>(),
146 #[cfg(feature = "reflect_documentation")]
147 docs: None,
148 }
149 }
150
151 #[cfg(feature = "reflect_documentation")]
153 pub fn with_docs(self, docs: Option<&'static str>) -> Self {
154 Self { docs, ..self }
155 }
156
157 impl_type_methods!(ty);
158
159 pub fn key_info(&self) -> Option<&'static TypeInfo> {
164 (self.key_info)()
165 }
166
167 pub fn key_ty(&self) -> Type {
171 self.key_ty
172 }
173
174 pub fn value_info(&self) -> Option<&'static TypeInfo> {
179 (self.value_info)()
180 }
181
182 pub fn value_ty(&self) -> Type {
186 self.value_ty
187 }
188
189 #[cfg(feature = "reflect_documentation")]
191 pub fn docs(&self) -> Option<&'static str> {
192 self.docs
193 }
194
195 impl_generic_info_methods!(generics);
196}
197
198#[macro_export]
201macro_rules! hash_error {
202 ( $key:expr ) => {{
203 let type_path = (*$key).reflect_type_path();
204 if !$key.is_dynamic() {
205 $crate::__macro_exports::alloc_utils::format!(
206 "the given key of type `{}` does not support hashing",
207 type_path
208 )
209 } else {
210 match (*$key).get_represented_type_info() {
211 ::core::option::Option::None => $crate::__macro_exports::alloc_utils::format!("the dynamic type `{}` does not support hashing", type_path),
213 ::core::option::Option::Some(s) => $crate::__macro_exports::alloc_utils::format!(
215 "the dynamic type `{}` (representing `{}`) does not support hashing",
216 type_path,
217 s.type_path()
218 ),
219 }
220 }
221 }}
222}
223
224#[derive(Default)]
226pub struct DynamicMap {
227 represented_type: Option<&'static TypeInfo>,
228 hash_table: HashTable<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
229}
230
231impl DynamicMap {
232 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
240 if let Some(represented_type) = represented_type {
241 assert!(
242 matches!(represented_type, TypeInfo::Map(_)),
243 "expected TypeInfo::Map but received: {represented_type:?}"
244 );
245 }
246
247 self.represented_type = represented_type;
248 }
249
250 pub fn insert<K: PartialReflect, V: PartialReflect>(&mut self, key: K, value: V) {
252 self.insert_boxed(Box::new(key), Box::new(value));
253 }
254
255 fn internal_hash(value: &dyn PartialReflect) -> u64 {
256 value.reflect_hash().expect(&hash_error!(value))
257 }
258
259 fn internal_eq(
260 key: &dyn PartialReflect,
261 ) -> impl FnMut(&(Box<dyn PartialReflect>, Box<dyn PartialReflect>)) -> bool + '_ {
262 |(other, _)| {
263 key
264 .reflect_partial_eq(&**other)
265 .expect("underlying type does not reflect `PartialEq` and hence doesn't support equality checks")
266 }
267 }
268}
269
270impl Map for DynamicMap {
271 fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> {
272 self.hash_table
273 .find(Self::internal_hash(key), Self::internal_eq(key))
274 .map(|(_, value)| &**value)
275 }
276
277 fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect> {
278 self.hash_table
279 .find_mut(Self::internal_hash(key), Self::internal_eq(key))
280 .map(|(_, value)| &mut **value)
281 }
282
283 fn len(&self) -> usize {
284 self.hash_table.len()
285 }
286
287 fn iter(&self) -> Box<dyn Iterator<Item = (&dyn PartialReflect, &dyn PartialReflect)> + '_> {
288 let iter = self.hash_table.iter().map(|(k, v)| (&**k, &**v));
289 Box::new(iter)
290 }
291
292 fn drain(&mut self) -> Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
293 self.hash_table.drain().collect()
294 }
295
296 fn retain(&mut self, f: &mut dyn FnMut(&dyn PartialReflect, &mut dyn PartialReflect) -> bool) {
297 self.hash_table
298 .retain(move |(key, value)| f(&**key, &mut **value));
299 }
300
301 fn insert_boxed(
302 &mut self,
303 key: Box<dyn PartialReflect>,
304 value: Box<dyn PartialReflect>,
305 ) -> Option<Box<dyn PartialReflect>> {
306 assert_eq!(
307 key.reflect_partial_eq(&*key),
308 Some(true),
309 "keys inserted in `Map`-like types are expected to reflect `PartialEq`"
310 );
311
312 let hash = Self::internal_hash(&*key);
313 let eq = Self::internal_eq(&*key);
314 match self.hash_table.find_mut(hash, eq) {
315 Some((_, old)) => Some(core::mem::replace(old, value)),
316 None => {
317 self.hash_table.insert_unique(
318 Self::internal_hash(key.as_ref()),
319 (key, value),
320 |(key, _)| Self::internal_hash(&**key),
321 );
322 None
323 }
324 }
325 }
326
327 fn remove(&mut self, key: &dyn PartialReflect) -> Option<Box<dyn PartialReflect>> {
328 let hash = Self::internal_hash(key);
329 let eq = Self::internal_eq(key);
330 match self.hash_table.find_entry(hash, eq) {
331 Ok(entry) => {
332 let ((_, old_value), _) = entry.remove();
333 Some(old_value)
334 }
335 Err(_) => None,
336 }
337 }
338}
339
340impl PartialReflect for DynamicMap {
341 #[inline]
342 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
343 self.represented_type
344 }
345
346 #[inline]
347 fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
348 self
349 }
350
351 #[inline]
352 fn as_partial_reflect(&self) -> &dyn PartialReflect {
353 self
354 }
355
356 #[inline]
357 fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
358 self
359 }
360
361 fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
362 Err(self)
363 }
364
365 fn try_as_reflect(&self) -> Option<&dyn Reflect> {
366 None
367 }
368
369 fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
370 None
371 }
372
373 fn apply(&mut self, value: &dyn PartialReflect) {
374 map_apply(self, value);
375 }
376
377 fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
378 map_try_apply(self, value)
379 }
380
381 fn reflect_kind(&self) -> ReflectKind {
382 ReflectKind::Map
383 }
384
385 fn reflect_ref(&self) -> ReflectRef<'_> {
386 ReflectRef::Map(self)
387 }
388
389 fn reflect_mut(&mut self) -> ReflectMut<'_> {
390 ReflectMut::Map(self)
391 }
392
393 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
394 ReflectOwned::Map(self)
395 }
396
397 fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
398 map_partial_eq(self, value)
399 }
400
401 fn debug(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
402 write!(f, "DynamicMap(")?;
403 map_debug(self, f)?;
404 write!(f, ")")
405 }
406
407 #[inline]
408 fn is_dynamic(&self) -> bool {
409 true
410 }
411}
412
413impl_type_path!((in bevy_reflect) DynamicMap);
414
415impl Debug for DynamicMap {
416 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
417 self.debug(f)
418 }
419}
420
421impl FromIterator<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)> for DynamicMap {
422 fn from_iter<I: IntoIterator<Item = (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>>(
423 items: I,
424 ) -> Self {
425 let mut map = Self::default();
426 for (key, value) in items.into_iter() {
427 map.insert_boxed(key, value);
428 }
429 map
430 }
431}
432
433impl<K: Reflect, V: Reflect> FromIterator<(K, V)> for DynamicMap {
434 fn from_iter<I: IntoIterator<Item = (K, V)>>(items: I) -> Self {
435 let mut map = Self::default();
436 for (key, value) in items.into_iter() {
437 map.insert(key, value);
438 }
439 map
440 }
441}
442
443impl IntoIterator for DynamicMap {
444 type Item = (Box<dyn PartialReflect>, Box<dyn PartialReflect>);
445 type IntoIter = bevy_platform::collections::hash_table::IntoIter<Self::Item>;
446
447 fn into_iter(self) -> Self::IntoIter {
448 self.hash_table.into_iter()
449 }
450}
451
452impl<'a> IntoIterator for &'a DynamicMap {
453 type Item = (&'a dyn PartialReflect, &'a dyn PartialReflect);
454 type IntoIter = core::iter::Map<
455 bevy_platform::collections::hash_table::Iter<
456 'a,
457 (Box<dyn PartialReflect>, Box<dyn PartialReflect>),
458 >,
459 fn(&'a (Box<dyn PartialReflect>, Box<dyn PartialReflect>)) -> Self::Item,
460 >;
461
462 fn into_iter(self) -> Self::IntoIter {
463 self.hash_table
464 .iter()
465 .map(|(k, v)| (k.as_ref(), v.as_ref()))
466 }
467}
468
469#[inline]
479pub fn map_partial_eq<M: Map + ?Sized>(a: &M, b: &dyn PartialReflect) -> Option<bool> {
480 let ReflectRef::Map(map) = b.reflect_ref() else {
481 return Some(false);
482 };
483
484 if a.len() != map.len() {
485 return Some(false);
486 }
487
488 for (key, value) in a.iter() {
489 if let Some(map_value) = map.get(key) {
490 let eq_result = value.reflect_partial_eq(map_value);
491 if let failed @ (Some(false) | None) = eq_result {
492 return failed;
493 }
494 } else {
495 return Some(false);
496 }
497 }
498
499 Some(true)
500}
501
502#[inline]
513pub fn map_partial_cmp<M: Map + ?Sized>(
514 a: &M,
515 b: &dyn PartialReflect,
516) -> Option<::core::cmp::Ordering> {
517 let ReflectRef::Map(map) = b.reflect_ref() else {
518 return None;
519 };
520
521 let mut a_iter = a.iter();
522 let mut b_iter = map.iter();
523
524 loop {
525 match (a_iter.next(), b_iter.next()) {
526 (Some((a_k, a_v)), Some((b_k, b_v))) => {
527 match a_k.reflect_partial_cmp(b_k) {
528 None => return None,
529 Some(core::cmp::Ordering::Equal) => {}
530 Some(ord) => return Some(ord),
531 }
532
533 match a_v.reflect_partial_cmp(b_v) {
534 None => return None,
535 Some(core::cmp::Ordering::Equal) => {}
536 Some(ord) => return Some(ord),
537 }
538 }
539 (None, None) => return Some(::core::cmp::Ordering::Equal),
540 (None, Some(_)) => return Some(::core::cmp::Ordering::Less),
541 (Some(_), None) => return Some(::core::cmp::Ordering::Greater),
542 }
543 }
544}
545
546#[inline]
564pub fn map_debug(dyn_map: &dyn Map, f: &mut Formatter<'_>) -> core::fmt::Result {
565 let mut debug = f.debug_map();
566 for (key, value) in dyn_map.iter() {
567 debug.entry(&key as &dyn Debug, &value as &dyn Debug);
568 }
569 debug.finish()
570}
571
572#[inline]
581pub fn map_apply<M: Map>(a: &mut M, b: &dyn PartialReflect) {
582 if let Err(err) = map_try_apply(a, b) {
583 panic!("{err}");
584 }
585}
586
587#[inline]
598pub fn map_try_apply<M: Map>(a: &mut M, b: &dyn PartialReflect) -> Result<(), ApplyError> {
599 let map_value = b.reflect_ref().as_map()?;
600
601 for (key, b_value) in map_value.iter() {
602 if let Some(a_value) = a.get_mut(key) {
603 a_value.try_apply(b_value)?;
604 } else {
605 a.insert_boxed(key.to_dynamic()?, b_value.to_dynamic()?);
606 }
607 }
608 a.retain(&mut |key, _| map_value.get(key).is_some());
609
610 Ok(())
611}
612
613#[cfg(test)]
614mod tests {
615
616 use crate::PartialReflect;
617
618 use super::{DynamicMap, Map};
619
620 #[test]
621 fn remove() {
622 let mut map = DynamicMap::default();
623 map.insert(0, 0);
624 map.insert(1, 1);
625
626 assert_eq!(map.remove(&0).unwrap().try_downcast_ref(), Some(&0));
627 assert!(map.get(&0).is_none());
628 assert_eq!(map.get(&1).unwrap().try_downcast_ref(), Some(&1));
629
630 assert_eq!(map.remove(&1).unwrap().try_downcast_ref(), Some(&1));
631 assert!(map.get(&1).is_none());
632
633 assert!(map.remove(&1).is_none());
634 assert!(map.get(&1).is_none());
635 }
636
637 #[test]
638 fn apply() {
639 let mut map_a = DynamicMap::default();
640 map_a.insert(0, 0);
641 map_a.insert(1, 1);
642
643 let mut map_b = DynamicMap::default();
644 map_b.insert(10, 10);
645 map_b.insert(1, 5);
646
647 map_a.apply(&map_b);
648
649 assert!(map_a.get(&0).is_none());
650 assert_eq!(map_a.get(&1).unwrap().try_downcast_ref(), Some(&5));
651 assert_eq!(map_a.get(&10).unwrap().try_downcast_ref(), Some(&10));
652 }
653}