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 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 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>(®istry, 10, 5, 15);
806 check_add::<u16>(®istry, 10, 5, 15);
807 check_add::<u32>(®istry, 10, 5, 15);
808 check_add::<u64>(®istry, 10, 5, 15);
809 check_add::<u128>(®istry, 10, 5, 15);
810 check_add::<usize>(®istry, 10, 5, 15);
811 check_add::<i8>(®istry, 10, 5, 15);
812 check_add::<i16>(®istry, 10, 5, 15);
813 check_add::<i32>(®istry, 10, 5, 15);
814 check_add::<i64>(®istry, 10, 5, 15);
815 check_add::<i128>(®istry, 10, 5, 15);
816 check_add::<isize>(®istry, 10, 5, 15);
817 check_add::<f32>(®istry, 1.5, 2.5, 4.0);
818 check_add::<f64>(®istry, 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>(®istry, 10, 5, 5);
859 check_sub::<u16>(®istry, 10, 5, 5);
860 check_sub::<u32>(®istry, 10, 5, 5);
861 check_sub::<u64>(®istry, 10, 5, 5);
862 check_sub::<u128>(®istry, 10, 5, 5);
863 check_sub::<usize>(®istry, 10, 5, 5);
864 check_sub::<i8>(®istry, 10, 5, 5);
865 check_sub::<i16>(®istry, 10, 5, 5);
866 check_sub::<i32>(®istry, 10, 5, 5);
867 check_sub::<i64>(®istry, 10, 5, 5);
868 check_sub::<i128>(®istry, 10, 5, 5);
869 check_sub::<isize>(®istry, 10, 5, 5);
870 check_sub::<f32>(®istry, 1.5, 2.5, -1.0);
871 check_sub::<f64>(®istry, 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>(®istry, 10, 5, 50);
912 check_mul::<u16>(®istry, 10, 5, 50);
913 check_mul::<u32>(®istry, 10, 5, 50);
914 check_mul::<u64>(®istry, 10, 5, 50);
915 check_mul::<u128>(®istry, 10, 5, 50);
916 check_mul::<usize>(®istry, 10, 5, 50);
917 check_mul::<i8>(®istry, 10, 5, 50);
918 check_mul::<i16>(®istry, 10, 5, 50);
919 check_mul::<i32>(®istry, 10, 5, 50);
920 check_mul::<i64>(®istry, 10, 5, 50);
921 check_mul::<i128>(®istry, 10, 5, 50);
922 check_mul::<isize>(®istry, 10, 5, 50);
923 check_mul::<f32>(®istry, 5., 2., 10.);
924 check_mul::<f64>(®istry, 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>(®istry, 10, 5, 2);
965 check_div::<u16>(®istry, 10, 5, 2);
966 check_div::<u32>(®istry, 10, 5, 2);
967 check_div::<u64>(®istry, 10, 5, 2);
968 check_div::<u128>(®istry, 10, 5, 2);
969 check_div::<usize>(®istry, 10, 5, 2);
970 check_div::<i8>(®istry, 10, 5, 2);
971 check_div::<i16>(®istry, 10, 5, 2);
972 check_div::<i32>(®istry, 10, 5, 2);
973 check_div::<i64>(®istry, 10, 5, 2);
974 check_div::<i128>(®istry, 10, 5, 2);
975 check_div::<isize>(®istry, 10, 5, 2);
976 check_div::<f32>(®istry, 10., 2., 5.);
977 check_div::<f64>(®istry, 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>(®istry, 10, 5, 0);
1018 check_rem::<u16>(®istry, 10, 5, 0);
1019 check_rem::<u32>(®istry, 10, 5, 0);
1020 check_rem::<u64>(®istry, 10, 5, 0);
1021 check_rem::<u128>(®istry, 10, 5, 0);
1022 check_rem::<usize>(®istry, 10, 5, 0);
1023 check_rem::<i8>(®istry, 10, 5, 0);
1024 check_rem::<i16>(®istry, 10, 5, 0);
1025 check_rem::<i32>(®istry, 10, 5, 0);
1026 check_rem::<i64>(®istry, 10, 5, 0);
1027 check_rem::<i128>(®istry, 10, 5, 0);
1028 check_rem::<isize>(®istry, 10, 5, 0);
1029 check_rem::<f32>(®istry, 10., 5., 0.);
1030 check_rem::<f64>(®istry, 10., 5., 0.);
1031 }
1032}