Skip to main content

bevy_reflect/impls/core/
primitives.rs

1use crate::{
2    array::{Array, ArrayInfo, ArrayIter},
3    error::ReflectCloneError,
4    kind::{ReflectKind, ReflectMut, ReflectOwned, ReflectRef},
5    prelude::*,
6    reflect::ApplyError,
7    type_info::{MaybeTyped, OpaqueInfo, TypeInfo, Typed},
8    type_registry::{
9        FromType, GetTypeRegistration, ReflectDeserialize, ReflectFromPtr, ReflectSerialize,
10        TypeRegistration, TypeRegistry,
11    },
12    utility::{reflect_hasher, GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell},
13};
14use bevy_platform::prelude::*;
15use bevy_reflect_derive::{impl_reflect_opaque, impl_type_path};
16use core::any::Any;
17use core::fmt;
18use core::hash::{Hash, Hasher};
19
20impl_reflect_opaque!(bool(
21    Clone,
22    Debug,
23    Hash,
24    PartialEq,
25    PartialOrd,
26    Serialize,
27    Deserialize,
28    Default,
29));
30impl_reflect_opaque!(char(
31    Clone,
32    Debug,
33    Hash,
34    PartialEq,
35    PartialOrd,
36    Serialize,
37    Deserialize,
38    Default,
39));
40impl_reflect_opaque!(u8(
41    Clone,
42    Debug,
43    Hash,
44    PartialEq,
45    PartialOrd,
46    Serialize,
47    Deserialize,
48    Default,
49    Add,
50    AddAssign,
51    Sub,
52    SubAssign,
53    Mul,
54    MulAssign,
55    Div,
56    DivAssign,
57    Rem,
58    RemAssign,
59));
60impl_reflect_opaque!(u16(
61    Clone,
62    Debug,
63    Hash,
64    PartialEq,
65    PartialOrd,
66    Serialize,
67    Deserialize,
68    Default,
69    Add,
70    AddAssign,
71    Sub,
72    SubAssign,
73    Mul,
74    MulAssign,
75    Div,
76    DivAssign,
77    Rem,
78    RemAssign,
79));
80impl_reflect_opaque!(u32(
81    Clone,
82    Debug,
83    Hash,
84    PartialEq,
85    PartialOrd,
86    Serialize,
87    Deserialize,
88    Default,
89    Add,
90    AddAssign,
91    Sub,
92    SubAssign,
93    Mul,
94    MulAssign,
95    Div,
96    DivAssign,
97    Rem,
98    RemAssign,
99));
100impl_reflect_opaque!(u64(
101    Clone,
102    Debug,
103    Hash,
104    PartialEq,
105    PartialOrd,
106    Serialize,
107    Deserialize,
108    Default,
109    Add,
110    AddAssign,
111    Sub,
112    SubAssign,
113    Mul,
114    MulAssign,
115    Div,
116    DivAssign,
117    Rem,
118    RemAssign,
119));
120impl_reflect_opaque!(u128(
121    Clone,
122    Debug,
123    Hash,
124    PartialEq,
125    PartialOrd,
126    Serialize,
127    Deserialize,
128    Default,
129    Add,
130    AddAssign,
131    Sub,
132    SubAssign,
133    Mul,
134    MulAssign,
135    Div,
136    DivAssign,
137    Rem,
138    RemAssign,
139));
140impl_reflect_opaque!(usize(
141    Clone,
142    Debug,
143    Hash,
144    PartialEq,
145    PartialOrd,
146    Serialize,
147    Deserialize,
148    Default,
149    Add,
150    AddAssign,
151    Sub,
152    SubAssign,
153    Mul,
154    MulAssign,
155    Div,
156    DivAssign,
157    Rem,
158    RemAssign,
159));
160impl_reflect_opaque!(i8(
161    Clone,
162    Debug,
163    Hash,
164    PartialEq,
165    PartialOrd,
166    Serialize,
167    Deserialize,
168    Default,
169    Add,
170    AddAssign,
171    Sub,
172    SubAssign,
173    Mul,
174    MulAssign,
175    Div,
176    DivAssign,
177    Rem,
178    RemAssign,
179));
180impl_reflect_opaque!(i16(
181    Clone,
182    Debug,
183    Hash,
184    PartialEq,
185    PartialOrd,
186    Serialize,
187    Deserialize,
188    Default,
189    Add,
190    AddAssign,
191    Sub,
192    SubAssign,
193    Mul,
194    MulAssign,
195    Div,
196    DivAssign,
197    Rem,
198    RemAssign,
199));
200impl_reflect_opaque!(i32(
201    Clone,
202    Debug,
203    Hash,
204    PartialEq,
205    PartialOrd,
206    Serialize,
207    Deserialize,
208    Default,
209    Add,
210    AddAssign,
211    Sub,
212    SubAssign,
213    Mul,
214    MulAssign,
215    Div,
216    DivAssign,
217    Rem,
218    RemAssign,
219));
220impl_reflect_opaque!(i64(
221    Clone,
222    Debug,
223    Hash,
224    PartialEq,
225    PartialOrd,
226    Serialize,
227    Deserialize,
228    Default,
229    Add,
230    AddAssign,
231    Sub,
232    SubAssign,
233    Mul,
234    MulAssign,
235    Div,
236    DivAssign,
237    Rem,
238    RemAssign,
239));
240impl_reflect_opaque!(i128(
241    Clone,
242    Debug,
243    Hash,
244    PartialEq,
245    PartialOrd,
246    Serialize,
247    Deserialize,
248    Default,
249    Add,
250    AddAssign,
251    Sub,
252    SubAssign,
253    Mul,
254    MulAssign,
255    Div,
256    DivAssign,
257    Rem,
258    RemAssign,
259));
260impl_reflect_opaque!(isize(
261    Clone,
262    Debug,
263    Hash,
264    PartialEq,
265    PartialOrd,
266    Serialize,
267    Deserialize,
268    Default,
269    Add,
270    AddAssign,
271    Sub,
272    SubAssign,
273    Mul,
274    MulAssign,
275    Div,
276    DivAssign,
277    Rem,
278    RemAssign,
279));
280impl_reflect_opaque!(f32(
281    Clone,
282    Debug,
283    PartialEq,
284    PartialOrd,
285    Serialize,
286    Deserialize,
287    Default,
288    Add,
289    AddAssign,
290    Sub,
291    SubAssign,
292    Mul,
293    MulAssign,
294    Div,
295    DivAssign,
296    Rem,
297    RemAssign,
298));
299impl_reflect_opaque!(f64(
300    Clone,
301    Debug,
302    PartialEq,
303    PartialOrd,
304    Serialize,
305    Deserialize,
306    Default,
307    Add,
308    AddAssign,
309    Sub,
310    SubAssign,
311    Mul,
312    MulAssign,
313    Div,
314    DivAssign,
315    Rem,
316    RemAssign,
317));
318impl_type_path!(str);
319
320impl PartialReflect for &'static str {
321    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
322        Some(<Self as Typed>::type_info())
323    }
324
325    #[inline]
326    fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
327        self
328    }
329
330    fn as_partial_reflect(&self) -> &dyn PartialReflect {
331        self
332    }
333
334    fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
335        self
336    }
337
338    fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
339        Ok(self)
340    }
341
342    fn try_as_reflect(&self) -> Option<&dyn Reflect> {
343        Some(self)
344    }
345
346    fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
347        Some(self)
348    }
349
350    fn reflect_ref(&self) -> ReflectRef<'_> {
351        ReflectRef::Opaque(self)
352    }
353
354    fn reflect_mut(&mut self) -> ReflectMut<'_> {
355        ReflectMut::Opaque(self)
356    }
357
358    fn reflect_owned(self: Box<Self>) -> ReflectOwned {
359        ReflectOwned::Opaque(self)
360    }
361
362    fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
363        Ok(Box::new(*self))
364    }
365
366    fn reflect_hash(&self) -> Option<u64> {
367        let mut hasher = reflect_hasher();
368        Hash::hash(&Any::type_id(self), &mut hasher);
369        Hash::hash(self, &mut hasher);
370        Some(hasher.finish())
371    }
372
373    fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
374        if let Some(value) = value.try_downcast_ref::<Self>() {
375            Some(PartialEq::eq(self, value))
376        } else {
377            Some(false)
378        }
379    }
380
381    fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<core::cmp::Ordering> {
382        if let Some(value) = value.try_downcast_ref::<Self>() {
383            PartialOrd::partial_cmp(self, value)
384        } else {
385            None
386        }
387    }
388
389    fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
390        fmt::Debug::fmt(&self, f)
391    }
392
393    fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
394        if let Some(value) = value.try_downcast_ref::<Self>() {
395            self.clone_from(value);
396        } else {
397            return Err(ApplyError::MismatchedTypes {
398                from_type: value.reflect_type_path().into(),
399                to_type: Self::type_path().into(),
400            });
401        }
402        Ok(())
403    }
404}
405
406impl Reflect for &'static str {
407    fn into_any(self: Box<Self>) -> Box<dyn Any> {
408        self
409    }
410
411    fn as_any(&self) -> &dyn Any {
412        self
413    }
414
415    fn as_any_mut(&mut self) -> &mut dyn Any {
416        self
417    }
418
419    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
420        self
421    }
422
423    fn as_reflect(&self) -> &dyn Reflect {
424        self
425    }
426
427    fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
428        self
429    }
430
431    fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
432        *self = value.take()?;
433        Ok(())
434    }
435}
436
437impl Typed for &'static str {
438    fn type_info() -> &'static TypeInfo {
439        static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
440        CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::<Self>()))
441    }
442}
443
444impl GetTypeRegistration for &'static str {
445    fn get_type_registration() -> TypeRegistration {
446        let mut registration = TypeRegistration::of::<Self>();
447        registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
448        registration.insert::<ReflectFromReflect>(FromType::<Self>::from_type());
449        registration.insert::<ReflectSerialize>(FromType::<Self>::from_type());
450        registration
451    }
452}
453
454impl FromReflect for &'static str {
455    fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
456        reflect.try_downcast_ref::<Self>().copied()
457    }
458}
459
460impl<T: Reflect + MaybeTyped + TypePath + GetTypeRegistration, const N: usize> Array for [T; N] {
461    #[inline]
462    fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
463        <[T]>::get(self, index).map(|value| value as &dyn PartialReflect)
464    }
465
466    #[inline]
467    fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
468        <[T]>::get_mut(self, index).map(|value| value as &mut dyn PartialReflect)
469    }
470
471    #[inline]
472    fn len(&self) -> usize {
473        N
474    }
475
476    #[inline]
477    fn iter(&self) -> ArrayIter<'_> {
478        ArrayIter::new(self)
479    }
480
481    #[inline]
482    fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
483        self.into_iter()
484            .map(|value| Box::new(value) as Box<dyn PartialReflect>)
485            .collect()
486    }
487}
488
489impl<T: Reflect + MaybeTyped + TypePath + GetTypeRegistration, const N: usize> PartialReflect
490    for [T; N]
491{
492    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
493        Some(<Self as Typed>::type_info())
494    }
495
496    #[inline]
497    fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
498        self
499    }
500
501    fn as_partial_reflect(&self) -> &dyn PartialReflect {
502        self
503    }
504
505    fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
506        self
507    }
508
509    fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
510        Ok(self)
511    }
512
513    fn try_as_reflect(&self) -> Option<&dyn Reflect> {
514        Some(self)
515    }
516
517    fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
518        Some(self)
519    }
520
521    #[inline]
522    fn reflect_kind(&self) -> ReflectKind {
523        ReflectKind::Array
524    }
525
526    #[inline]
527    fn reflect_ref(&self) -> ReflectRef<'_> {
528        ReflectRef::Array(self)
529    }
530
531    #[inline]
532    fn reflect_mut(&mut self) -> ReflectMut<'_> {
533        ReflectMut::Array(self)
534    }
535
536    #[inline]
537    fn reflect_owned(self: Box<Self>) -> ReflectOwned {
538        ReflectOwned::Array(self)
539    }
540
541    #[inline]
542    fn reflect_hash(&self) -> Option<u64> {
543        crate::array::array_hash(self)
544    }
545
546    #[inline]
547    fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
548        crate::array::array_partial_eq(self, value)
549    }
550
551    #[inline]
552    fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<::core::cmp::Ordering> {
553        crate::array::array_partial_cmp(self, value)
554    }
555
556    fn apply(&mut self, value: &dyn PartialReflect) {
557        crate::array::array_apply(self, value);
558    }
559
560    #[inline]
561    fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
562        crate::array::array_try_apply(self, value)
563    }
564}
565
566impl<T: Reflect + MaybeTyped + TypePath + GetTypeRegistration, const N: usize> Reflect for [T; N] {
567    #[inline]
568    fn into_any(self: Box<Self>) -> Box<dyn Any> {
569        self
570    }
571
572    #[inline]
573    fn as_any(&self) -> &dyn Any {
574        self
575    }
576
577    #[inline]
578    fn as_any_mut(&mut self) -> &mut dyn Any {
579        self
580    }
581
582    #[inline]
583    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
584        self
585    }
586
587    #[inline]
588    fn as_reflect(&self) -> &dyn Reflect {
589        self
590    }
591
592    #[inline]
593    fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
594        self
595    }
596
597    #[inline]
598    fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
599        *self = value.take()?;
600        Ok(())
601    }
602}
603
604impl<T: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, const N: usize> FromReflect
605    for [T; N]
606{
607    fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
608        let ref_array = reflect.reflect_ref().as_array().ok()?;
609
610        let mut temp_vec = Vec::with_capacity(ref_array.len());
611
612        for field in ref_array.iter() {
613            temp_vec.push(T::from_reflect(field)?);
614        }
615
616        temp_vec.try_into().ok()
617    }
618}
619
620impl<T: Reflect + MaybeTyped + TypePath + GetTypeRegistration, const N: usize> Typed for [T; N] {
621    fn type_info() -> &'static TypeInfo {
622        static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
623        CELL.get_or_insert::<Self, _>(|| TypeInfo::Array(ArrayInfo::new::<Self, T>(N)))
624    }
625}
626
627impl<T: TypePath, const N: usize> TypePath for [T; N] {
628    fn type_path() -> &'static str {
629        static CELL: GenericTypePathCell = GenericTypePathCell::new();
630        CELL.get_or_insert::<Self, _>(|| format!("[{t}; {N}]", t = T::type_path()))
631    }
632
633    fn short_type_path() -> &'static str {
634        static CELL: GenericTypePathCell = GenericTypePathCell::new();
635        CELL.get_or_insert::<Self, _>(|| format!("[{t}; {N}]", t = T::short_type_path()))
636    }
637}
638
639impl<T: Reflect + MaybeTyped + TypePath + GetTypeRegistration, const N: usize> GetTypeRegistration
640    for [T; N]
641{
642    fn get_type_registration() -> TypeRegistration {
643        TypeRegistration::of::<[T; N]>()
644    }
645
646    fn register_type_dependencies(registry: &mut TypeRegistry) {
647        registry.register::<T>();
648    }
649}
650
651#[cfg(feature = "functions")]
652crate::func::macros::impl_function_traits!([T; N]; <T: Reflect + MaybeTyped + TypePath + GetTypeRegistration> [const N: usize]);
653
654impl<T: TypePath> TypePath for [T]
655where
656    [T]: ToOwned,
657{
658    fn type_path() -> &'static str {
659        static CELL: GenericTypePathCell = GenericTypePathCell::new();
660        CELL.get_or_insert::<Self, _>(|| format!("[{}]", <T>::type_path()))
661    }
662
663    fn short_type_path() -> &'static str {
664        static CELL: GenericTypePathCell = GenericTypePathCell::new();
665        CELL.get_or_insert::<Self, _>(|| format!("[{}]", <T>::short_type_path()))
666    }
667}
668
669impl<T: TypePath + ?Sized> TypePath for &'static T {
670    fn type_path() -> &'static str {
671        static CELL: GenericTypePathCell = GenericTypePathCell::new();
672        CELL.get_or_insert::<Self, _>(|| format!("&{}", T::type_path()))
673    }
674
675    fn short_type_path() -> &'static str {
676        static CELL: GenericTypePathCell = GenericTypePathCell::new();
677        CELL.get_or_insert::<Self, _>(|| format!("&{}", T::short_type_path()))
678    }
679}
680
681impl<T: TypePath + ?Sized> TypePath for &'static mut T {
682    fn type_path() -> &'static str {
683        static CELL: GenericTypePathCell = GenericTypePathCell::new();
684        CELL.get_or_insert::<Self, _>(|| format!("&mut {}", T::type_path()))
685    }
686
687    fn short_type_path() -> &'static str {
688        static CELL: GenericTypePathCell = GenericTypePathCell::new();
689        CELL.get_or_insert::<Self, _>(|| format!("&mut {}", T::short_type_path()))
690    }
691}
692
693#[cfg(test)]
694mod tests {
695    use alloc::boxed::Box;
696    use bevy_reflect::{FromReflect, PartialReflect};
697    use core::{
698        any::TypeId,
699        f32::consts::{PI, TAU},
700        ops::{Add, Div, Mul, Rem, Sub},
701    };
702
703    use crate::{
704        prelude::{
705            ReflectAdd, ReflectDivAssign, ReflectMulAssign, ReflectRem, ReflectRemAssign,
706            ReflectSubAssign,
707        },
708        std_traits::{ReflectAddAssign, ReflectDiv, ReflectMul, ReflectSub},
709        Reflect, TypeRegistry,
710    };
711
712    #[test]
713    fn should_partial_eq_char() {
714        let a: &dyn PartialReflect = &'x';
715        let b: &dyn PartialReflect = &'x';
716        let c: &dyn PartialReflect = &'o';
717        assert!(a.reflect_partial_eq(b).unwrap_or_default());
718        assert!(!a.reflect_partial_eq(c).unwrap_or_default());
719    }
720
721    #[test]
722    fn should_partial_eq_i32() {
723        let a: &dyn PartialReflect = &123_i32;
724        let b: &dyn PartialReflect = &123_i32;
725        let c: &dyn PartialReflect = &321_i32;
726        assert!(a.reflect_partial_eq(b).unwrap_or_default());
727        assert!(!a.reflect_partial_eq(c).unwrap_or_default());
728    }
729
730    #[test]
731    fn should_partial_eq_f32() {
732        let a: &dyn PartialReflect = &PI;
733        let b: &dyn PartialReflect = &PI;
734        let c: &dyn PartialReflect = &TAU;
735        assert!(a.reflect_partial_eq(b).unwrap_or_default());
736        assert!(!a.reflect_partial_eq(c).unwrap_or_default());
737    }
738
739    #[test]
740    fn should_partial_cmp_f32() {
741        use core::cmp::Ordering;
742
743        let a: &dyn PartialReflect = &1.0_f32;
744        let b: &dyn PartialReflect = &2.0_f32;
745
746        let ord = a.reflect_partial_cmp(b);
747        assert_eq!(ord, Some(Ordering::Less));
748
749        // mismatched type should return None
750        let ord_mismatch = a.reflect_partial_cmp(&1i32);
751        assert_eq!(ord_mismatch, None);
752    }
753
754    #[test]
755    fn reflect_partial_cmp_f32_nan() {
756        // NaN comparisons should return None
757        let nan = f32::NAN;
758        assert_eq!(PartialReflect::reflect_partial_cmp(&nan, &nan), None);
759    }
760
761    #[test]
762    fn static_str_should_from_reflect() {
763        let expected = "Hello, World!";
764        let output = <&'static str as FromReflect>::from_reflect(&expected).unwrap();
765        assert_eq!(expected, output);
766    }
767
768    #[test]
769    fn should_add() {
770        fn check_add<T: Reflect + Add<Output = T> + Copy + 'static>(
771            registry: &TypeRegistry,
772            mut a: T,
773            b: T,
774            result: T,
775        ) {
776            let reflect_add = registry
777                .get_type_data::<ReflectAdd>(TypeId::of::<T>())
778                .unwrap();
779            let reflect_add_assign = registry
780                .get_type_data::<ReflectAddAssign>(TypeId::of::<T>())
781                .unwrap();
782
783            assert_eq!(
784                reflect_add
785                    .add(Box::new(a), Box::new(b))
786                    .unwrap()
787                    .reflect_partial_eq(&result),
788                Some(true)
789            );
790            reflect_add_assign.add_assign(&mut a, Box::new(b)).unwrap();
791            assert_eq!(a.reflect_partial_eq(&result), Some(true));
792
793            assert!(reflect_add.add(Box::new(a), Box::new("not a T")).is_err());
794            assert!(reflect_add.add(Box::new("not a T"), Box::new(b)).is_err());
795            assert!(reflect_add_assign
796                .add_assign(&mut a, Box::new("not a T"))
797                .is_err());
798            assert!(reflect_add_assign
799                .add_assign(&mut "not a T", Box::new(b))
800                .is_err());
801        }
802
803        let registry = TypeRegistry::new();
804
805        check_add::<u8>(&registry, 10, 5, 15);
806        check_add::<u16>(&registry, 10, 5, 15);
807        check_add::<u32>(&registry, 10, 5, 15);
808        check_add::<u64>(&registry, 10, 5, 15);
809        check_add::<u128>(&registry, 10, 5, 15);
810        check_add::<usize>(&registry, 10, 5, 15);
811        check_add::<i8>(&registry, 10, 5, 15);
812        check_add::<i16>(&registry, 10, 5, 15);
813        check_add::<i32>(&registry, 10, 5, 15);
814        check_add::<i64>(&registry, 10, 5, 15);
815        check_add::<i128>(&registry, 10, 5, 15);
816        check_add::<isize>(&registry, 10, 5, 15);
817        check_add::<f32>(&registry, 1.5, 2.5, 4.0);
818        check_add::<f64>(&registry, 1.5, 2.5, 4.0);
819    }
820
821    #[test]
822    fn should_sub() {
823        fn check_sub<T: Reflect + Sub<Output = T> + Copy + 'static>(
824            registry: &TypeRegistry,
825            mut a: T,
826            b: T,
827            result: T,
828        ) {
829            let reflect_sub = registry
830                .get_type_data::<ReflectSub>(TypeId::of::<T>())
831                .unwrap();
832            let reflect_sub_assign = registry
833                .get_type_data::<ReflectSubAssign>(TypeId::of::<T>())
834                .unwrap();
835
836            assert_eq!(
837                reflect_sub
838                    .sub(Box::new(a), Box::new(b))
839                    .unwrap()
840                    .reflect_partial_eq(&result),
841                Some(true)
842            );
843            reflect_sub_assign.sub_assign(&mut a, Box::new(b)).unwrap();
844            assert_eq!(a.reflect_partial_eq(&result), Some(true));
845
846            assert!(reflect_sub.sub(Box::new(a), Box::new("not a T")).is_err());
847            assert!(reflect_sub.sub(Box::new("not a T"), Box::new(b)).is_err());
848            assert!(reflect_sub_assign
849                .sub_assign(&mut a, Box::new("not a T"))
850                .is_err());
851            assert!(reflect_sub_assign
852                .sub_assign(&mut "not a T", Box::new(b))
853                .is_err());
854        }
855
856        let registry = TypeRegistry::new();
857
858        check_sub::<u8>(&registry, 10, 5, 5);
859        check_sub::<u16>(&registry, 10, 5, 5);
860        check_sub::<u32>(&registry, 10, 5, 5);
861        check_sub::<u64>(&registry, 10, 5, 5);
862        check_sub::<u128>(&registry, 10, 5, 5);
863        check_sub::<usize>(&registry, 10, 5, 5);
864        check_sub::<i8>(&registry, 10, 5, 5);
865        check_sub::<i16>(&registry, 10, 5, 5);
866        check_sub::<i32>(&registry, 10, 5, 5);
867        check_sub::<i64>(&registry, 10, 5, 5);
868        check_sub::<i128>(&registry, 10, 5, 5);
869        check_sub::<isize>(&registry, 10, 5, 5);
870        check_sub::<f32>(&registry, 1.5, 2.5, -1.0);
871        check_sub::<f64>(&registry, 1.5, 2.5, -1.0);
872    }
873
874    #[test]
875    fn should_mul() {
876        fn check_mul<T: Reflect + Mul<Output = T> + Copy + 'static>(
877            registry: &TypeRegistry,
878            mut a: T,
879            b: T,
880            result: T,
881        ) {
882            let reflect_mul = registry
883                .get_type_data::<ReflectMul>(TypeId::of::<T>())
884                .unwrap();
885            let reflect_mul_assign = registry
886                .get_type_data::<ReflectMulAssign>(TypeId::of::<T>())
887                .unwrap();
888
889            assert_eq!(
890                reflect_mul
891                    .mul(Box::new(a), Box::new(b))
892                    .unwrap()
893                    .reflect_partial_eq(&result),
894                Some(true)
895            );
896            reflect_mul_assign.mul_assign(&mut a, Box::new(b)).unwrap();
897            assert_eq!(a.reflect_partial_eq(&result), Some(true));
898
899            assert!(reflect_mul.mul(Box::new(a), Box::new("not a T")).is_err());
900            assert!(reflect_mul.mul(Box::new("not a T"), Box::new(b)).is_err());
901            assert!(reflect_mul_assign
902                .mul_assign(&mut a, Box::new("not a T"))
903                .is_err());
904            assert!(reflect_mul_assign
905                .mul_assign(&mut "not a T", Box::new(b))
906                .is_err());
907        }
908
909        let registry = TypeRegistry::new();
910
911        check_mul::<u8>(&registry, 10, 5, 50);
912        check_mul::<u16>(&registry, 10, 5, 50);
913        check_mul::<u32>(&registry, 10, 5, 50);
914        check_mul::<u64>(&registry, 10, 5, 50);
915        check_mul::<u128>(&registry, 10, 5, 50);
916        check_mul::<usize>(&registry, 10, 5, 50);
917        check_mul::<i8>(&registry, 10, 5, 50);
918        check_mul::<i16>(&registry, 10, 5, 50);
919        check_mul::<i32>(&registry, 10, 5, 50);
920        check_mul::<i64>(&registry, 10, 5, 50);
921        check_mul::<i128>(&registry, 10, 5, 50);
922        check_mul::<isize>(&registry, 10, 5, 50);
923        check_mul::<f32>(&registry, 5., 2., 10.);
924        check_mul::<f64>(&registry, 5., 2., 10.);
925    }
926
927    #[test]
928    fn should_div() {
929        fn check_div<T: Reflect + Div<Output = T> + Copy + 'static>(
930            registry: &TypeRegistry,
931            mut a: T,
932            b: T,
933            result: T,
934        ) {
935            let reflect_div = registry
936                .get_type_data::<ReflectDiv>(TypeId::of::<T>())
937                .unwrap();
938            let reflect_div_assign = registry
939                .get_type_data::<ReflectDivAssign>(TypeId::of::<T>())
940                .unwrap();
941
942            assert_eq!(
943                reflect_div
944                    .div(Box::new(a), Box::new(b))
945                    .unwrap()
946                    .reflect_partial_eq(&result),
947                Some(true)
948            );
949            reflect_div_assign.div_assign(&mut a, Box::new(b)).unwrap();
950            assert_eq!(a.reflect_partial_eq(&result), Some(true));
951
952            assert!(reflect_div.div(Box::new(a), Box::new("not a T")).is_err());
953            assert!(reflect_div.div(Box::new("not a T"), Box::new(b)).is_err());
954            assert!(reflect_div_assign
955                .div_assign(&mut a, Box::new("not a T"))
956                .is_err());
957            assert!(reflect_div_assign
958                .div_assign(&mut "not a T", Box::new(b))
959                .is_err());
960        }
961
962        let registry = TypeRegistry::new();
963
964        check_div::<u8>(&registry, 10, 5, 2);
965        check_div::<u16>(&registry, 10, 5, 2);
966        check_div::<u32>(&registry, 10, 5, 2);
967        check_div::<u64>(&registry, 10, 5, 2);
968        check_div::<u128>(&registry, 10, 5, 2);
969        check_div::<usize>(&registry, 10, 5, 2);
970        check_div::<i8>(&registry, 10, 5, 2);
971        check_div::<i16>(&registry, 10, 5, 2);
972        check_div::<i32>(&registry, 10, 5, 2);
973        check_div::<i64>(&registry, 10, 5, 2);
974        check_div::<i128>(&registry, 10, 5, 2);
975        check_div::<isize>(&registry, 10, 5, 2);
976        check_div::<f32>(&registry, 10., 2., 5.);
977        check_div::<f64>(&registry, 10., 2., 5.);
978    }
979
980    #[test]
981    fn should_rem() {
982        fn check_rem<T: Reflect + Rem<Output = T> + Copy + 'static>(
983            registry: &TypeRegistry,
984            mut a: T,
985            b: T,
986            result: T,
987        ) {
988            let reflect_rem = registry
989                .get_type_data::<ReflectRem>(TypeId::of::<T>())
990                .unwrap();
991            let reflect_rem_assign = registry
992                .get_type_data::<ReflectRemAssign>(TypeId::of::<T>())
993                .unwrap();
994
995            assert_eq!(
996                reflect_rem
997                    .rem(Box::new(a), Box::new(b))
998                    .unwrap()
999                    .reflect_partial_eq(&result),
1000                Some(true)
1001            );
1002            reflect_rem_assign.rem_assign(&mut a, Box::new(b)).unwrap();
1003            assert_eq!(a.reflect_partial_eq(&result), Some(true));
1004
1005            assert!(reflect_rem.rem(Box::new(a), Box::new("not a T")).is_err());
1006            assert!(reflect_rem.rem(Box::new("not a T"), Box::new(b)).is_err());
1007            assert!(reflect_rem_assign
1008                .rem_assign(&mut a, Box::new("not a T"))
1009                .is_err());
1010            assert!(reflect_rem_assign
1011                .rem_assign(&mut "not a T", Box::new(b))
1012                .is_err());
1013        }
1014
1015        let registry = TypeRegistry::new();
1016
1017        check_rem::<u8>(&registry, 10, 5, 0);
1018        check_rem::<u16>(&registry, 10, 5, 0);
1019        check_rem::<u32>(&registry, 10, 5, 0);
1020        check_rem::<u64>(&registry, 10, 5, 0);
1021        check_rem::<u128>(&registry, 10, 5, 0);
1022        check_rem::<usize>(&registry, 10, 5, 0);
1023        check_rem::<i8>(&registry, 10, 5, 0);
1024        check_rem::<i16>(&registry, 10, 5, 0);
1025        check_rem::<i32>(&registry, 10, 5, 0);
1026        check_rem::<i64>(&registry, 10, 5, 0);
1027        check_rem::<i128>(&registry, 10, 5, 0);
1028        check_rem::<isize>(&registry, 10, 5, 0);
1029        check_rem::<f32>(&registry, 10., 5., 0.);
1030        check_rem::<f64>(&registry, 10., 5., 0.);
1031    }
1032}