Skip to main content

bevy_reflect/
std_traits.rs

1//! Module containing the [`ReflectDefault`] type.
2
3use alloc::boxed::Box;
4use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
5
6use crate::{FromType, PartialReflect, Reflect};
7
8/// A struct used to provide the default value of a type.
9///
10/// A [`ReflectDefault`] for type `T` can be obtained via [`FromType::from_type`].
11#[derive(Clone)]
12pub struct ReflectDefault {
13    default: fn() -> Box<dyn Reflect>,
14}
15
16impl ReflectDefault {
17    /// Returns the default value for a type.
18    pub fn default(&self) -> Box<dyn Reflect> {
19        (self.default)()
20    }
21}
22
23impl<T: Reflect + Default> FromType<T> for ReflectDefault {
24    fn from_type() -> Self {
25        ReflectDefault {
26            default: || Box::<T>::default(),
27        }
28    }
29}
30
31/// A struct used to perform addition on reflected values.
32///
33/// A [`ReflectAdd`] for type `T` can be obtained via [`FromType::from_type`].
34#[derive(Clone)]
35pub struct ReflectAdd {
36    /// Function pointer implementing [`ReflectAdd::add()`].
37    pub add: fn(
38        Box<dyn PartialReflect>,
39        Box<dyn PartialReflect>,
40    )
41        -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
42}
43
44impl ReflectAdd {
45    /// Adds two reflected values together, returning the result as a new reflected value.
46    ///
47    /// # Errors
48    ///
49    /// Returns `Err((a, b))` if the types are incompatible.
50    pub fn add(
51        &self,
52        a: Box<dyn PartialReflect>,
53        b: Box<dyn PartialReflect>,
54    ) -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
55        (self.add)(a, b)
56    }
57}
58
59impl<T: Reflect + Add<Output: Reflect>> FromType<T> for ReflectAdd {
60    fn from_type() -> Self {
61        ReflectAdd {
62            add: |a: Box<dyn PartialReflect>, b: Box<dyn PartialReflect>| {
63                let (a, b) = match (a.try_downcast::<T>(), b.try_downcast::<T>()) {
64                    (Ok(a), Ok(b)) => (a, b),
65                    (a, b) => {
66                        let a = a
67                            .map(|a| a as Box<dyn PartialReflect>)
68                            .unwrap_or_else(|e| e);
69                        let b = b
70                            .map(|b| b as Box<dyn PartialReflect>)
71                            .unwrap_or_else(|e| e);
72                        return Err((a, b));
73                    }
74                };
75                Ok(Box::new(*a + *b))
76            },
77        }
78    }
79}
80
81/// A struct used to perform subtraction on reflected values.
82///
83/// A [`ReflectSub`] for type `T` can be obtained via [`FromType::from_type`].
84#[derive(Clone)]
85pub struct ReflectSub {
86    /// Function pointer implementing [`ReflectSub::sub()`].
87    pub sub: fn(
88        Box<dyn PartialReflect>,
89        Box<dyn PartialReflect>,
90    )
91        -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
92}
93
94impl ReflectSub {
95    /// Subtracts two reflected values, returning the result as a new reflected value.
96    ///
97    /// # Errors
98    ///
99    /// Returns `Err((a, b))` if the types are incompatible.
100    pub fn sub(
101        &self,
102        a: Box<dyn PartialReflect>,
103        b: Box<dyn PartialReflect>,
104    ) -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
105        (self.sub)(a, b)
106    }
107}
108
109impl<T: Reflect + Sub<Output: Reflect>> FromType<T> for ReflectSub {
110    fn from_type() -> Self {
111        ReflectSub {
112            sub: |a: Box<dyn PartialReflect>, b: Box<dyn PartialReflect>| {
113                let (a, b) = match (a.try_downcast::<T>(), b.try_downcast::<T>()) {
114                    (Ok(a), Ok(b)) => (a, b),
115                    (a, b) => {
116                        let a = a
117                            .map(|a| a as Box<dyn PartialReflect>)
118                            .unwrap_or_else(|e| e);
119                        let b = b
120                            .map(|b| b as Box<dyn PartialReflect>)
121                            .unwrap_or_else(|e| e);
122                        return Err((a, b));
123                    }
124                };
125                Ok(Box::new(*a - *b))
126            },
127        }
128    }
129}
130
131/// A struct used to perform multiplication on reflected values.
132///
133/// A [`ReflectMul`] for type `T` can be obtained via [`FromType::from_type`].
134#[derive(Clone)]
135pub struct ReflectMul {
136    /// Function pointer implementing [`ReflectMul::mul()`].
137    pub mul: fn(
138        Box<dyn PartialReflect>,
139        Box<dyn PartialReflect>,
140    )
141        -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
142}
143
144impl ReflectMul {
145    /// Multiplies two reflected values, returning the result as a new reflected value.
146    ///
147    /// # Errors
148    ///
149    /// Returns `Err((a, b))` if the types are incompatible.
150    pub fn mul(
151        &self,
152        a: Box<dyn PartialReflect>,
153        b: Box<dyn PartialReflect>,
154    ) -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
155        (self.mul)(a, b)
156    }
157}
158
159impl<T: Reflect + Mul<Output: Reflect>> FromType<T> for ReflectMul {
160    fn from_type() -> Self {
161        ReflectMul {
162            mul: |a: Box<dyn PartialReflect>, b: Box<dyn PartialReflect>| {
163                let (a, b) = match (a.try_downcast::<T>(), b.try_downcast::<T>()) {
164                    (Ok(a), Ok(b)) => (a, b),
165                    (a, b) => {
166                        let a = a
167                            .map(|a| a as Box<dyn PartialReflect>)
168                            .unwrap_or_else(|e| e);
169                        let b = b
170                            .map(|b| b as Box<dyn PartialReflect>)
171                            .unwrap_or_else(|e| e);
172                        return Err((a, b));
173                    }
174                };
175                Ok(Box::new(*a * *b))
176            },
177        }
178    }
179}
180
181/// A struct used to perform division on reflected values.
182///
183/// A [`ReflectDiv`] for type `T` can be obtained via [`FromType::from_type`].
184#[derive(Clone)]
185pub struct ReflectDiv {
186    /// Function pointer implementing [`ReflectDiv::div()`].
187    pub div: fn(
188        Box<dyn PartialReflect>,
189        Box<dyn PartialReflect>,
190    )
191        -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
192}
193
194impl ReflectDiv {
195    /// Divides two reflected values, returning the result as a new reflected value.
196    ///
197    /// # Errors
198    ///
199    /// Returns `Err((a, b))` if the types are incompatible.
200    pub fn div(
201        &self,
202        a: Box<dyn PartialReflect>,
203        b: Box<dyn PartialReflect>,
204    ) -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
205        (self.div)(a, b)
206    }
207}
208
209impl<T: Reflect + Div<Output: Reflect>> FromType<T> for ReflectDiv {
210    fn from_type() -> Self {
211        ReflectDiv {
212            div: |a: Box<dyn PartialReflect>, b: Box<dyn PartialReflect>| {
213                let (a, b) = match (a.try_downcast::<T>(), b.try_downcast::<T>()) {
214                    (Ok(a), Ok(b)) => (a, b),
215                    (a, b) => {
216                        let a = a
217                            .map(|a| a as Box<dyn PartialReflect>)
218                            .unwrap_or_else(|e| e);
219                        let b = b
220                            .map(|b| b as Box<dyn PartialReflect>)
221                            .unwrap_or_else(|e| e);
222                        return Err((a, b));
223                    }
224                };
225                Ok(Box::new(*a / *b))
226            },
227        }
228    }
229}
230
231/// A struct used to perform remainder on reflected values.
232///
233/// A [`ReflectRem`] for type `T` can be obtained via [`FromType::from_type`].
234#[derive(Clone)]
235pub struct ReflectRem {
236    /// Function pointer implementing [`ReflectRem::rem()`].
237    pub rem: fn(
238        Box<dyn PartialReflect>,
239        Box<dyn PartialReflect>,
240    )
241        -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
242}
243
244impl ReflectRem {
245    /// Computes the remainder of two reflected values, returning the result as
246    /// a new reflected value.
247    ///
248    /// # Errors
249    ///
250    /// Returns `Err((a, b))` if the types are incompatible.
251    pub fn rem(
252        &self,
253        a: Box<dyn PartialReflect>,
254        b: Box<dyn PartialReflect>,
255    ) -> Result<Box<dyn Reflect>, (Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
256        (self.rem)(a, b)
257    }
258}
259
260impl<T: Reflect + Rem<Output: Reflect>> FromType<T> for ReflectRem {
261    fn from_type() -> Self {
262        ReflectRem {
263            rem: |a: Box<dyn PartialReflect>, b: Box<dyn PartialReflect>| {
264                let (a, b) = match (a.try_downcast::<T>(), b.try_downcast::<T>()) {
265                    (Ok(a), Ok(b)) => (a, b),
266                    (a, b) => {
267                        let a = a
268                            .map(|a| a as Box<dyn PartialReflect>)
269                            .unwrap_or_else(|e| e);
270                        let b = b
271                            .map(|b| b as Box<dyn PartialReflect>)
272                            .unwrap_or_else(|e| e);
273                        return Err((a, b));
274                    }
275                };
276                Ok(Box::new(*a % *b))
277            },
278        }
279    }
280}
281
282/// A struct used to perform addition assignment on reflected values.
283///
284/// A [`ReflectAddAssign`] for type `T` can be obtained via [`FromType::from_type`].
285#[derive(Clone)]
286pub struct ReflectAddAssign {
287    /// Function pointer implementing [`ReflectAddAssign::add_assign()`].
288    pub add_assign: fn(
289        &mut dyn Reflect,
290        Box<dyn PartialReflect>,
291    ) -> Result<(), Option<Box<dyn PartialReflect>>>,
292}
293
294impl ReflectAddAssign {
295    /// Adds a reflected value to another reflected value in place.
296    ///
297    /// # Errors
298    ///
299    /// - Returns `Err(None)` if the first argument is of an incompatible type.
300    /// - Returns `Err(Some(b))` if the second argument is of an incompatible type.
301    pub fn add_assign(
302        &self,
303        a: &mut dyn Reflect,
304        b: Box<dyn PartialReflect>,
305    ) -> Result<(), Option<Box<dyn PartialReflect>>> {
306        (self.add_assign)(a, b)
307    }
308}
309
310impl<T: Reflect + AddAssign> FromType<T> for ReflectAddAssign {
311    fn from_type() -> Self {
312        ReflectAddAssign {
313            add_assign: |a: &mut dyn Reflect, b: Box<dyn PartialReflect>| {
314                let Some(a) = a.downcast_mut::<T>() else {
315                    return Err(None);
316                };
317                let b = match b.try_downcast::<T>() {
318                    Ok(b) => b,
319                    Err(b) => return Err(Some(b)),
320                };
321                *a += *b;
322                Ok(())
323            },
324        }
325    }
326}
327
328/// A struct used to perform subtraction assignment on reflected values.
329///
330/// A [`ReflectSubAssign`] for type `T` can be obtained via [`FromType::from_type`].
331#[derive(Clone)]
332pub struct ReflectSubAssign {
333    /// Function pointer implementing [`ReflectSubAssign::sub_assign()`].
334    pub sub_assign: fn(
335        &mut dyn Reflect,
336        Box<dyn PartialReflect>,
337    ) -> Result<(), Option<Box<dyn PartialReflect>>>,
338}
339
340impl ReflectSubAssign {
341    /// Subtracts a reflected value from another reflected value in place.
342    ///
343    /// # Errors
344    ///
345    /// - Returns `Err(None)` if the first argument is of an incompatible type.
346    /// - Returns `Err(Some(b))` if the second argument is of an incompatible type.
347    pub fn sub_assign(
348        &self,
349        a: &mut dyn Reflect,
350        b: Box<dyn PartialReflect>,
351    ) -> Result<(), Option<Box<dyn PartialReflect>>> {
352        (self.sub_assign)(a, b)
353    }
354}
355
356impl<T: Reflect + SubAssign> FromType<T> for ReflectSubAssign {
357    fn from_type() -> Self {
358        ReflectSubAssign {
359            sub_assign: |a: &mut dyn Reflect, b: Box<dyn PartialReflect>| {
360                let Some(a) = a.downcast_mut::<T>() else {
361                    return Err(None);
362                };
363                let b = match b.try_downcast::<T>() {
364                    Ok(b) => b,
365                    Err(b) => return Err(Some(b)),
366                };
367                *a -= *b;
368                Ok(())
369            },
370        }
371    }
372}
373
374/// A struct used to perform multiplication assignment on reflected values.
375///
376/// A [`ReflectMulAssign`] for type `T` can be obtained via [`FromType::from_type`].
377#[derive(Clone)]
378pub struct ReflectMulAssign {
379    /// Function pointer implementing [`ReflectMulAssign::mul_assign()`].
380    pub mul_assign: fn(
381        &mut dyn Reflect,
382        Box<dyn PartialReflect>,
383    ) -> Result<(), Option<Box<dyn PartialReflect>>>,
384}
385
386impl ReflectMulAssign {
387    /// Multiplies a reflected value by another reflected value in place.
388    ///
389    /// # Errors
390    ///
391    /// - Returns `Err(None)` if the first argument is of an incompatible type.
392    /// - Returns `Err(Some(b))` if the second argument is of an incompatible type.
393    pub fn mul_assign(
394        &self,
395        a: &mut dyn Reflect,
396        b: Box<dyn PartialReflect>,
397    ) -> Result<(), Option<Box<dyn PartialReflect>>> {
398        (self.mul_assign)(a, b)
399    }
400}
401
402impl<T: Reflect + MulAssign> FromType<T> for ReflectMulAssign {
403    fn from_type() -> Self {
404        ReflectMulAssign {
405            mul_assign: |a: &mut dyn Reflect, b: Box<dyn PartialReflect>| {
406                let Some(a) = a.downcast_mut::<T>() else {
407                    return Err(None);
408                };
409                let b = match b.try_downcast::<T>() {
410                    Ok(b) => b,
411                    Err(b) => return Err(Some(b)),
412                };
413                *a *= *b;
414                Ok(())
415            },
416        }
417    }
418}
419
420/// A struct used to perform division assignment on reflected values.
421///
422/// A [`ReflectDivAssign`] for type `T` can be obtained via [`FromType::from_type`].
423#[derive(Clone)]
424pub struct ReflectDivAssign {
425    /// Function pointer implementing [`ReflectDivAssign::div_assign()`].
426    pub div_assign: fn(
427        &mut dyn Reflect,
428        Box<dyn PartialReflect>,
429    ) -> Result<(), Option<Box<dyn PartialReflect>>>,
430}
431
432impl ReflectDivAssign {
433    /// Divides a reflected value by another reflected value in place.
434    ///
435    /// # Errors
436    ///
437    /// - Returns `Err(None)` if the first argument is of an incompatible type.
438    /// - Returns `Err(Some(b))` if the second argument is of an incompatible type.
439    pub fn div_assign(
440        &self,
441        a: &mut dyn Reflect,
442        b: Box<dyn PartialReflect>,
443    ) -> Result<(), Option<Box<dyn PartialReflect>>> {
444        (self.div_assign)(a, b)
445    }
446}
447
448impl<T: Reflect + DivAssign> FromType<T> for ReflectDivAssign {
449    fn from_type() -> Self {
450        ReflectDivAssign {
451            div_assign: |a: &mut dyn Reflect, b: Box<dyn PartialReflect>| {
452                let Some(a) = a.downcast_mut::<T>() else {
453                    return Err(None);
454                };
455                let b = match b.try_downcast::<T>() {
456                    Ok(b) => b,
457                    Err(b) => return Err(Some(b)),
458                };
459                *a /= *b;
460                Ok(())
461            },
462        }
463    }
464}
465
466/// A struct used to perform remainder assignment on reflected values.
467///
468/// A [`ReflectRemAssign`] for type `T` can be obtained via [`FromType::from_type`].
469#[derive(Clone)]
470pub struct ReflectRemAssign {
471    /// Function pointer implementing [`ReflectRemAssign::rem_assign()`].
472    pub rem_assign: fn(
473        &mut dyn Reflect,
474        Box<dyn PartialReflect>,
475    ) -> Result<(), Option<Box<dyn PartialReflect>>>,
476}
477
478impl ReflectRemAssign {
479    /// Computes the remainder of a reflected value by another reflected value in place.
480    ///
481    /// # Errors
482    ///
483    /// - Returns `Err(None)` if the first argument is of an incompatible type.
484    /// - Returns `Err(Some(b))` if the second argument is of an incompatible type.
485    pub fn rem_assign(
486        &self,
487        a: &mut dyn Reflect,
488        b: Box<dyn PartialReflect>,
489    ) -> Result<(), Option<Box<dyn PartialReflect>>> {
490        (self.rem_assign)(a, b)
491    }
492}
493
494impl<T: Reflect + RemAssign> FromType<T> for ReflectRemAssign {
495    fn from_type() -> Self {
496        ReflectRemAssign {
497            rem_assign: |a: &mut dyn Reflect, b: Box<dyn PartialReflect>| {
498                let Some(a) = a.downcast_mut::<T>() else {
499                    return Err(None);
500                };
501                let b = match b.try_downcast::<T>() {
502                    Ok(b) => b,
503                    Err(b) => return Err(Some(b)),
504                };
505                *a %= *b;
506                Ok(())
507            },
508        }
509    }
510}