1mod dynamic_enum;
5mod enum_trait;
6mod helpers;
7mod variants;
8
9pub use dynamic_enum::*;
10pub use enum_trait::*;
11pub use helpers::*;
12pub use variants::*;
13
14#[cfg(test)]
15mod tests {
16 use crate::{enums::*, structs::*, tuple::*, *};
17 use alloc::boxed::Box;
18
19 #[derive(Reflect, Debug, PartialEq)]
20 enum MyEnum {
21 A,
22 B(usize, i32),
23 C { foo: f32, bar: bool },
24 }
25
26 #[test]
27 fn should_get_enum_type_info() {
28 let info = MyEnum::type_info();
29 if let TypeInfo::Enum(info) = info {
30 assert!(info.is::<MyEnum>(), "expected type to be `MyEnum`");
31 assert_eq!(MyEnum::type_path(), info.type_path());
32 assert_eq!(MyEnum::type_path(), info.type_path_table().path());
33 assert_eq!(MyEnum::type_ident(), info.type_path_table().ident());
34 assert_eq!(MyEnum::module_path(), info.type_path_table().module_path());
35 assert_eq!(MyEnum::crate_name(), info.type_path_table().crate_name());
36 assert_eq!(
37 MyEnum::short_type_path(),
38 info.type_path_table().short_path()
39 );
40
41 assert_eq!("A", info.variant_at(0).unwrap().name());
43 assert_eq!("A", info.variant("A").unwrap().name());
44 if let VariantInfo::Unit(variant) = info.variant("A").unwrap() {
45 assert_eq!("A", variant.name());
46 } else {
47 panic!("Expected `VariantInfo::Unit`");
48 }
49
50 assert_eq!("B", info.variant_at(1).unwrap().name());
52 assert_eq!("B", info.variant("B").unwrap().name());
53 if let VariantInfo::Tuple(variant) = info.variant("B").unwrap() {
54 assert!(variant.field_at(0).unwrap().is::<usize>());
55 assert!(variant.field_at(1).unwrap().is::<i32>());
56 assert!(variant
57 .field_at(0)
58 .unwrap()
59 .type_info()
60 .unwrap()
61 .is::<usize>());
62 assert!(variant
63 .field_at(1)
64 .unwrap()
65 .type_info()
66 .unwrap()
67 .is::<i32>());
68 } else {
69 panic!("Expected `VariantInfo::Tuple`");
70 }
71
72 assert_eq!("C", info.variant_at(2).unwrap().name());
74 assert_eq!("C", info.variant("C").unwrap().name());
75 if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
76 assert!(variant.field_at(0).unwrap().is::<f32>());
77 assert!(variant.field("foo").unwrap().is::<f32>());
78 assert!(variant
79 .field("foo")
80 .unwrap()
81 .type_info()
82 .unwrap()
83 .is::<f32>());
84 } else {
85 panic!("Expected `VariantInfo::Struct`");
86 }
87 } else {
88 panic!("Expected `TypeInfo::Enum`");
89 }
90 }
91
92 #[test]
93 fn dynamic_enum_should_set_variant_fields() {
94 let mut value = MyEnum::A;
96 let dyn_enum = DynamicEnum::from(MyEnum::A);
97 value.apply(&dyn_enum);
98 assert_eq!(MyEnum::A, value);
99
100 let mut value = MyEnum::B(0, 0);
102 let dyn_enum = DynamicEnum::from(MyEnum::B(123, 321));
103 value.apply(&dyn_enum);
104 assert_eq!(MyEnum::B(123, 321), value);
105
106 let mut value = MyEnum::C {
108 foo: 0.0,
109 bar: false,
110 };
111 let dyn_enum = DynamicEnum::from(MyEnum::C {
112 foo: 1.23,
113 bar: true,
114 });
115 value.apply(&dyn_enum);
116 assert_eq!(
117 MyEnum::C {
118 foo: 1.23,
119 bar: true,
120 },
121 value
122 );
123 }
124
125 #[test]
126 fn partial_dynamic_enum_should_set_variant_fields() {
127 let mut value = MyEnum::B(0, 0);
129
130 let mut data = DynamicTuple::default();
131 data.insert(123usize);
132
133 let mut dyn_enum = DynamicEnum::default();
134 dyn_enum.set_variant("B", data);
135 value.apply(&dyn_enum);
136 assert_eq!(MyEnum::B(123, 0), value);
137
138 let mut value = MyEnum::C {
140 foo: 1.23,
141 bar: false,
142 };
143
144 let mut data = DynamicStruct::default();
145 data.insert("bar", true);
146
147 let mut dyn_enum = DynamicEnum::default();
148 dyn_enum.set_variant("C", data);
149 value.apply(&dyn_enum);
150 assert_eq!(
151 MyEnum::C {
152 foo: 1.23,
153 bar: true,
154 },
155 value
156 );
157 }
158
159 #[test]
160 fn dynamic_enum_should_apply_dynamic_enum() {
161 let mut a = DynamicEnum::from(MyEnum::B(123, 321));
162 let b = DynamicEnum::from(MyEnum::B(123, 321));
163
164 assert!(
166 a.reflect_partial_eq(&b).unwrap_or_default(),
167 "dynamic enums should be equal"
168 );
169
170 a.set_variant("A", ());
171 assert!(
172 !a.reflect_partial_eq(&b).unwrap_or_default(),
173 "dynamic enums should not be equal"
174 );
175
176 a.apply(&b);
177 assert!(a.reflect_partial_eq(&b).unwrap_or_default());
178 }
179
180 #[test]
181 fn dynamic_enum_should_change_variant() {
182 let mut value = MyEnum::A;
183
184 let mut dyn_enum = DynamicEnum::from(MyEnum::B(123, 321));
186 value.apply(&dyn_enum);
187 assert_eq!(MyEnum::B(123, 321), value);
188
189 let mut data = DynamicStruct::default();
191 data.insert("foo", 1.23_f32);
192 data.insert("bar", true);
193 dyn_enum.set_variant("C", data);
194 value.apply(&dyn_enum);
195 assert_eq!(
196 MyEnum::C {
197 foo: 1.23,
198 bar: true
199 },
200 value
201 );
202
203 let mut data = DynamicTuple::default();
205 data.insert(123_usize);
206 data.insert(321_i32);
207 dyn_enum.set_variant("B", data);
208 value.apply(&dyn_enum);
209 assert_eq!(MyEnum::B(123, 321), value);
210
211 dyn_enum.set_variant("A", ());
213 value.apply(&dyn_enum);
214 assert_eq!(MyEnum::A, value);
215 }
216
217 #[test]
218 fn dynamic_enum_should_return_is_dynamic() {
219 let dyn_enum = DynamicEnum::from(MyEnum::B(123, 321));
220 assert!(dyn_enum.is_dynamic());
221 }
222
223 #[test]
224 fn enum_should_iterate_fields() {
225 let value: &dyn Enum = &MyEnum::A;
227 assert_eq!(0, value.field_len());
228 let mut iter = value.iter_fields();
229 assert!(iter.next().is_none());
230
231 let value: &dyn Enum = &MyEnum::B(123, 321);
233 assert_eq!(2, value.field_len());
234 let mut iter = value.iter_fields();
235 assert!(iter
236 .next()
237 .and_then(|field| field.value().reflect_partial_eq(&123_usize))
238 .unwrap_or_default());
239 assert!(iter
240 .next()
241 .and_then(|field| field.value().reflect_partial_eq(&321_i32))
242 .unwrap_or_default());
243
244 let value: &dyn Enum = &MyEnum::C {
246 foo: 1.23,
247 bar: true,
248 };
249 assert_eq!(2, value.field_len());
250 let mut iter = value.iter_fields();
251 assert!(iter
252 .next()
253 .and_then(|field| field
254 .value()
255 .reflect_partial_eq(&1.23_f32)
256 .and(field.name().map(|name| name == "foo")))
257 .unwrap_or_default());
258 assert!(iter
259 .next()
260 .and_then(|field| field
261 .value()
262 .reflect_partial_eq(&true)
263 .and(field.name().map(|name| name == "bar")))
264 .unwrap_or_default());
265 }
266
267 #[test]
268 fn enum_should_return_correct_variant_type() {
269 let value = MyEnum::A;
271 assert_eq!(VariantType::Unit, value.variant_type());
272
273 let value = MyEnum::B(0, 0);
275 assert_eq!(VariantType::Tuple, value.variant_type());
276
277 let value = MyEnum::C {
279 foo: 1.23,
280 bar: true,
281 };
282 assert_eq!(VariantType::Struct, value.variant_type());
283 }
284
285 #[test]
286 fn enum_should_return_correct_variant_path() {
287 let value = MyEnum::A;
289 assert_eq!(
290 "bevy_reflect::enums::tests::MyEnum::A",
291 value.variant_path()
292 );
293
294 let value = MyEnum::B(0, 0);
296 assert_eq!(
297 "bevy_reflect::enums::tests::MyEnum::B",
298 value.variant_path()
299 );
300
301 let value = MyEnum::C {
303 foo: 1.23,
304 bar: true,
305 };
306 assert_eq!(
307 "bevy_reflect::enums::tests::MyEnum::C",
308 value.variant_path()
309 );
310 }
311
312 #[test]
313 #[should_panic(
314 expected = "called `Result::unwrap()` on an `Err` value: MismatchedKinds { from_kind: Tuple, to_kind: Enum }"
315 )]
316 fn applying_non_enum_should_panic() {
317 let mut value = MyEnum::B(0, 0);
318 let mut dyn_tuple = DynamicTuple::default();
319 dyn_tuple.insert((123_usize, 321_i32));
320 value.apply(&dyn_tuple);
321 }
322
323 #[test]
324 fn enum_try_apply_should_detect_type_mismatch() {
325 #[derive(Reflect, Debug, PartialEq)]
326 enum MyEnumAnalogue {
327 A(u32),
328 B(usize, usize),
329 C { foo: f32, bar: u8 },
330 }
331
332 let mut target = MyEnumAnalogue::A(0);
333
334 let result = target.try_apply(&MyEnum::B(0, 1));
336 assert!(
337 matches!(result, Err(ApplyError::MismatchedTypes { .. })),
338 "`result` was {result:?}"
339 );
340
341 target = MyEnumAnalogue::C { foo: 0.0, bar: 1 };
343 let result = target.try_apply(&MyEnum::C {
344 foo: 1.0,
345 bar: true,
346 });
347 assert!(
348 matches!(result, Err(ApplyError::MismatchedTypes { .. })),
349 "`result` was {result:?}"
350 );
351 assert_eq!(target, MyEnumAnalogue::C { foo: 1.0, bar: 1 });
353 }
354
355 #[test]
356 fn should_skip_ignored_fields() {
357 #[derive(Reflect, Debug, PartialEq)]
358 enum TestEnum {
359 A,
360 B,
361 C {
362 #[reflect(ignore)]
363 foo: f32,
364 bar: bool,
365 },
366 }
367
368 if let TypeInfo::Enum(info) = TestEnum::type_info() {
369 assert_eq!(3, info.variant_len());
370 if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
371 assert_eq!(
372 1,
373 variant.field_len(),
374 "expected one of the fields to be ignored"
375 );
376 assert!(variant.field_at(0).unwrap().is::<bool>());
377 } else {
378 panic!("expected `VariantInfo::Struct`");
379 }
380 } else {
381 panic!("expected `TypeInfo::Enum`");
382 }
383 }
384
385 #[test]
386 fn enum_should_allow_generics() {
387 #[derive(Reflect, Debug, PartialEq)]
388 enum TestEnum<T: FromReflect> {
389 A,
390 B(T),
391 C { value: T },
392 }
393
394 if let TypeInfo::Enum(info) = TestEnum::<f32>::type_info() {
395 if let VariantInfo::Tuple(variant) = info.variant("B").unwrap() {
396 assert!(variant.field_at(0).unwrap().is::<f32>());
397 } else {
398 panic!("expected `VariantInfo::Struct`");
399 }
400 if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
401 assert!(variant.field("value").unwrap().is::<f32>());
402 } else {
403 panic!("expected `VariantInfo::Struct`");
404 }
405 } else {
406 panic!("expected `TypeInfo::Enum`");
407 }
408
409 let mut value = TestEnum::<f32>::A;
410
411 let mut data = DynamicTuple::default();
413 data.insert(1.23_f32);
414 let dyn_enum = DynamicEnum::new("B", data);
415 value.apply(&dyn_enum);
416 assert_eq!(TestEnum::B(1.23), value);
417
418 let mut data = DynamicStruct::default();
420 data.insert("value", 1.23_f32);
421 let dyn_enum = DynamicEnum::new("C", data);
422 value.apply(&dyn_enum);
423 assert_eq!(TestEnum::C { value: 1.23 }, value);
424 }
425
426 #[test]
427 fn enum_should_allow_struct_fields() {
428 #[derive(Reflect, Debug, PartialEq)]
429 enum TestEnum {
430 A,
431 B(TestStruct),
432 C { value: TestStruct },
433 }
434
435 #[derive(Reflect, Debug, PartialEq)]
436 struct TestStruct(usize);
437
438 let mut value = TestEnum::A;
439
440 let mut data = DynamicTuple::default();
442 data.insert(TestStruct(123));
443 let dyn_enum = DynamicEnum::new("B", data);
444 value.apply(&dyn_enum);
445 assert_eq!(TestEnum::B(TestStruct(123)), value);
446
447 let mut data = DynamicStruct::default();
449 data.insert("value", TestStruct(123));
450 let dyn_enum = DynamicEnum::new("C", data);
451 value.apply(&dyn_enum);
452 assert_eq!(
453 TestEnum::C {
454 value: TestStruct(123)
455 },
456 value
457 );
458 }
459
460 #[test]
461 fn enum_should_allow_nesting_enums() {
462 #[derive(Reflect, Debug, PartialEq)]
463 enum TestEnum {
464 A,
465 B(OtherEnum),
466 C { value: OtherEnum },
467 }
468
469 #[derive(Reflect, Debug, PartialEq)]
470 enum OtherEnum {
471 A,
472 B(usize),
473 C { value: f32 },
474 }
475
476 let mut value = TestEnum::A;
477
478 let mut data = DynamicTuple::default();
480 data.insert(OtherEnum::B(123));
481 let dyn_enum = DynamicEnum::new("B", data);
482 value.apply(&dyn_enum);
483 assert_eq!(TestEnum::B(OtherEnum::B(123)), value);
484
485 let mut data = DynamicStruct::default();
487 data.insert("value", OtherEnum::C { value: 1.23 });
488 let dyn_enum = DynamicEnum::new("C", data);
489 value.apply(&dyn_enum);
490 assert_eq!(
491 TestEnum::C {
492 value: OtherEnum::C { value: 1.23 }
493 },
494 value
495 );
496 }
497
498 #[test]
499 fn enum_should_apply() {
500 let mut value: Box<dyn Reflect> = Box::new(MyEnum::A);
501
502 value.apply(&MyEnum::A);
504 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
505
506 value.apply(&MyEnum::B(123, 321));
508 assert!(value
509 .reflect_partial_eq(&MyEnum::B(123, 321))
510 .unwrap_or_default());
511
512 value.apply(&MyEnum::B(321, 123));
514 assert!(value
515 .reflect_partial_eq(&MyEnum::B(321, 123))
516 .unwrap_or_default());
517
518 value.apply(&MyEnum::C {
520 foo: 1.23,
521 bar: true,
522 });
523 assert!(value
524 .reflect_partial_eq(&MyEnum::C {
525 foo: 1.23,
526 bar: true
527 })
528 .unwrap_or_default());
529
530 value.apply(&MyEnum::C {
532 foo: 3.21,
533 bar: false,
534 });
535 assert!(value
536 .reflect_partial_eq(&MyEnum::C {
537 foo: 3.21,
538 bar: false
539 })
540 .unwrap_or_default());
541
542 value.apply(&MyEnum::B(123, 321));
544 assert!(value
545 .reflect_partial_eq(&MyEnum::B(123, 321))
546 .unwrap_or_default());
547
548 value.apply(&MyEnum::A);
550 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
551 }
552
553 #[test]
554 fn enum_should_set() {
555 let mut value: Box<dyn Reflect> = Box::new(MyEnum::A);
556
557 value.set(Box::new(MyEnum::A)).unwrap();
559 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
560
561 value.set(Box::new(MyEnum::B(123, 321))).unwrap();
563 assert!(value
564 .reflect_partial_eq(&MyEnum::B(123, 321))
565 .unwrap_or_default());
566
567 value.set(Box::new(MyEnum::B(321, 123))).unwrap();
569 assert!(value
570 .reflect_partial_eq(&MyEnum::B(321, 123))
571 .unwrap_or_default());
572
573 value
575 .set(Box::new(MyEnum::C {
576 foo: 1.23,
577 bar: true,
578 }))
579 .unwrap();
580 assert!(value
581 .reflect_partial_eq(&MyEnum::C {
582 foo: 1.23,
583 bar: true
584 })
585 .unwrap_or_default());
586
587 value
589 .set(Box::new(MyEnum::C {
590 foo: 3.21,
591 bar: false,
592 }))
593 .unwrap();
594 assert!(value
595 .reflect_partial_eq(&MyEnum::C {
596 foo: 3.21,
597 bar: false
598 })
599 .unwrap_or_default());
600
601 value.set(Box::new(MyEnum::B(123, 321))).unwrap();
603 assert!(value
604 .reflect_partial_eq(&MyEnum::B(123, 321))
605 .unwrap_or_default());
606
607 value.set(Box::new(MyEnum::A)).unwrap();
609 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
610 }
611
612 #[test]
613 fn enum_should_partial_eq() {
614 #[derive(Reflect)]
615 enum TestEnum {
616 A,
617 A1,
618 B(usize),
619 B1(usize),
620 B2(usize, usize),
621 C { value: i32 },
622 C1 { value: i32 },
623 C2 { value: f32 },
624 }
625
626 let a: &dyn PartialReflect = &TestEnum::A;
627 let b: &dyn PartialReflect = &TestEnum::A;
628 assert!(
629 a.reflect_partial_eq(b).unwrap_or_default(),
630 "expected TestEnum::A == TestEnum::A"
631 );
632
633 let a: &dyn PartialReflect = &TestEnum::A;
634 let b: &dyn PartialReflect = &TestEnum::A1;
635 assert!(
636 !a.reflect_partial_eq(b).unwrap_or_default(),
637 "expected TestEnum::A != TestEnum::A1"
638 );
639
640 let a: &dyn PartialReflect = &TestEnum::B(123);
641 let b: &dyn PartialReflect = &TestEnum::B(123);
642 assert!(
643 a.reflect_partial_eq(b).unwrap_or_default(),
644 "expected TestEnum::B(123) == TestEnum::B(123)"
645 );
646
647 let a: &dyn PartialReflect = &TestEnum::B(123);
648 let b: &dyn PartialReflect = &TestEnum::B(321);
649 assert!(
650 !a.reflect_partial_eq(b).unwrap_or_default(),
651 "expected TestEnum::B(123) != TestEnum::B(321)"
652 );
653
654 let a: &dyn PartialReflect = &TestEnum::B(123);
655 let b: &dyn PartialReflect = &TestEnum::B1(123);
656 assert!(
657 !a.reflect_partial_eq(b).unwrap_or_default(),
658 "expected TestEnum::B(123) != TestEnum::B1(123)"
659 );
660
661 let a: &dyn PartialReflect = &TestEnum::B(123);
662 let b: &dyn PartialReflect = &TestEnum::B2(123, 123);
663 assert!(
664 !a.reflect_partial_eq(b).unwrap_or_default(),
665 "expected TestEnum::B(123) != TestEnum::B2(123, 123)"
666 );
667
668 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
669 let b: &dyn PartialReflect = &TestEnum::C { value: 123 };
670 assert!(
671 a.reflect_partial_eq(b).unwrap_or_default(),
672 "expected TestEnum::C{{value: 123}} == TestEnum::C{{value: 123}}"
673 );
674
675 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
676 let b: &dyn PartialReflect = &TestEnum::C { value: 321 };
677 assert!(
678 !a.reflect_partial_eq(b).unwrap_or_default(),
679 "expected TestEnum::C{{value: 123}} != TestEnum::C{{value: 321}}"
680 );
681
682 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
683 let b: &dyn PartialReflect = &TestEnum::C1 { value: 123 };
684 assert!(
685 !a.reflect_partial_eq(b).unwrap_or_default(),
686 "expected TestEnum::C{{value: 123}} != TestEnum::C1{{value: 123}}"
687 );
688
689 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
690 let b: &dyn PartialReflect = &TestEnum::C2 { value: 1.23 };
691 assert!(
692 !a.reflect_partial_eq(b).unwrap_or_default(),
693 "expected TestEnum::C{{value: 123}} != TestEnum::C2{{value: 1.23}}"
694 );
695
696 #[derive(Reflect)]
697 enum TestEnum2 {
698 A,
699 A1,
700 B(usize, usize),
701 C { value: i32, value2: f32 },
702 }
703 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
704 let a2: &dyn PartialReflect = &TestEnum2::C {
705 value: 123,
706 value2: 1.23,
707 };
708 assert!(
709 !a.reflect_partial_eq(a2).unwrap_or_default(),
710 "expected TestEnum::C{{value: 123}} != TestEnum2::C{{value: 123, value2: 1.23}}"
711 );
712 let b: &dyn PartialReflect = &TestEnum::B(123);
713 let b2 = &TestEnum2::B(123, 321);
714 assert!(
715 !b.reflect_partial_eq(b2).unwrap_or_default(),
716 "expected TestEnum::C{{value: 123}} != TestEnum2::B(123, 321)"
717 );
718 }
719}