bevy_reflect/func/args/from_arg.rs
1use crate::func::args::{Arg, ArgError};
2use crate::{Reflect, TypePath};
3
4/// A trait for types that can be created from an [`Arg`].
5///
6/// This trait exists so that types can be automatically converted into an [`Arg`]
7/// so they can be put into an [`ArgList`] and passed to a [`DynamicFunction`] or
8/// [`DynamicFunctionMut`].
9///
10/// This trait is used instead of a blanket [`From`] implementation due to coherence issues:
11/// we can't implement `From<T>` for both `T` and `&T`/`&mut T`.
12///
13/// This trait is automatically implemented for non-reference types when using the `Reflect`
14/// [derive macro]. Blanket impls cover `&T` and `&mut T`.
15///
16/// [`ArgList`]: crate::func::args::ArgList
17/// [`DynamicFunction`]: crate::func::DynamicFunction
18/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
19/// [derive macro]: derive@crate::Reflect
20pub trait FromArg {
21 /// The type to convert into.
22 ///
23 /// This should almost always be the same as `Self`, but with the lifetime `'a`.
24 ///
25 /// The reason we use a separate associated type is to allow for the lifetime
26 /// to be tied to the argument, rather than the type itself.
27 type This<'a>;
28
29 /// Creates an item from an argument.
30 ///
31 /// The argument must be of the expected type and ownership.
32 fn from_arg(arg: Arg<'_>) -> Result<Self::This<'_>, ArgError>;
33}
34
35// Blanket impl.
36impl<T: Reflect + TypePath> FromArg for &'static T {
37 type This<'a> = &'a T;
38 fn from_arg(arg: Arg<'_>) -> Result<Self::This<'_>, ArgError> {
39 arg.take_ref()
40 }
41}
42
43// Blanket impl.
44impl<T: Reflect + TypePath> FromArg for &'static mut T {
45 type This<'a> = &'a mut T;
46 fn from_arg(arg: Arg<'_>) -> Result<Self::This<'_>, ArgError> {
47 arg.take_mut()
48 }
49}
50
51/// Implements the [`FromArg`] trait for the given type.
52///
53/// This will implement it for `$ty`, `&$ty`, and `&mut $ty`.
54///
55/// See [`impl_function_traits`] for details on syntax.
56///
57/// [`impl_function_traits`]: crate::func::macros::impl_function_traits
58macro_rules! impl_from_arg {
59 (
60 $ty: ty
61 $(;
62 < $($T: ident $(: $T1: tt $(+ $T2: tt)*)?),* >
63 )?
64 $(
65 [ $(const $N: ident : $size: ident),* ]
66 )?
67 $(
68 where $($U: ty $(: $U1: tt $(+ $U2: tt)*)?),*
69 )?
70 ) => {
71 impl <
72 $($($T $(: $T1 $(+ $T2)*)?),*)?
73 $(, $(const $N : $size),*)?
74 > $crate::func::args::FromArg for $ty
75 $(
76 where $($U $(: $U1 $(+ $U2)*)?),*
77 )?
78 {
79 type This<'from_arg> = $ty;
80 fn from_arg(arg: $crate::func::args::Arg<'_>) ->
81 Result<Self::This<'_>, $crate::func::args::ArgError>
82 {
83 arg.take_owned()
84 }
85 }
86 };
87}
88
89pub(crate) use impl_from_arg;