bevy/crates/bevy_reflect/src/reflect.rs
dataphract 4b4dbb021f document Struct, TupleStruct and Tuple (#3081)
# Objective

These traits are undocumented on `main`.

## Solution

Now they have docs! Included are examples for each trait and their corresponding `GetTypeField` trait. The docs also mention that `#[derive(Reflect)]` will automatically derive the correct subtrait on structs and tuple structs.
2022-01-08 20:45:24 +00:00

100 lines
3.4 KiB
Rust

use crate::{serde::Serializable, List, Map, Struct, Tuple, TupleStruct};
use std::{any::Any, fmt::Debug};
pub use bevy_utils::AHasher as ReflectHasher;
pub enum ReflectRef<'a> {
Struct(&'a dyn Struct),
TupleStruct(&'a dyn TupleStruct),
Tuple(&'a dyn Tuple),
List(&'a dyn List),
Map(&'a dyn Map),
Value(&'a dyn Reflect),
}
pub enum ReflectMut<'a> {
Struct(&'a mut dyn Struct),
TupleStruct(&'a mut dyn TupleStruct),
Tuple(&'a mut dyn Tuple),
List(&'a mut dyn List),
Map(&'a mut dyn Map),
Value(&'a mut dyn Reflect),
}
/// A reflected Rust type.
///
/// Methods for working with particular kinds of Rust type are available using the [`List`], [`Map`],
/// [`Struct`], [`TupleStruct`], and [`Tuple`] subtraits.
///
/// When using `#[derive(Reflect)]` with a struct or tuple struct, the suitable subtrait for that
/// type (`Struct` or `TupleStruct`) is derived automatically.
///
/// # Safety
/// Implementors _must_ ensure that [`Reflect::any`] and [`Reflect::any_mut`] both return the `self`
/// value passed in. If this is not done, [`Reflect::downcast`](trait.Reflect.html#method.downcast)
/// will be UB (and also just logically broken).
pub unsafe trait Reflect: Any + Send + Sync {
fn type_name(&self) -> &str;
fn any(&self) -> &dyn Any;
fn any_mut(&mut self) -> &mut dyn Any;
fn apply(&mut self, value: &dyn Reflect);
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>;
fn reflect_ref(&self) -> ReflectRef;
fn reflect_mut(&mut self) -> ReflectMut;
fn clone_value(&self) -> Box<dyn Reflect>;
/// Returns a hash of the value (which includes the type) if hashing is supported. Otherwise
/// `None` will be returned.
fn reflect_hash(&self) -> Option<u64>;
/// Returns a "partial equal" comparison result if comparison is supported. Otherwise `None`
/// will be returned.
fn reflect_partial_eq(&self, _value: &dyn Reflect) -> Option<bool>;
/// Returns a serializable value, if serialization is supported. Otherwise `None` will be
/// returned.
fn serializable(&self) -> Option<Serializable>;
}
pub trait FromReflect: Reflect + Sized {
/// Creates a clone of a reflected value, converting it to a concrete type if it was a dynamic types (e.g. [`DynamicStruct`](crate::DynamicStruct))
fn from_reflect(reflect: &dyn Reflect) -> Option<Self>;
}
impl Debug for dyn Reflect {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Reflect({})", self.type_name())
}
}
impl dyn Reflect {
pub fn downcast<T: Reflect>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
// SAFE?: Same approach used by std::any::Box::downcast. ReflectValue is always Any and type
// has been checked.
if self.is::<T>() {
unsafe {
let raw: *mut dyn Reflect = Box::into_raw(self);
Ok(Box::from_raw(raw as *mut T))
}
} else {
Err(self)
}
}
pub fn take<T: Reflect>(self: Box<dyn Reflect>) -> Result<T, Box<dyn Reflect>> {
self.downcast::<T>().map(|value| *value)
}
#[inline]
pub fn is<T: Reflect>(&self) -> bool {
self.any().is::<T>()
}
#[inline]
pub fn downcast_ref<T: Reflect>(&self) -> Option<&T> {
self.any().downcast_ref::<T>()
}
#[inline]
pub fn downcast_mut<T: Reflect>(&mut self) -> Option<&mut T> {
self.any_mut().downcast_mut::<T>()
}
}