Skip to main content

bevy_reflect/impls/core/
option.rs

1#![expect(
2    unused_qualifications,
3    reason = "the macro uses `MyEnum::Variant` which is generally unnecessary for `Option`"
4)]
5
6use crate::std_traits::ReflectDefault;
7use bevy_reflect_derive::impl_reflect;
8
9impl_reflect! {
10    #[type_path = "core::option"]
11    #[reflect(Default)]
12    enum Option<T> {
13        None,
14        Some(T),
15    }
16}
17
18#[cfg(test)]
19mod tests {
20    use crate::{
21        enums::{Enum, VariantInfo, VariantType},
22        FromReflect, PartialReflect, TypeInfo, Typed,
23    };
24    use bevy_reflect_derive::Reflect;
25    use static_assertions::assert_impl_all;
26
27    #[test]
28    fn should_partial_eq_option() {
29        let a: &dyn PartialReflect = &Some(123);
30        let b: &dyn PartialReflect = &Some(123);
31        assert_eq!(Some(true), a.reflect_partial_eq(b));
32    }
33
34    #[test]
35    fn option_should_impl_enum() {
36        assert_impl_all!(Option<()>: Enum);
37
38        let mut value = Some(123usize);
39
40        assert!(value
41            .reflect_partial_eq(&Some(123usize))
42            .unwrap_or_default());
43        assert!(!value
44            .reflect_partial_eq(&Some(321usize))
45            .unwrap_or_default());
46
47        assert_eq!("Some", value.variant_name());
48        assert_eq!("core::option::Option<usize>::Some", value.variant_path());
49
50        if value.is_variant(VariantType::Tuple) {
51            if let Some(field) = value
52                .field_at_mut(0)
53                .and_then(|field| field.try_downcast_mut::<usize>())
54            {
55                *field = 321;
56            }
57        } else {
58            panic!("expected `VariantType::Tuple`");
59        }
60
61        assert_eq!(Some(321), value);
62    }
63
64    #[test]
65    fn option_should_from_reflect() {
66        #[derive(Reflect, PartialEq, Debug)]
67        struct Foo(usize);
68
69        let expected = Some(Foo(123));
70        let output = <Option<Foo> as FromReflect>::from_reflect(&expected).unwrap();
71
72        assert_eq!(expected, output);
73    }
74
75    #[test]
76    fn option_should_apply() {
77        #[derive(Reflect, PartialEq, Debug)]
78        struct Foo(usize);
79
80        // === None on None === //
81        let patch = None::<Foo>;
82        let mut value = None::<Foo>;
83        PartialReflect::apply(&mut value, &patch);
84
85        assert_eq!(patch, value, "None apply onto None");
86
87        // === Some on None === //
88        let patch = Some(Foo(123));
89        let mut value = None::<Foo>;
90        PartialReflect::apply(&mut value, &patch);
91
92        assert_eq!(patch, value, "Some apply onto None");
93
94        // === None on Some === //
95        let patch = None::<Foo>;
96        let mut value = Some(Foo(321));
97        PartialReflect::apply(&mut value, &patch);
98
99        assert_eq!(patch, value, "None apply onto Some");
100
101        // === Some on Some === //
102        let patch = Some(Foo(123));
103        let mut value = Some(Foo(321));
104        PartialReflect::apply(&mut value, &patch);
105
106        assert_eq!(patch, value, "Some apply onto Some");
107    }
108
109    #[test]
110    fn option_should_impl_typed() {
111        assert_impl_all!(Option<()>: Typed);
112
113        type MyOption = Option<i32>;
114        let info = MyOption::type_info();
115        if let TypeInfo::Enum(info) = info {
116            assert_eq!(
117                "None",
118                info.variant_at(0).unwrap().name(),
119                "Expected `None` to be variant at index `0`"
120            );
121            assert_eq!(
122                "Some",
123                info.variant_at(1).unwrap().name(),
124                "Expected `Some` to be variant at index `1`"
125            );
126            assert_eq!("Some", info.variant("Some").unwrap().name());
127            if let VariantInfo::Tuple(variant) = info.variant("Some").unwrap() {
128                assert!(
129                    variant.field_at(0).unwrap().is::<i32>(),
130                    "Expected `Some` variant to contain `i32`"
131                );
132                assert!(
133                    variant.field_at(1).is_none(),
134                    "Expected `Some` variant to only contain 1 field"
135                );
136            } else {
137                panic!("Expected `VariantInfo::Tuple`");
138            }
139        } else {
140            panic!("Expected `TypeInfo::Enum`");
141        }
142    }
143}