Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/func/args/arg.rs
6600 views
1
use crate::{
2
func::args::{ArgError, FromArg, Ownership},
3
PartialReflect, Reflect, TypePath,
4
};
5
use alloc::{boxed::Box, string::ToString};
6
use core::ops::Deref;
7
8
/// Represents an argument that can be passed to a [`DynamicFunction`] or [`DynamicFunctionMut`].
9
///
10
/// [`DynamicFunction`]: crate::func::DynamicFunction
11
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
12
#[derive(Debug)]
13
pub struct Arg<'a> {
14
index: usize,
15
value: ArgValue<'a>,
16
}
17
18
impl<'a> Arg<'a> {
19
/// Create a new [`Arg`] with the given index and value.
20
pub fn new(index: usize, value: ArgValue<'a>) -> Self {
21
Self { index, value }
22
}
23
24
/// The index of the argument.
25
pub fn index(&self) -> usize {
26
self.index
27
}
28
29
/// Set the index of the argument.
30
pub(crate) fn set_index(&mut self, index: usize) {
31
self.index = index;
32
}
33
34
/// The value of the argument.
35
pub fn value(&self) -> &ArgValue<'a> {
36
&self.value
37
}
38
39
/// Take the value of the argument.
40
pub fn take_value(self) -> ArgValue<'a> {
41
self.value
42
}
43
44
/// Take the value of the argument and attempt to convert it to a concrete value, `T`.
45
///
46
/// This is a convenience method for calling [`FromArg::from_arg`] on the argument.
47
///
48
/// # Example
49
///
50
/// ```
51
/// # use bevy_reflect::func::ArgList;
52
/// let a = 1u32;
53
/// let b = 2u32;
54
/// let mut c = 3u32;
55
/// let mut args = ArgList::new().with_owned(a).with_ref(&b).with_mut(&mut c);
56
///
57
/// let a = args.take::<u32>().unwrap();
58
/// assert_eq!(a, 1);
59
///
60
/// let b = args.take::<&u32>().unwrap();
61
/// assert_eq!(*b, 2);
62
///
63
/// let c = args.take::<&mut u32>().unwrap();
64
/// assert_eq!(*c, 3);
65
/// ```
66
pub fn take<T: FromArg>(self) -> Result<T::This<'a>, ArgError> {
67
T::from_arg(self)
68
}
69
70
/// Returns `Ok(T)` if the argument is [`ArgValue::Owned`].
71
///
72
/// If the argument is not owned, returns an error.
73
///
74
/// It's generally preferred to use [`Self::take`] instead of this method.
75
///
76
/// # Example
77
///
78
/// ```
79
/// # use bevy_reflect::func::ArgList;
80
/// let value = 123u32;
81
/// let mut args = ArgList::new().with_owned(value);
82
/// let value = args.take_owned::<u32>().unwrap();
83
/// assert_eq!(value, 123);
84
/// ```
85
pub fn take_owned<T: Reflect + TypePath>(self) -> Result<T, ArgError> {
86
match self.value {
87
ArgValue::Owned(arg) => arg.try_take().map_err(|arg| ArgError::UnexpectedType {
88
index: self.index,
89
expected: alloc::borrow::Cow::Borrowed(T::type_path()),
90
received: alloc::borrow::Cow::Owned(arg.reflect_type_path().to_string()),
91
}),
92
ArgValue::Ref(_) => Err(ArgError::InvalidOwnership {
93
index: self.index,
94
expected: Ownership::Owned,
95
received: Ownership::Ref,
96
}),
97
ArgValue::Mut(_) => Err(ArgError::InvalidOwnership {
98
index: self.index,
99
expected: Ownership::Owned,
100
received: Ownership::Mut,
101
}),
102
}
103
}
104
105
/// Returns `Ok(&T)` if the argument is [`ArgValue::Ref`].
106
///
107
/// If the argument is not a reference, returns an error.
108
///
109
/// It's generally preferred to use [`Self::take`] instead of this method.
110
///
111
/// # Example
112
///
113
/// ```
114
/// # use bevy_reflect::func::ArgList;
115
/// let value = 123u32;
116
/// let mut args = ArgList::new().with_ref(&value);
117
/// let value = args.take_ref::<u32>().unwrap();
118
/// assert_eq!(*value, 123);
119
/// ```
120
pub fn take_ref<T: Reflect + TypePath>(self) -> Result<&'a T, ArgError> {
121
match self.value {
122
ArgValue::Owned(_) => Err(ArgError::InvalidOwnership {
123
index: self.index,
124
expected: Ownership::Ref,
125
received: Ownership::Owned,
126
}),
127
ArgValue::Ref(arg) => {
128
Ok(arg
129
.try_downcast_ref()
130
.ok_or_else(|| ArgError::UnexpectedType {
131
index: self.index,
132
expected: alloc::borrow::Cow::Borrowed(T::type_path()),
133
received: alloc::borrow::Cow::Owned(arg.reflect_type_path().to_string()),
134
})?)
135
}
136
ArgValue::Mut(_) => Err(ArgError::InvalidOwnership {
137
index: self.index,
138
expected: Ownership::Ref,
139
received: Ownership::Mut,
140
}),
141
}
142
}
143
144
/// Returns `Ok(&mut T)` if the argument is [`ArgValue::Mut`].
145
///
146
/// If the argument is not a mutable reference, returns an error.
147
///
148
/// It's generally preferred to use [`Self::take`] instead of this method.
149
///
150
/// # Example
151
///
152
/// ```
153
/// # use bevy_reflect::func::ArgList;
154
/// let mut value = 123u32;
155
/// let mut args = ArgList::new().with_mut(&mut value);
156
/// let value = args.take_mut::<u32>().unwrap();
157
/// assert_eq!(*value, 123);
158
/// ```
159
pub fn take_mut<T: Reflect + TypePath>(self) -> Result<&'a mut T, ArgError> {
160
match self.value {
161
ArgValue::Owned(_) => Err(ArgError::InvalidOwnership {
162
index: self.index,
163
expected: Ownership::Mut,
164
received: Ownership::Owned,
165
}),
166
ArgValue::Ref(_) => Err(ArgError::InvalidOwnership {
167
index: self.index,
168
expected: Ownership::Mut,
169
received: Ownership::Ref,
170
}),
171
ArgValue::Mut(arg) => {
172
let received = alloc::borrow::Cow::Owned(arg.reflect_type_path().to_string());
173
Ok(arg
174
.try_downcast_mut()
175
.ok_or_else(|| ArgError::UnexpectedType {
176
index: self.index,
177
expected: alloc::borrow::Cow::Borrowed(T::type_path()),
178
received,
179
})?)
180
}
181
}
182
}
183
184
/// Returns `true` if the argument is of type `T`.
185
pub fn is<T: TypePath>(&self) -> bool {
186
self.value
187
.try_as_reflect()
188
.map(<dyn Reflect>::is::<T>)
189
.unwrap_or_default()
190
}
191
}
192
193
/// Represents an argument that can be passed to a [`DynamicFunction`] or [`DynamicFunctionMut`].
194
///
195
/// [`DynamicFunction`]: crate::func::DynamicFunction
196
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
197
#[derive(Debug)]
198
pub enum ArgValue<'a> {
199
/// An owned argument.
200
Owned(Box<dyn PartialReflect>),
201
/// An immutable reference argument.
202
Ref(&'a dyn PartialReflect),
203
/// A mutable reference argument.
204
Mut(&'a mut dyn PartialReflect),
205
}
206
207
impl<'a> Deref for ArgValue<'a> {
208
type Target = dyn PartialReflect;
209
210
fn deref(&self) -> &Self::Target {
211
match self {
212
ArgValue::Owned(arg) => arg.as_ref(),
213
ArgValue::Ref(arg) => *arg,
214
ArgValue::Mut(arg) => *arg,
215
}
216
}
217
}
218
219