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;