1use crate::{
2 AccessKind, AnyRef, EnumAccess, EnumAccessMut, MapAccess, MapAccessMut, MapEntryVisitor, Meta,
3 MetaMut, Object, ObjectOps, ObjectRef, ObjectRefMut, OptionAccessMut, Reflect, ReflectMut,
4 SequenceAccess, SequenceAccessMut, TupleAccess, TupleAccessMut, TypedMapAccess,
5 TypedMapAccessMut, VariantFields, VariantFieldsMut, as_map_key, btree_map_get, btree_map_get_mut,
6};
7#[cfg(feature = "std")]
8use crate::{hash_map_get, hash_map_get_mut};
9use alloc::borrow::ToOwned;
10use alloc::boxed::Box;
11use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
12use alloc::rc::Rc;
13use alloc::string::String;
14use alloc::sync::Arc;
15use alloc::vec::Vec;
16use core::any::{Any, TypeId};
17#[cfg(feature = "std")]
18use core::hash::Hash;
19#[cfg(feature = "std")]
20use std::collections::HashMap;
21
22macro_rules! impl_meta {
23 ($($ty:ty),* $(,)?) => {
24 $(
25 impl Meta for $ty {
26 fn reflect(&self) -> Reflect<'_> {
27 Reflect::Scalar
28 }
29
30 fn eq_dyn(&self, other: &dyn Meta) -> bool {
31 other.as_any().downcast_ref::<$ty>().is_some_and(|other| self == other)
32 }
33
34 fn into_any(self: Box<Self>) -> Box<dyn Any> {
35 self
36 }
37
38 fn as_any(&self) -> &dyn Any {
39 self
40 }
41 }
42
43 impl MetaMut for $ty {
44 set_body!();
45
46 fn reflect_mut(&mut self) -> ReflectMut<'_> {
47 ReflectMut::Opaque
48 }
49
50 fn as_any_mut(&mut self) -> &mut dyn Any {
51 self
52 }
53 }
54 )*
55 };
56}
57
58impl_meta!(
59 bool,
60 char,
61 i8,
62 i16,
63 i32,
64 i64,
65 i128,
66 isize,
67 u8,
68 u16,
69 u32,
70 u64,
71 u128,
72 usize,
73 f32,
74 f64,
75 &'static str,
76 String,
77);
78
79fn into_typed<T: 'static>(value: Object) -> Result<T, Object> {
81 if !value.is::<T>() {
82 return Err(value);
83 }
84
85 Ok(*value.into_inner().into_any().downcast::<T>().unwrap())
86}
87
88macro_rules! impl_meta_forward {
89 ($wrapper:ident) => {
90 impl<T> Meta for $wrapper<T>
91 where
92 T: Meta + 'static,
93 {
94 fn reflect(&self) -> Reflect<'_> {
95 (**self).reflect()
96 }
97
98 fn eq_dyn(&self, other: &dyn Meta) -> bool {
99 other
100 .as_any()
101 .downcast_ref::<Self>()
102 .is_some_and(|other| (**self).eq_dyn(&**other))
103 }
104
105 fn into_any(self: Box<Self>) -> Box<dyn Any> {
106 self
107 }
108
109 fn as_any(&self) -> &dyn Any {
110 self
111 }
112 }
113 };
114}
115
116macro_rules! impl_meta_mut_forward {
117 (wrapper = $wrapper:ident, mode = direct $(,)?) => {
118 impl<T> MetaMut for $wrapper<T>
119 where
120 T: MetaMut + 'static,
121 {
122 set_body!();
123
124 fn reflect_mut(&mut self) -> ReflectMut<'_> {
125 (**self).reflect_mut()
126 }
127
128 fn as_any_mut(&mut self) -> &mut dyn Any {
129 self
130 }
131 }
132 };
133 (wrapper = $wrapper:ident, mode = unique $(,)?) => {
134 impl<T> MetaMut for $wrapper<T>
135 where
136 T: MetaMut + 'static,
137 {
138 set_body!();
139
140 fn reflect_mut(&mut self) -> ReflectMut<'_> {
142 match $wrapper::get_mut(self) {
143 Some(inner) => inner.reflect_mut(),
144 None => ReflectMut::Opaque,
145 }
146 }
147
148 fn as_any_mut(&mut self) -> &mut dyn Any {
149 self
150 }
151 }
152 };
153}
154
155impl_meta_forward!(Box);
156impl_meta_forward!(Rc);
157impl_meta_forward!(Arc);
158impl_meta_mut_forward!(wrapper = Box, mode = direct);
159impl_meta_mut_forward!(wrapper = Rc, mode = unique);
160impl_meta_mut_forward!(wrapper = Arc, mode = unique);
161
162fn move_vec_item<T>(value: &mut [T], from: usize, to: usize) -> Result<(), crate::MoveItemError> {
163 let len = value.len();
164 if from >= len || to > len {
165 return Err(crate::MoveItemError::IndexOutOfBounds);
166 }
167 if from == to {
168 return Ok(());
169 }
170
171 if from < to {
172 value[from..to].rotate_left(1);
173 } else {
174 value[to..=from].rotate_right(1);
175 }
176 Ok(())
177}
178
179fn move_vec_deque_item<T>(
180 value: &mut VecDeque<T>,
181 from: usize,
182 to: usize,
183) -> Result<(), crate::MoveItemError> {
184 let len = value.len();
185 if from >= len || to > len {
186 return Err(crate::MoveItemError::IndexOutOfBounds);
187 }
188 if from == to {
189 return Ok(());
190 }
191
192 let value = value.make_contiguous();
193 if from < to {
194 value[from..to].rotate_left(1);
195 } else {
196 value[to..=from].rotate_right(1);
197 }
198 Ok(())
199}
200
201fn move_linked_list_item<T>(
202 value: &mut LinkedList<T>,
203 from: usize,
204 to: usize,
205) -> Result<(), crate::MoveItemError> {
206 let len = value.len();
207 if from >= len || to > len {
208 return Err(crate::MoveItemError::IndexOutOfBounds);
209 }
210 if from == to {
211 return Ok(());
212 }
213
214 let mut tail = value.split_off(from);
215 let item = tail.pop_front().expect("validated source index");
216 value.append(&mut tail);
217 let insert_at = if from < to { to - 1 } else { to };
218 let mut suffix = value.split_off(insert_at);
219 value.push_back(item);
220 value.append(&mut suffix);
221 Ok(())
222}
223
224fn ordered_eq<'a, T, I>(a: I, b: I) -> bool
227where
228 T: Meta + 'a,
229 I: IntoIterator<Item = &'a T>,
230{
231 a.into_iter().zip(b).all(|(a, b)| a.eq_dyn(b))
232}
233
234fn sorted_eq<'a, T, I>(a: I, b: I) -> bool
237where
238 T: Meta + Ord + 'a,
239 I: IntoIterator<Item = &'a T>,
240{
241 let mut a = a.into_iter().collect::<Vec<_>>();
242 let mut b = b.into_iter().collect::<Vec<_>>();
243 a.sort_unstable();
244 b.sort_unstable();
245 ordered_eq(a, b)
246}
247
248macro_rules! impl_seq_meta {
249 (
250 type = $ty:ty,
251 generics = [$($generics:tt)*],
252 bounds = [$($bounds:tt)*],
253 item = get,
254 len = method $(,)?
255 ) => {
256 impl_seq_meta!(@meta $ty, [$($generics)*], [$($bounds)*]);
257
258 impl<$($generics)*> SequenceAccess for $ty
259 where
260 $($bounds)*
261 {
262 fn len(&self) -> usize {
263 self.len()
264 }
265
266 fn item(&self, index: usize) -> Option<ObjectRef<'_>> {
267 self.get(index).map(|value| ObjectRef::new(value))
268 }
269 }
270 };
271 (
272 type = $ty:ty,
273 generics = [$($generics:tt)*],
274 bounds = [$($bounds:tt)*],
275 item = get,
276 len = const $len:ident $(,)?
277 ) => {
278 impl_seq_meta!(@meta $ty, [$($generics)*], [$($bounds)*]);
279
280 impl<$($generics)*> SequenceAccess for $ty
281 where
282 $($bounds)*
283 {
284 fn len(&self) -> usize {
285 $len
286 }
287
288 fn item(&self, index: usize) -> Option<ObjectRef<'_>> {
289 self.get(index).map(|value| ObjectRef::new(value))
290 }
291 }
292 };
293 (
294 type = $ty:ty,
295 generics = [$($generics:tt)*],
296 bounds = [$($bounds:tt)*],
297 item = iter,
298 len = method,
299 eq = $eq:ident $(,)?
300 ) => {
301 impl<$($generics)*> Meta for $ty
302 where
303 $($bounds)*
304 {
305 fn reflect(&self) -> Reflect<'_> {
306 Reflect::Sequence(self)
307 }
308
309 fn eq_dyn(&self, other: &dyn Meta) -> bool {
310 other
311 .as_any()
312 .downcast_ref::<Self>()
313 .is_some_and(|other| self.len() == other.len() && $eq(self, other))
314 }
315
316 fn into_any(self: Box<Self>) -> Box<dyn Any> {
317 self
318 }
319
320 fn as_any(&self) -> &dyn Any {
321 self
322 }
323 }
324
325 impl<$($generics)*> SequenceAccess for $ty
326 where
327 $($bounds)*
328 {
329 fn len(&self) -> usize {
330 self.len()
331 }
332
333 fn item(&self, index: usize) -> Option<ObjectRef<'_>> {
334 self.iter().nth(index).map(|value| ObjectRef::new(value))
335 }
336 }
337 };
338 (@meta $ty:ty, [$($generics:tt)*], [$($bounds:tt)*]) => {
339 impl<$($generics)*> Meta for $ty
340 where
341 $($bounds)*
342 {
343 fn reflect(&self) -> Reflect<'_> {
344 Reflect::Sequence(self)
345 }
346
347 fn into_any(self: Box<Self>) -> Box<dyn Any> {
348 self
349 }
350
351 fn as_any(&self) -> &dyn Any {
352 self
353 }
354 }
355 };
356}
357
358macro_rules! impl_seq_meta_mut {
360 (type = $ty:ty, generics = [$($generics:tt)*], bounds = [$($bounds:tt)*] $(,)?) => {
361 impl<$($generics)*> MetaMut for $ty
362 where
363 $($bounds)*
364 {
365 set_body!();
366
367 fn reflect_mut(&mut self) -> ReflectMut<'_> {
368 ReflectMut::Sequence(self)
369 }
370
371 fn as_any_mut(&mut self) -> &mut dyn Any {
372 self
373 }
374 }
375 };
376}
377
378macro_rules! impl_indexed_meta_mut {
379 (
380 type = $ty:ty,
381 generics = [$($generics:tt)*],
382 bounds = [$($bounds:tt)*],
383 access_mut = $access_mut:ident,
384 push = $push:ident,
385 last = $last:ident,
386 insert = $insert:ident,
387 move_item = $move_item:path,
388 $($extra:item)*
389 ) => {
390 impl_seq_meta_mut!(type = $ty, generics = [$($generics)*], bounds = [$($bounds)*]);
391
392 impl<$($generics)*> SequenceAccessMut for $ty
393 where
394 $($bounds)*
395 {
396 fn item_mut(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
397 self
398 .$access_mut(index)
399 .map(|value| ObjectRefMut::new(value))
400 }
401
402 fn push_item(&mut self, value: Object) -> Result<ObjectRefMut<'_>, Object> {
403 let value = into_typed(value)?;
404 self.$push(value);
405
406 Ok(ObjectRefMut::new(
407 self.$last().expect("just pushed")
408 ))
409 }
410
411 fn insert_item(&mut self, index: usize, value: Object) -> Result<ObjectRefMut<'_>, Object> {
412 if index > self.len() {
413 return Err(value);
414 }
415
416 let value = into_typed(value)?;
417 self.$insert(index, value);
418
419 Ok(ObjectRefMut::new(
420 self.$access_mut(index).expect("just inserted"),
421 ))
422 }
423
424 $($extra)*
425
426 fn move_item(&mut self, from: usize, to: usize) -> Result<(), crate::MoveItemError> {
427 $move_item(self, from, to)
428 }
429 }
430 };
431}
432
433impl_seq_meta!(
434 type = Vec<T>,
435 generics = [T],
436 bounds = [T: Meta + 'static],
437 item = get,
438 len = method,
439);
440
441impl_indexed_meta_mut!(
442 type = Vec<T>,
443 generics = [T],
444 bounds = [T: MetaMut + 'static],
445 access_mut = get_mut,
446 push = push,
447 last = last_mut,
448 insert = insert,
449 move_item = move_vec_item,
450 fn remove_item(&mut self, index: usize) -> Option<Object> {
451 (index < self.len()).then(|| Object::new(self.remove(index)))
452 }
453);
454
455impl_seq_meta!(
456 type = [T; N],
457 generics = [T, const N: usize],
458 bounds = [T: Meta + 'static],
459 item = get,
460 len = const N,
461);
462impl_seq_meta_mut!(
463 type = [T; N],
464 generics = [T, const N: usize],
465 bounds = [T: MetaMut + 'static],
466);
467
468impl<T, const N: usize> SequenceAccessMut for [T; N]
469where
470 T: MetaMut + 'static,
471{
472 fn item_mut(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
473 self.get_mut(index).map(|value| ObjectRefMut::new(value))
474 }
475}
476
477impl_seq_meta!(
478 type = VecDeque<T>,
479 generics = [T],
480 bounds = [T: Meta + 'static],
481 item = get,
482 len = method,
483);
484impl_indexed_meta_mut!(
485 type = VecDeque<T>,
486 generics = [T],
487 bounds = [T: MetaMut + 'static],
488 access_mut = get_mut,
489 push = push_back,
490 last = back_mut,
491 insert = insert,
492 move_item = move_vec_deque_item,
493 fn remove_item(&mut self, index: usize) -> Option<Object> {
494 self.remove(index).map(Object::new)
495 }
496);
497
498impl_seq_meta!(
499 type = LinkedList<T>,
500 generics = [T],
501 bounds = [T: Meta + 'static],
502 item = iter,
503 len = method,
504 eq = ordered_eq,
505);
506impl_seq_meta_mut!(
507 type = LinkedList<T>,
508 generics = [T],
509 bounds = [T: MetaMut + 'static],
510);
511
512impl<T> SequenceAccessMut for LinkedList<T>
513where
514 T: MetaMut + 'static,
515{
516 fn item_mut(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
517 self
518 .iter_mut()
519 .nth(index)
520 .map(|value| ObjectRefMut::new(value))
521 }
522
523 fn push_item(&mut self, value: Object) -> Result<ObjectRefMut<'_>, Object> {
524 let value = into_typed(value)?;
525 self.push_back(value);
526
527 Ok(ObjectRefMut::new(self.back_mut().expect("just pushed")))
528 }
529
530 fn insert_item(&mut self, index: usize, value: Object) -> Result<ObjectRefMut<'_>, Object> {
531 if index > self.len() {
532 return Err(value);
533 }
534
535 let value = into_typed(value)?;
536 let mut tail = self.split_off(index);
537 self.push_back(value);
538 self.append(&mut tail);
539
540 Ok(ObjectRefMut::new(
541 self.iter_mut().nth(index).expect("just inserted"),
542 ))
543 }
544
545 fn remove_item(&mut self, index: usize) -> Option<Object> {
546 (index < self.len()).then(|| {
547 let mut tail = self.split_off(index);
548 let value = tail.pop_front().expect("just split at a valid index");
549 self.append(&mut tail);
550 Object::new(value)
551 })
552 }
553
554 fn move_item(&mut self, from: usize, to: usize) -> Result<(), crate::MoveItemError> {
555 move_linked_list_item(self, from, to)
556 }
557}
558
559impl_seq_meta!(
560 type = BTreeSet<T>,
561 generics = [T],
562 bounds = [T: Meta + Ord + 'static],
563 item = iter,
564 len = method,
565 eq = ordered_eq,
566);
567
568impl<T> MetaMut for BTreeSet<T>
575where
576 T: Meta + Ord + 'static,
577{
578 set_body!();
579
580 fn reflect_mut(&mut self) -> ReflectMut<'_> {
581 ReflectMut::Opaque
582 }
583
584 fn as_any_mut(&mut self) -> &mut dyn Any {
585 self
586 }
587}
588
589impl_seq_meta!(
590 type = BinaryHeap<T>,
591 generics = [T],
592 bounds = [T: Meta + Ord + 'static],
593 item = iter,
594 len = method,
595 eq = sorted_eq,
596);
597
598impl<T> MetaMut for BinaryHeap<T>
603where
604 T: Meta + Ord + 'static,
605{
606 set_body!();
607
608 fn reflect_mut(&mut self) -> ReflectMut<'_> {
609 ReflectMut::Opaque
610 }
611
612 fn as_any_mut(&mut self) -> &mut dyn Any {
613 self
614 }
615}
616
617impl<T> Meta for Option<T>
618where
619 T: Meta + 'static,
620{
621 fn reflect(&self) -> Reflect<'_> {
622 Reflect::Option(self.as_ref().map(|value| ObjectRef::new(value)))
623 }
624
625 fn field_dyn(&self, name: &str) -> Option<ObjectRef<'_>> {
630 self.as_ref()?.field_dyn(name)
631 }
632
633 fn key_dyn(&self, key: &str) -> Option<ObjectRef<'_>> {
634 self.as_ref()?.key_dyn(key)
635 }
636
637 fn access_kind_dyn(&self) -> Option<AccessKind> {
638 self.as_ref()?.access_kind_dyn()
639 }
640
641 fn field_names_dyn(&self) -> &'static [&'static str] {
642 self.as_ref().map_or(&[], Meta::field_names_dyn)
643 }
644
645 fn visit_map_entries_dyn(&self, visitor: &mut MapEntryVisitor<'_>) -> bool {
646 self
647 .as_ref()
648 .is_some_and(|value| value.visit_map_entries_dyn(visitor))
649 }
650
651 fn into_any(self: Box<Self>) -> Box<dyn Any> {
652 self
653 }
654
655 fn as_any(&self) -> &dyn Any {
656 self
657 }
658}
659
660impl<T> MetaMut for Option<T>
661where
662 T: MetaMut + 'static,
663{
664 set_body!();
665
666 fn reflect_mut(&mut self) -> ReflectMut<'_> {
667 ReflectMut::Option(self)
668 }
669
670 fn field_mut_dyn(&mut self, name: &str) -> Option<ObjectRefMut<'_>> {
675 self.as_mut()?.field_mut_dyn(name)
676 }
677
678 fn key_mut_dyn(&mut self, key: &str) -> Option<ObjectRefMut<'_>> {
679 self.as_mut()?.key_mut_dyn(key)
680 }
681
682 fn item_mut_dyn(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
683 if index == 0 {
684 OptionAccessMut::value_mut(self)
685 } else {
686 None
687 }
688 }
689
690 fn as_any_mut(&mut self) -> &mut dyn Any {
691 self
692 }
693}
694
695impl<T> OptionAccessMut for Option<T>
696where
697 T: MetaMut + 'static,
698{
699 fn value_mut(&mut self) -> Option<ObjectRefMut<'_>> {
700 self.as_mut().map(|value| ObjectRefMut::new(value))
701 }
702
703 fn insert_value(&mut self, value: Object) -> Result<ObjectRefMut<'_>, Object> {
704 if self.is_some() {
705 return Err(value);
706 }
707
708 let value = into_typed(value)?;
709 Ok(ObjectRefMut::new(self.insert(value)))
710 }
711
712 fn take_value(&mut self) -> Option<Object> {
713 self.take().map(Object::new)
714 }
715}
716
717impl<T, E> Meta for Result<T, E>
718where
719 T: Meta + 'static,
720 E: Meta + 'static,
721{
722 fn reflect(&self) -> Reflect<'_> {
723 Reflect::Enum(self)
724 }
725
726 fn is_variant_dyn(&self, name: &str) -> Option<bool> {
727 Some(match self {
728 Self::Ok(_) => name == "Ok",
729 Self::Err(_) => name == "Err",
730 })
731 }
732
733 fn eq_dyn(&self, other: &dyn Meta) -> bool {
734 match (self, other.as_any().downcast_ref::<Self>()) {
735 (Self::Ok(value), Some(Self::Ok(other))) => value.eq_dyn(other),
736 (Self::Err(error), Some(Self::Err(other))) => error.eq_dyn(other),
737 _ => false,
738 }
739 }
740
741 fn into_any(self: Box<Self>) -> Box<dyn Any> {
742 self
743 }
744
745 fn as_any(&self) -> &dyn Any {
746 self
747 }
748}
749
750impl<T, E> EnumAccess for Result<T, E>
753where
754 T: Meta + 'static,
755 E: Meta + 'static,
756{
757 fn variant_name(&self) -> &'static str {
758 match self {
759 Self::Ok(_) => "Ok",
760 Self::Err(_) => "Err",
761 }
762 }
763
764 fn fields(&self) -> VariantFields<'_> {
765 VariantFields::Positional(self)
766 }
767}
768
769impl<T, E> TupleAccess for Result<T, E>
770where
771 T: Meta + 'static,
772 E: Meta + 'static,
773{
774 fn item(&self, index: usize) -> Option<ObjectRef<'_>> {
775 match (self, index) {
776 (Self::Ok(value), 0) => Some(ObjectRef::new(value)),
777 (Self::Err(error), 0) => Some(ObjectRef::new(error)),
778 _ => None,
779 }
780 }
781
782 fn len(&self) -> usize {
783 1
784 }
785}
786
787impl<T, E> MetaMut for Result<T, E>
788where
789 T: MetaMut + 'static,
790 E: MetaMut + 'static,
791{
792 set_body!();
793
794 fn reflect_mut(&mut self) -> ReflectMut<'_> {
795 ReflectMut::Enum(self)
796 }
797
798 fn as_any_mut(&mut self) -> &mut dyn Any {
799 self
800 }
801}
802
803impl<T, E> EnumAccessMut for Result<T, E>
804where
805 T: MetaMut + 'static,
806 E: MetaMut + 'static,
807{
808 fn fields_mut(&mut self) -> VariantFieldsMut<'_> {
809 VariantFieldsMut::Positional(self)
810 }
811}
812
813impl<T, E> TupleAccessMut for Result<T, E>
814where
815 T: MetaMut + 'static,
816 E: MetaMut + 'static,
817{
818 fn item_mut(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
819 match (self, index) {
820 (Self::Ok(value), 0) => Some(ObjectRefMut::new(value)),
821 (Self::Err(error), 0) => Some(ObjectRefMut::new(error)),
822 _ => None,
823 }
824 }
825}
826
827macro_rules! impl_tuple_meta {
828 ($(($($idx:tt => $ty:ident),+)),* $(,)?) => {
829 $(
830 impl<$($ty),+> Meta for ($($ty,)+)
831 where
832 $($ty: Meta + 'static,)+
833 {
834 fn reflect(&self) -> Reflect<'_> {
835 Reflect::Tuple(self)
836 }
837
838 fn eq_dyn(&self, other: &dyn Meta) -> bool {
839 other
840 .as_any()
841 .downcast_ref::<Self>()
842 .is_some_and(|other| true $(&& self.$idx.eq_dyn(&other.$idx))+)
843 }
844
845 fn into_any(self: Box<Self>) -> Box<dyn Any> {
846 self
847 }
848
849 fn as_any(&self) -> &dyn Any {
850 self
851 }
852 }
853
854 impl<$($ty),+> TupleAccess for ($($ty,)+)
855 where
856 $($ty: Meta + 'static,)+
857 {
858 fn item(&self, index: usize) -> Option<ObjectRef<'_>> {
859 match index {
860 $($idx => Some(ObjectRef::new(&self.$idx)),)+
861 _ => None,
862 }
863 }
864
865 fn len(&self) -> usize {
866 <[_]>::len(&[$($idx),+])
867 }
868 }
869
870 impl<$($ty),+> MetaMut for ($($ty,)+)
871 where
872 $($ty: MetaMut + 'static,)+
873 {
874 set_body!();
875
876 fn reflect_mut(&mut self) -> ReflectMut<'_> {
877 ReflectMut::Tuple(self)
878 }
879
880 fn as_any_mut(&mut self) -> &mut dyn Any {
881 self
882 }
883 }
884
885 impl<$($ty),+> TupleAccessMut for ($($ty,)+)
886 where
887 $($ty: MetaMut + 'static,)+
888 {
889 fn item_mut(&mut self, index: usize) -> Option<ObjectRefMut<'_>> {
890 match index {
891 $($idx => Some(ObjectRefMut::new(&mut self.$idx)),)+
892 _ => None,
893 }
894 }
895 }
896 )*
897 };
898}
899
900impl_tuple_meta!(
901 (0 => T0),
902 (0 => T0, 1 => T1),
903 (0 => T0, 1 => T1, 2 => T2),
904 (0 => T0, 1 => T1, 2 => T2, 3 => T3),
905 (0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4),
906 (0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5),
907 (0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6),
908 (0 => T0, 1 => T1, 2 => T2, 3 => T3, 4 => T4, 5 => T5, 6 => T6, 7 => T7),
909);
910
911macro_rules! impl_map_meta {
912 (
913 type = $ty:ty,
914 generics = [$($generics:tt)*],
915 bounds = [$($bounds:tt)*],
916 lookup = $lookup:ident,
917 equality = $eq:ident $(,)?
918 ) => {
919 impl<$($generics)*> Meta for $ty
920 where
921 $($bounds)*
922 {
923 fn reflect(&self) -> Reflect<'_> {
924 Reflect::Map(self)
925 }
926
927 fn eq_dyn(&self, other: &dyn Meta) -> bool {
928 $eq(self, other)
929 }
930
931 fn into_any(self: Box<Self>) -> Box<dyn Any> {
932 self
933 }
934
935 fn as_any(&self) -> &dyn Any {
936 self
937 }
938 }
939
940 impl<$($generics)*> MapAccess for $ty
941 where
942 $($bounds)*
943 {
944 fn len(&self) -> usize {
945 self.len()
946 }
947
948 fn key(&self, key: &str) -> Option<ObjectRef<'_>> {
949 $lookup(self, key).map(|value| ObjectRef::new(value))
950 }
951
952 fn keys(&self) -> Option<Vec<String>> {
953 self.keys().map(as_map_key).collect()
954 }
955
956 #[inline]
957 fn visit_entries(&self, visitor: &mut MapEntryVisitor<'_>) {
958 for (key, value) in self {
959 if !visitor(AnyRef::new(key), ObjectRef::new(value)) {
960 break;
961 }
962 }
963 }
964 }
965 };
966}
967
968fn btree_map_eq<K, V>(this: &BTreeMap<K, V>, other: &dyn Meta) -> bool
974where
975 K: Ord + 'static,
976 V: Meta + 'static,
977{
978 let Some(other) = other.as_any().downcast_ref::<BTreeMap<K, V>>() else {
979 return false;
980 };
981
982 this.len() == other.len()
983 && this
984 .iter()
985 .zip(other)
986 .all(|((key, value), (other_key, other_value))| key == other_key && value.eq_dyn(other_value))
987}
988
989#[cfg(feature = "std")]
994fn hash_map_eq<K, V, S>(this: &HashMap<K, V, S>, other: &dyn Meta) -> bool
995where
996 K: Eq + Hash + 'static,
997 V: Meta + 'static,
998 S: core::hash::BuildHasher + 'static,
999{
1000 let Some(other) = other.as_any().downcast_ref::<HashMap<K, V, S>>() else {
1001 return false;
1002 };
1003
1004 this.len() == other.len()
1005 && this.iter().all(|(key, value)| {
1006 other
1007 .get(key)
1008 .is_some_and(|other_value| value.eq_dyn(other_value))
1009 })
1010}
1011
1012macro_rules! impl_typed_map_access {
1013 (
1014 type = $ty:ty,
1015 generics = [$($generics:tt)*],
1016 read_bounds = [$($read_bounds:tt)*],
1017 mut_bounds = [$($mut_bounds:tt)*] $(,)?
1018 ) => {
1019 impl<$($generics)*> TypedMapAccess<K> for $ty
1020 where
1021 $($read_bounds)*
1022 {
1023 fn key_typed(&self, key: &K) -> Option<ObjectRef<'_>> {
1024 self
1025 .get(key)
1026 .map(|value| ObjectRef::new(value))
1027 }
1028 }
1029
1030 impl<$($generics)*> TypedMapAccessMut<K> for $ty
1031 where
1032 $($mut_bounds)*
1033 {
1034 fn key_typed_mut(&mut self, key: &K) -> Option<ObjectRefMut<'_>> {
1035 self
1036 .get_mut(key)
1037 .map(|value| ObjectRefMut::new(value))
1038 }
1039 }
1040 };
1041}
1042
1043macro_rules! impl_map_mut {
1044 (
1045 type = $ty:ty,
1046 string_map = $string_map:ty,
1047 static_str_map = $static_str_map:ty,
1048 generics = [$($generics:tt)*],
1049 bounds = [$($bounds:tt)*],
1050 lookup = $lookup:ident $(,)?
1051 ) => {
1052 impl<$($generics)*> MetaMut for $ty
1053 where
1054 $($bounds)*
1055 {
1056 set_body!();
1057
1058 fn reflect_mut(&mut self) -> ReflectMut<'_> {
1059 ReflectMut::Map(self)
1060 }
1061
1062 fn as_any_mut(&mut self) -> &mut dyn Any {
1063 self
1064 }
1065 }
1066
1067 impl<$($generics)*> MapAccessMut for $ty
1068 where
1069 $($bounds)*
1070 {
1071 fn key_mut(&mut self, key: &str) -> Option<ObjectRefMut<'_>> {
1072 $lookup(self, key).map(|value| ObjectRefMut::new(value))
1073 }
1074
1075 fn insert_key(&mut self, key: &str, value: Object) -> Result<ObjectRefMut<'_>, Object> {
1076 if !value.is::<V>() {
1077 return Err(value);
1078 }
1079
1080 if TypeId::of::<K>() == TypeId::of::<String>() {
1081 let value = *value.into_inner().into_any().downcast::<V>().unwrap();
1083 let map = (self as &mut dyn Any)
1084 .downcast_mut::<$string_map>()
1085 .unwrap();
1086 map.insert(key.to_owned(), value);
1087 return Ok(MapAccessMut::key_mut(self, key).expect("just inserted"));
1088 }
1089
1090 Err(value)
1093 }
1094
1095 fn remove_key(&mut self, key: &str) -> Option<Object> {
1096 if TypeId::of::<K>() == TypeId::of::<String>() {
1097 let map = (self as &mut dyn Any)
1098 .downcast_mut::<$string_map>()
1099 .unwrap();
1100 return map.remove(key).map(Object::new);
1101 }
1102 if TypeId::of::<K>() == TypeId::of::<&'static str>() {
1103 let map = (self as &mut dyn Any)
1104 .downcast_mut::<$static_str_map>()
1105 .unwrap();
1106 return map.remove(key).map(Object::new);
1107 }
1108
1109 None
1111 }
1112 }
1113 };
1114}
1115impl_map_meta!(
1116 type = BTreeMap<K, V>,
1117 generics = [K, V],
1118 bounds = [K: Ord + 'static, V: Meta + 'static],
1119 lookup = btree_map_get,
1120 equality = btree_map_eq,
1121);
1122
1123impl_typed_map_access!(
1124 type = BTreeMap<K, V>,
1125 generics = [K, V],
1126 read_bounds = [K: Ord + 'static, V: Meta + 'static],
1127 mut_bounds = [K: Ord + 'static, V: MetaMut + 'static],
1128);
1129
1130impl_map_mut!(
1131 type = BTreeMap<K, V>,
1132 string_map = BTreeMap<String, V>,
1133 static_str_map = BTreeMap<&'static str, V>,
1134 generics = [K, V],
1135 bounds = [K: Ord + 'static, V: MetaMut + 'static],
1136 lookup = btree_map_get_mut,
1137);
1138
1139#[cfg(feature = "std")]
1140impl_map_meta!(
1141 type = HashMap<K, V, S>,
1142 generics = [K, V, S],
1143 bounds = [K: Eq + Hash + 'static, V: Meta + 'static, S: core::hash::BuildHasher + 'static],
1144 lookup = hash_map_get,
1145 equality = hash_map_eq,
1146);
1147
1148#[cfg(feature = "std")]
1149impl_typed_map_access!(
1150 type = HashMap<K, V, S>,
1151 generics = [K, V, S],
1152 read_bounds = [K: Eq + Hash + 'static, V: Meta + 'static, S: core::hash::BuildHasher + 'static],
1153 mut_bounds = [K: Eq + Hash + 'static, V: MetaMut + 'static, S: core::hash::BuildHasher + 'static],
1154);
1155
1156#[cfg(feature = "std")]
1157impl_map_mut!(
1158 type = HashMap<K, V, S>,
1159 string_map = HashMap<String, V, S>,
1160 static_str_map = HashMap<&'static str, V, S>,
1161 generics = [K, V, S],
1162 bounds = [K: Eq + Hash + 'static, V: MetaMut + 'static, S: core::hash::BuildHasher + 'static],
1163 lookup = hash_map_get_mut,
1164);