Skip to main content

bevy_reflect/func/
return_type.rs

1use crate::PartialReflect;
2use alloc::boxed::Box;
3
4/// The return type of a [`DynamicFunction`] or [`DynamicFunctionMut`].
5///
6/// [`DynamicFunction`]: crate::func::DynamicFunction
7/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
8#[derive(Debug)]
9pub enum Return<'a> {
10    /// The function returns an owned value.
11    ///
12    /// This includes functions that return nothing (i.e. they return `()`).
13    Owned(Box<dyn PartialReflect>),
14    /// The function returns a reference to a value.
15    Ref(&'a dyn PartialReflect),
16    /// The function returns a mutable reference to a value.
17    Mut(&'a mut dyn PartialReflect),
18}
19
20impl<'a> Return<'a> {
21    /// Creates an [`Owned`](Self::Owned) unit (`()`) type.
22    pub fn unit() -> Self {
23        Self::Owned(Box::new(()))
24    }
25
26    /// Returns `true` if the return value is an [`Owned`](Self::Owned) unit (`()`) type.
27    pub fn is_unit(&self) -> bool {
28        match self {
29            Return::Owned(val) => val.represents::<()>(),
30            _ => false,
31        }
32    }
33
34    /// Unwraps the return value as an owned value.
35    ///
36    /// # Panics
37    ///
38    /// Panics if the return value is not [`Self::Owned`].
39    pub fn unwrap_owned(self) -> Box<dyn PartialReflect> {
40        match self {
41            Return::Owned(value) => value,
42            _ => panic!("expected owned value"),
43        }
44    }
45
46    /// Unwraps the return value as a reference to a value.
47    ///
48    /// # Panics
49    ///
50    /// Panics if the return value is not [`Self::Ref`].
51    pub fn unwrap_ref(self) -> &'a dyn PartialReflect {
52        match self {
53            Return::Ref(value) => value,
54            _ => panic!("expected reference value"),
55        }
56    }
57
58    /// Unwraps the return value as a mutable reference to a value.
59    ///
60    /// # Panics
61    ///
62    /// Panics if the return value is not [`Self::Mut`].
63    pub fn unwrap_mut(self) -> &'a mut dyn PartialReflect {
64        match self {
65            Return::Mut(value) => value,
66            _ => panic!("expected mutable reference value"),
67        }
68    }
69}
70
71/// A trait for types that can be converted into a [`Return`] value.
72///
73/// This trait exists so that types can be automatically converted into a [`Return`]
74/// by [`ReflectFn`] and [`ReflectFnMut`].
75///
76/// This trait is used instead of a blanket [`Into`] implementation due to coherence issues:
77/// we can't implement `Into<Return>` for both `T` and `&T`/`&mut T`.
78///
79/// This trait is automatically implemented for non-reference types when using the `Reflect`
80/// [derive macro]. Blanket impls cover `&T` and `&mut T`.
81///
82/// [`ReflectFn`]: crate::func::ReflectFn
83/// [`ReflectFnMut`]: crate::func::ReflectFnMut
84/// [derive macro]: derive@crate::Reflect
85pub trait IntoReturn {
86    /// Converts [`Self`] into a [`Return`] value.
87    fn into_return<'a>(self) -> Return<'a>
88    where
89        Self: 'a;
90}
91
92// Blanket impl.
93impl<T: PartialReflect> IntoReturn for &'_ T {
94    fn into_return<'a>(self) -> Return<'a>
95    where
96        Self: 'a,
97    {
98        Return::Ref(self)
99    }
100}
101
102// Blanket impl.
103impl<T: PartialReflect> IntoReturn for &'_ mut T {
104    fn into_return<'a>(self) -> Return<'a>
105    where
106        Self: 'a,
107    {
108        Return::Mut(self)
109    }
110}
111
112impl IntoReturn for () {
113    fn into_return<'a>(self) -> Return<'a> {
114        Return::unit()
115    }
116}
117
118/// Implements the [`IntoReturn`] trait for the given type.
119///
120/// This will implement it for `ty`, `&ty`, and `&mut ty`.
121///
122/// See [`impl_function_traits`] for details on syntax.
123///
124/// [`impl_function_traits`]: crate::func::macros::impl_function_traits
125macro_rules! impl_into_return {
126    (
127        $ty: ty
128        $(;
129            < $($T: ident $(: $T1: tt $(+ $T2: tt)*)?),* >
130        )?
131        $(
132            [ $(const $N: ident : $size: ident),* ]
133        )?
134        $(
135            where $($U: ty $(: $U1: tt $(+ $U2: tt)*)?),*
136        )?
137    ) => {
138        impl <
139            $($($T $(: $T1 $(+ $T2)*)?),*)?
140            $(, $(const $N : $size),*)?
141        > $crate::func::IntoReturn for $ty
142        $(
143            where $($U $(: $U1 $(+ $U2)*)?),*
144        )?
145        {
146            fn into_return<'into_return>(self) -> $crate::func::Return<'into_return>
147                where Self: 'into_return
148            {
149                $crate::func::Return::Owned(bevy_platform::prelude::Box::new(self))
150            }
151        }
152    };
153}
154
155pub(crate) use impl_into_return;