mirror_mirror/foreign_impls/
via_scalar.rs

1use core::num::NonZeroI128;
2use core::num::NonZeroI16;
3use core::num::NonZeroI32;
4use core::num::NonZeroI64;
5use core::num::NonZeroI8;
6use core::num::NonZeroU128;
7use core::num::NonZeroU16;
8use core::num::NonZeroU32;
9use core::num::NonZeroU64;
10use core::num::NonZeroU8;
11use core::num::NonZeroUsize;
12use core::time::Duration;
13
14macro_rules! impl_reflect_via_scalar {
15    ($ty:ty, $via_ty:ty, $get_fn:expr, $new_fn:expr $(,)?) => {
16        const _: () = {
17            use $crate::__private::*;
18
19            impl DescribeType for $ty {
20                fn build(graph: &mut TypeGraph) -> NodeId {
21                    graph.get_or_build_node_with::<Self, _>(|graph| {
22                        OpaqueNode::new::<Self>(Default::default(), graph)
23                    })
24                }
25            }
26
27            impl Reflect for $ty {
28                trivial_reflect_methods!();
29
30                #[allow(clippy::redundant_closure_call)]
31                fn reflect_owned(self: Box<Self>) -> ReflectOwned {
32                    ReflectOwned::Scalar(ScalarOwned::from($get_fn(&*self)))
33                }
34
35                #[allow(clippy::redundant_closure_call)]
36                fn reflect_ref(&self) -> ReflectRef<'_> {
37                    ReflectRef::Scalar(ScalarRef::from($get_fn(self)))
38                }
39
40                fn reflect_mut(&mut self) -> ReflectMut<'_> {
41                    ReflectMut::Opaque(self)
42                }
43
44                fn patch(&mut self, value: &dyn Reflect) {
45                    if let Some(n) = Self::from_reflect(value) {
46                        *self = n;
47                    }
48                }
49
50                #[allow(clippy::redundant_closure_call)]
51                fn to_value(&self) -> Value {
52                    $get_fn(self).to_value()
53                }
54
55                fn clone_reflect(&self) -> Box<dyn Reflect> {
56                    Box::new(*self)
57                }
58
59                fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60                    if f.alternate() {
61                        write!(f, "{:#?}", self)
62                    } else {
63                        write!(f, "{:?}", self)
64                    }
65                }
66            }
67
68            impl FromReflect for $ty {
69                fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
70                    if let Some(n) = reflect.downcast_ref::<Self>() {
71                        Some(*n)
72                    } else {
73                        <$via_ty>::from_reflect(reflect)
74                            .and_then(|value| $new_fn(value).into_option())
75                    }
76                }
77            }
78
79            impl From<$ty> for Value {
80                fn from(n: $ty) -> Self {
81                    n.to_value()
82                }
83            }
84        };
85    };
86}
87
88impl_reflect_via_scalar! { NonZeroUsize, usize, |n: &NonZeroUsize| n.get(), Self::new }
89impl_reflect_via_scalar! { NonZeroU8,    u8,    |n: &NonZeroU8| n.get(),    Self::new }
90impl_reflect_via_scalar! { NonZeroU16,   u16,   |n: &NonZeroU16| n.get(),   Self::new }
91impl_reflect_via_scalar! { NonZeroU32,   u32,   |n: &NonZeroU32| n.get(),   Self::new }
92impl_reflect_via_scalar! { NonZeroU64,   u64,   |n: &NonZeroU64| n.get(),   Self::new }
93impl_reflect_via_scalar! { NonZeroU128,  u128,  |n: &NonZeroU128| n.get(),  Self::new }
94impl_reflect_via_scalar! { NonZeroI8,    i8,    |n: &NonZeroI8| n.get(),    Self::new }
95impl_reflect_via_scalar! { NonZeroI16,   i16,   |n: &NonZeroI16| n.get(),   Self::new }
96impl_reflect_via_scalar! { NonZeroI32,   i32,   |n: &NonZeroI32| n.get(),   Self::new }
97impl_reflect_via_scalar! { NonZeroI64,   i64,   |n: &NonZeroI64| n.get(),   Self::new }
98impl_reflect_via_scalar! { NonZeroI128,  i128,  |n: &NonZeroI128| n.get(),  Self::new }
99
100impl_reflect_via_scalar! { Duration, f32, |d: &Duration| d.as_secs_f32(), Self::from_secs_f32 }
101
102trait IntoOption<T> {
103    fn into_option(self) -> Option<T>;
104}
105
106impl<T> IntoOption<T> for Option<T> {
107    fn into_option(self) -> Option<T> {
108        self
109    }
110}
111
112impl<T> IntoOption<T> for T {
113    fn into_option(self) -> Option<T> {
114        Some(self)
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121    use crate::DescribeType;
122
123    #[test]
124    fn keeps_type_name() {
125        assert_eq!(
126            <NonZeroI8 as DescribeType>::type_descriptor()
127                .get_type()
128                .type_name(),
129            "core::num::nonzero::NonZero<i8>"
130        );
131
132        assert_eq!(
133            <Duration as DescribeType>::type_descriptor()
134                .get_type()
135                .type_name(),
136            "core::time::Duration"
137        );
138    }
139}