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::try_from(MyEnum::A).unwrap();
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::try_from(MyEnum::B(123, 321)).unwrap();
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::try_from(MyEnum::C {
112 foo: 1.23,
113 bar: true,
114 })
115 .unwrap();
116 value.apply(&dyn_enum);
117 assert_eq!(
118 MyEnum::C {
119 foo: 1.23,
120 bar: true,
121 },
122 value
123 );
124 }
125
126 #[test]
127 fn partial_dynamic_enum_should_set_variant_fields() {
128 let mut value = MyEnum::B(0, 0);
130
131 let mut data = DynamicTuple::default();
132 data.insert(123usize);
133
134 let mut dyn_enum = DynamicEnum::default();
135 dyn_enum.set_variant("B", data);
136 value.apply(&dyn_enum);
137 assert_eq!(MyEnum::B(123, 0), value);
138
139 let mut value = MyEnum::C {
141 foo: 1.23,
142 bar: false,
143 };
144
145 let mut data = DynamicStruct::default();
146 data.insert("bar", true);
147
148 let mut dyn_enum = DynamicEnum::default();
149 dyn_enum.set_variant("C", data);
150 value.apply(&dyn_enum);
151 assert_eq!(
152 MyEnum::C {
153 foo: 1.23,
154 bar: true,
155 },
156 value
157 );
158 }
159
160 #[test]
161 fn dynamic_enum_should_apply_dynamic_enum() {
162 let mut a = DynamicEnum::try_from(MyEnum::B(123, 321)).unwrap();
163 let b = DynamicEnum::try_from(MyEnum::B(123, 321)).unwrap();
164
165 assert!(
167 a.reflect_partial_eq(&b).unwrap_or_default(),
168 "dynamic enums should be equal"
169 );
170
171 a.set_variant("A", ());
172 assert!(
173 !a.reflect_partial_eq(&b).unwrap_or_default(),
174 "dynamic enums should not be equal"
175 );
176
177 a.apply(&b);
178 assert!(a.reflect_partial_eq(&b).unwrap_or_default());
179 }
180
181 #[test]
182 fn dynamic_enum_should_change_variant() {
183 let mut value = MyEnum::A;
184
185 let mut dyn_enum = DynamicEnum::try_from(MyEnum::B(123, 321)).unwrap();
187 value.apply(&dyn_enum);
188 assert_eq!(MyEnum::B(123, 321), value);
189
190 let mut data = DynamicStruct::default();
192 data.insert("foo", 1.23_f32);
193 data.insert("bar", true);
194 dyn_enum.set_variant("C", data);
195 value.apply(&dyn_enum);
196 assert_eq!(
197 MyEnum::C {
198 foo: 1.23,
199 bar: true
200 },
201 value
202 );
203
204 let mut data = DynamicTuple::default();
206 data.insert(123_usize);
207 data.insert(321_i32);
208 dyn_enum.set_variant("B", data);
209 value.apply(&dyn_enum);
210 assert_eq!(MyEnum::B(123, 321), value);
211
212 dyn_enum.set_variant("A", ());
214 value.apply(&dyn_enum);
215 assert_eq!(MyEnum::A, value);
216 }
217
218 #[test]
219 fn dynamic_enum_should_return_is_dynamic() {
220 let dyn_enum = DynamicEnum::try_from(MyEnum::B(123, 321)).unwrap();
221 assert!(dyn_enum.is_dynamic());
222 }
223
224 #[test]
225 fn enum_should_iterate_fields() {
226 let value: &dyn Enum = &MyEnum::A;
228 assert_eq!(0, value.field_len());
229 let mut iter = value.iter_fields();
230 assert!(iter.next().is_none());
231
232 let value: &dyn Enum = &MyEnum::B(123, 321);
234 assert_eq!(2, value.field_len());
235 let mut iter = value.iter_fields();
236 assert!(iter
237 .next()
238 .and_then(|field| field.value().reflect_partial_eq(&123_usize))
239 .unwrap_or_default());
240 assert!(iter
241 .next()
242 .and_then(|field| field.value().reflect_partial_eq(&321_i32))
243 .unwrap_or_default());
244
245 let value: &dyn Enum = &MyEnum::C {
247 foo: 1.23,
248 bar: true,
249 };
250 assert_eq!(2, value.field_len());
251 let mut iter = value.iter_fields();
252 assert!(iter
253 .next()
254 .and_then(|field| field
255 .value()
256 .reflect_partial_eq(&1.23_f32)
257 .and(field.name().map(|name| name == "foo")))
258 .unwrap_or_default());
259 assert!(iter
260 .next()
261 .and_then(|field| field
262 .value()
263 .reflect_partial_eq(&true)
264 .and(field.name().map(|name| name == "bar")))
265 .unwrap_or_default());
266 }
267
268 #[test]
269 fn enum_should_return_correct_variant_type() {
270 let value = MyEnum::A;
272 assert_eq!(VariantType::Unit, value.variant_type());
273
274 let value = MyEnum::B(0, 0);
276 assert_eq!(VariantType::Tuple, value.variant_type());
277
278 let value = MyEnum::C {
280 foo: 1.23,
281 bar: true,
282 };
283 assert_eq!(VariantType::Struct, value.variant_type());
284 }
285
286 #[test]
287 fn enum_should_return_correct_variant_path() {
288 let value = MyEnum::A;
290 assert_eq!(
291 "bevy_reflect::enums::tests::MyEnum::A",
292 value.variant_path()
293 );
294
295 let value = MyEnum::B(0, 0);
297 assert_eq!(
298 "bevy_reflect::enums::tests::MyEnum::B",
299 value.variant_path()
300 );
301
302 let value = MyEnum::C {
304 foo: 1.23,
305 bar: true,
306 };
307 assert_eq!(
308 "bevy_reflect::enums::tests::MyEnum::C",
309 value.variant_path()
310 );
311 }
312
313 #[test]
314 #[should_panic(
315 expected = "called `Result::unwrap()` on an `Err` value: MismatchedKinds { from_kind: Tuple, to_kind: Enum }"
316 )]
317 fn applying_non_enum_should_panic() {
318 let mut value = MyEnum::B(0, 0);
319 let mut dyn_tuple = DynamicTuple::default();
320 dyn_tuple.insert((123_usize, 321_i32));
321 value.apply(&dyn_tuple);
322 }
323
324 #[test]
325 fn enum_try_apply_should_detect_type_mismatch() {
326 #[derive(Reflect, Debug, PartialEq)]
327 enum MyEnumAnalogue {
328 A(u32),
329 B(usize, usize),
330 C { foo: f32, bar: u8 },
331 }
332
333 let mut target = MyEnumAnalogue::A(0);
334
335 let result = target.try_apply(&MyEnum::B(0, 1));
337 assert!(
338 matches!(result, Err(ApplyError::MismatchedTypes { .. })),
339 "`result` was {result:?}"
340 );
341
342 target = MyEnumAnalogue::C { foo: 0.0, bar: 1 };
344 let result = target.try_apply(&MyEnum::C {
345 foo: 1.0,
346 bar: true,
347 });
348 assert!(
349 matches!(result, Err(ApplyError::MismatchedTypes { .. })),
350 "`result` was {result:?}"
351 );
352 assert_eq!(target, MyEnumAnalogue::C { foo: 1.0, bar: 1 });
354 }
355
356 #[test]
357 fn should_skip_ignored_fields() {
358 #[derive(Reflect, Debug, PartialEq)]
359 enum TestEnum {
360 A,
361 B,
362 C {
363 #[reflect(ignore)]
364 foo: f32,
365 bar: bool,
366 },
367 }
368
369 if let TypeInfo::Enum(info) = TestEnum::type_info() {
370 assert_eq!(3, info.variant_len());
371 if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
372 assert_eq!(
373 1,
374 variant.field_len(),
375 "expected one of the fields to be ignored"
376 );
377 assert!(variant.field_at(0).unwrap().is::<bool>());
378 } else {
379 panic!("expected `VariantInfo::Struct`");
380 }
381 } else {
382 panic!("expected `TypeInfo::Enum`");
383 }
384 }
385
386 #[test]
387 fn enum_should_allow_generics() {
388 #[derive(Reflect, Debug, PartialEq)]
389 enum TestEnum<T: FromReflect> {
390 A,
391 B(T),
392 C { value: T },
393 }
394
395 if let TypeInfo::Enum(info) = TestEnum::<f32>::type_info() {
396 if let VariantInfo::Tuple(variant) = info.variant("B").unwrap() {
397 assert!(variant.field_at(0).unwrap().is::<f32>());
398 } else {
399 panic!("expected `VariantInfo::Struct`");
400 }
401 if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
402 assert!(variant.field("value").unwrap().is::<f32>());
403 } else {
404 panic!("expected `VariantInfo::Struct`");
405 }
406 } else {
407 panic!("expected `TypeInfo::Enum`");
408 }
409
410 let mut value = TestEnum::<f32>::A;
411
412 let mut data = DynamicTuple::default();
414 data.insert(1.23_f32);
415 let dyn_enum = DynamicEnum::new("B", data);
416 value.apply(&dyn_enum);
417 assert_eq!(TestEnum::B(1.23), value);
418
419 let mut data = DynamicStruct::default();
421 data.insert("value", 1.23_f32);
422 let dyn_enum = DynamicEnum::new("C", data);
423 value.apply(&dyn_enum);
424 assert_eq!(TestEnum::C { value: 1.23 }, value);
425 }
426
427 #[test]
428 fn enum_should_allow_struct_fields() {
429 #[derive(Reflect, Debug, PartialEq)]
430 enum TestEnum {
431 A,
432 B(TestStruct),
433 C { value: TestStruct },
434 }
435
436 #[derive(Reflect, Debug, PartialEq)]
437 struct TestStruct(usize);
438
439 let mut value = TestEnum::A;
440
441 let mut data = DynamicTuple::default();
443 data.insert(TestStruct(123));
444 let dyn_enum = DynamicEnum::new("B", data);
445 value.apply(&dyn_enum);
446 assert_eq!(TestEnum::B(TestStruct(123)), value);
447
448 let mut data = DynamicStruct::default();
450 data.insert("value", TestStruct(123));
451 let dyn_enum = DynamicEnum::new("C", data);
452 value.apply(&dyn_enum);
453 assert_eq!(
454 TestEnum::C {
455 value: TestStruct(123)
456 },
457 value
458 );
459 }
460
461 #[test]
462 fn enum_should_allow_nesting_enums() {
463 #[derive(Reflect, Debug, PartialEq)]
464 enum TestEnum {
465 A,
466 B(OtherEnum),
467 C { value: OtherEnum },
468 }
469
470 #[derive(Reflect, Debug, PartialEq)]
471 enum OtherEnum {
472 A,
473 B(usize),
474 C { value: f32 },
475 }
476
477 let mut value = TestEnum::A;
478
479 let mut data = DynamicTuple::default();
481 data.insert(OtherEnum::B(123));
482 let dyn_enum = DynamicEnum::new("B", data);
483 value.apply(&dyn_enum);
484 assert_eq!(TestEnum::B(OtherEnum::B(123)), value);
485
486 let mut data = DynamicStruct::default();
488 data.insert("value", OtherEnum::C { value: 1.23 });
489 let dyn_enum = DynamicEnum::new("C", data);
490 value.apply(&dyn_enum);
491 assert_eq!(
492 TestEnum::C {
493 value: OtherEnum::C { value: 1.23 }
494 },
495 value
496 );
497 }
498
499 #[test]
500 fn enum_should_apply() {
501 let mut value: Box<dyn Reflect> = Box::new(MyEnum::A);
502
503 value.apply(&MyEnum::A);
505 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
506
507 value.apply(&MyEnum::B(123, 321));
509 assert!(value
510 .reflect_partial_eq(&MyEnum::B(123, 321))
511 .unwrap_or_default());
512
513 value.apply(&MyEnum::B(321, 123));
515 assert!(value
516 .reflect_partial_eq(&MyEnum::B(321, 123))
517 .unwrap_or_default());
518
519 value.apply(&MyEnum::C {
521 foo: 1.23,
522 bar: true,
523 });
524 assert!(value
525 .reflect_partial_eq(&MyEnum::C {
526 foo: 1.23,
527 bar: true
528 })
529 .unwrap_or_default());
530
531 value.apply(&MyEnum::C {
533 foo: 3.21,
534 bar: false,
535 });
536 assert!(value
537 .reflect_partial_eq(&MyEnum::C {
538 foo: 3.21,
539 bar: false
540 })
541 .unwrap_or_default());
542
543 value.apply(&MyEnum::B(123, 321));
545 assert!(value
546 .reflect_partial_eq(&MyEnum::B(123, 321))
547 .unwrap_or_default());
548
549 value.apply(&MyEnum::A);
551 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
552 }
553
554 #[test]
555 fn enum_should_set() {
556 let mut value: Box<dyn Reflect> = Box::new(MyEnum::A);
557
558 value.set(Box::new(MyEnum::A)).unwrap();
560 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
561
562 value.set(Box::new(MyEnum::B(123, 321))).unwrap();
564 assert!(value
565 .reflect_partial_eq(&MyEnum::B(123, 321))
566 .unwrap_or_default());
567
568 value.set(Box::new(MyEnum::B(321, 123))).unwrap();
570 assert!(value
571 .reflect_partial_eq(&MyEnum::B(321, 123))
572 .unwrap_or_default());
573
574 value
576 .set(Box::new(MyEnum::C {
577 foo: 1.23,
578 bar: true,
579 }))
580 .unwrap();
581 assert!(value
582 .reflect_partial_eq(&MyEnum::C {
583 foo: 1.23,
584 bar: true
585 })
586 .unwrap_or_default());
587
588 value
590 .set(Box::new(MyEnum::C {
591 foo: 3.21,
592 bar: false,
593 }))
594 .unwrap();
595 assert!(value
596 .reflect_partial_eq(&MyEnum::C {
597 foo: 3.21,
598 bar: false
599 })
600 .unwrap_or_default());
601
602 value.set(Box::new(MyEnum::B(123, 321))).unwrap();
604 assert!(value
605 .reflect_partial_eq(&MyEnum::B(123, 321))
606 .unwrap_or_default());
607
608 value.set(Box::new(MyEnum::A)).unwrap();
610 assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
611 }
612
613 #[test]
614 fn enum_should_partial_eq() {
615 #[derive(Reflect)]
616 enum TestEnum {
617 A,
618 A1,
619 B(usize),
620 B1(usize),
621 B2(usize, usize),
622 C { value: i32 },
623 C1 { value: i32 },
624 C2 { value: f32 },
625 }
626
627 let a: &dyn PartialReflect = &TestEnum::A;
628 let b: &dyn PartialReflect = &TestEnum::A;
629 assert!(
630 a.reflect_partial_eq(b).unwrap_or_default(),
631 "expected TestEnum::A == TestEnum::A"
632 );
633
634 let a: &dyn PartialReflect = &TestEnum::A;
635 let b: &dyn PartialReflect = &TestEnum::A1;
636 assert!(
637 !a.reflect_partial_eq(b).unwrap_or_default(),
638 "expected TestEnum::A != TestEnum::A1"
639 );
640
641 let a: &dyn PartialReflect = &TestEnum::B(123);
642 let b: &dyn PartialReflect = &TestEnum::B(123);
643 assert!(
644 a.reflect_partial_eq(b).unwrap_or_default(),
645 "expected TestEnum::B(123) == TestEnum::B(123)"
646 );
647
648 let a: &dyn PartialReflect = &TestEnum::B(123);
649 let b: &dyn PartialReflect = &TestEnum::B(321);
650 assert!(
651 !a.reflect_partial_eq(b).unwrap_or_default(),
652 "expected TestEnum::B(123) != TestEnum::B(321)"
653 );
654
655 let a: &dyn PartialReflect = &TestEnum::B(123);
656 let b: &dyn PartialReflect = &TestEnum::B1(123);
657 assert!(
658 !a.reflect_partial_eq(b).unwrap_or_default(),
659 "expected TestEnum::B(123) != TestEnum::B1(123)"
660 );
661
662 let a: &dyn PartialReflect = &TestEnum::B(123);
663 let b: &dyn PartialReflect = &TestEnum::B2(123, 123);
664 assert!(
665 !a.reflect_partial_eq(b).unwrap_or_default(),
666 "expected TestEnum::B(123) != TestEnum::B2(123, 123)"
667 );
668
669 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
670 let b: &dyn PartialReflect = &TestEnum::C { value: 123 };
671 assert!(
672 a.reflect_partial_eq(b).unwrap_or_default(),
673 "expected TestEnum::C{{value: 123}} == TestEnum::C{{value: 123}}"
674 );
675
676 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
677 let b: &dyn PartialReflect = &TestEnum::C { value: 321 };
678 assert!(
679 !a.reflect_partial_eq(b).unwrap_or_default(),
680 "expected TestEnum::C{{value: 123}} != TestEnum::C{{value: 321}}"
681 );
682
683 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
684 let b: &dyn PartialReflect = &TestEnum::C1 { value: 123 };
685 assert!(
686 !a.reflect_partial_eq(b).unwrap_or_default(),
687 "expected TestEnum::C{{value: 123}} != TestEnum::C1{{value: 123}}"
688 );
689
690 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
691 let b: &dyn PartialReflect = &TestEnum::C2 { value: 1.23 };
692 assert!(
693 !a.reflect_partial_eq(b).unwrap_or_default(),
694 "expected TestEnum::C{{value: 123}} != TestEnum::C2{{value: 1.23}}"
695 );
696
697 #[derive(Reflect)]
698 enum TestEnum2 {
699 A,
700 A1,
701 B(usize, usize),
702 C { value: i32, value2: f32 },
703 }
704 let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
705 let a2: &dyn PartialReflect = &TestEnum2::C {
706 value: 123,
707 value2: 1.23,
708 };
709 assert!(
710 !a.reflect_partial_eq(a2).unwrap_or_default(),
711 "expected TestEnum::C{{value: 123}} != TestEnum2::C{{value: 123, value2: 1.23}}"
712 );
713 let b: &dyn PartialReflect = &TestEnum::B(123);
714 let b2 = &TestEnum2::B(123, 321);
715 assert!(
716 !b.reflect_partial_eq(b2).unwrap_or_default(),
717 "expected TestEnum::C{{value: 123}} != TestEnum2::B(123, 321)"
718 );
719 }
720}