Skip to content

Commit

Permalink
Unhide ToPartialReflect and ToReflect
Browse files Browse the repository at this point in the history
Also moved these traits to a new `cast` module
  • Loading branch information
MrGVSV committed Aug 16, 2024
1 parent fe6e822 commit 5affe80
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 108 deletions.
114 changes: 6 additions & 108 deletions crates/bevy_reflect/src/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,121 +2,14 @@ use core::fmt::Formatter;
use std::any::Any;

use crate::__macro_exports::RegisterForReflection;
use crate::cast::{ToPartialReflect, ToReflect};
use crate::serde::Serializable;
use crate::utility::GenericTypePathCell;
use crate::{
ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned,
ReflectRef, ReflectRemote, TypeInfo, TypePath,
};

/// A trait used to access `Self` as a [`dyn PartialReflect`].
///
/// This is used to provide by [`ReflectBox<T>`] in order to remotely reflect
/// the inner type, `T`.
///
/// This trait can be implemented on custom trait objects to allow them to be remotely reflected
/// by [`ReflectBox`].
///
/// [`dyn PartialReflect`]: PartialReflect
#[doc(hidden)]
pub trait ToPartialReflect: Send + Sync + 'static {
/// Get a reference to `Self` as a [`&dyn PartialReflect`](PartialReflect).
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect;
/// Get a mutable reference to `Self` as a [`&mut dyn PartialReflect`](PartialReflect).
fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect;
/// Take `Self` as a [`Box<dyn PartialReflect>`](PartialReflect).
fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect>;
}

impl<T: PartialReflect> ToPartialReflect for T {
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect {
self
}

fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
self
}

fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect> {
self
}
}

impl ToPartialReflect for dyn PartialReflect {
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect {
self
}

fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
self
}

fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect> {
self
}
}

/// A trait used to access `Self` as a [`dyn Reflect`].
///
/// This is used to provide by [`ReflectBox<T>`] in order to remotely reflect
/// the inner type, `T`.
///
/// This trait can be implemented on custom trait objects to allow them to be remotely reflected
/// by [`ReflectBox`].
///
/// [`dyn Reflect`]: Reflect
#[doc(hidden)]
pub trait ToReflect: ToPartialReflect {
/// Get a reference to `Self` as a [`&dyn Reflect`](Reflect).
fn to_reflect_ref(&self) -> &dyn Reflect;
/// Get a mutable reference to `Self` as a [`&mut dyn Reflect`](Reflect).
fn to_reflect_mut(&mut self) -> &mut dyn Reflect;
/// Take `Self` as a [`Box<dyn Reflect>`](Reflect).
fn to_reflect_box(self: Box<Self>) -> Box<dyn Reflect>;
}

impl<T: Reflect> ToReflect for T {
fn to_reflect_ref(&self) -> &dyn Reflect {
self
}

fn to_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}

fn to_reflect_box(self: Box<Self>) -> Box<dyn Reflect> {
self
}
}

impl ToPartialReflect for dyn Reflect {
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect {
self.as_partial_reflect()
}

fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
self.as_partial_reflect_mut()
}

fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect> {
self.into_partial_reflect()
}
}

impl ToReflect for dyn Reflect {
fn to_reflect_ref(&self) -> &dyn Reflect {
self
}

fn to_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}

fn to_reflect_box(self: Box<Self>) -> Box<dyn Reflect> {
self
}
}

/// A [remote wrapper] type around [`Box<T>`] where `T` is either a type that implements [`PartialReflect`]/[`Reflect`]
/// or a [`dyn PartialReflect`]/[`dyn Reflect`] trait object.
///
Expand All @@ -126,6 +19,10 @@ impl ToReflect for dyn Reflect {
/// [`ReflectBox`] should never be created or used directly outside remote reflection,
/// in order to avoid double-boxing.
///
/// Along with supporting reflection for `Box<dyn Reflect>`, `Box<dyn PartialReflect>`, and `Box<T: PartialReflect>`,
/// [`ReflectBox`] can also be used to reflect any boxed trait object that is compatible with reflection.
/// This can be achieved by implementing [`ToPartialReflect`] and [`ToReflect`] for the custom trait object type.
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -164,6 +61,7 @@ impl ToReflect for dyn Reflect {
/// [remote wrapper]: ReflectRemote
/// [`dyn PartialReflect`]: PartialReflect
/// [`dyn Reflect`]: Reflect
/// [`cast`]: crate::cast
#[repr(transparent)]
pub struct ReflectBox<T: ?Sized + ToPartialReflect + TypePath>(Box<T>);

Expand Down
179 changes: 179 additions & 0 deletions crates/bevy_reflect/src/cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
//! Traits for casting types to [`dyn PartialReflect`] and [`dyn Reflect`] trait objects.
//!
//! These traits are primarily used by [`ReflectBox`] to cast the inner type to
//! the corresponding reflection trait object.
//!
//! # Example
//!
//! ```
//! # use bevy_reflect::cast::{ToPartialReflect, ToReflect};
//! # use bevy_reflect::{PartialReflect, Reflect, TypePath};
//!
//! // A custom trait used to represent equippable items
//! trait Equippable: Reflect {}
//!
//! impl TypePath for dyn Equippable {
//! fn type_path() -> &'static str {
//! "dyn my_crate::equipment::Equippable"
//! }
//!
//! fn short_type_path() -> &'static str {
//! "dyn Equippable"
//! }
//! }
//!
//! impl ToPartialReflect for dyn Equippable {
//! fn to_partial_reflect_ref(&self) -> &dyn PartialReflect {
//! self.as_partial_reflect()
//! }
//!
//! fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
//! self.as_partial_reflect_mut()
//! }
//!
//! fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect> {
//! self.into_partial_reflect()
//! }
//! }
//!
//! impl ToReflect for dyn Equippable {
//! fn to_reflect_ref(&self) -> &dyn Reflect {
//! self.as_reflect()
//! }
//!
//! fn to_reflect_mut(&mut self) -> &mut dyn Reflect {
//! self.as_reflect_mut()
//! }
//!
//! fn to_reflect_box(self: Box<Self>) -> Box<dyn Reflect> {
//! self.into_reflect()
//! }
//! }
//!
//! #[derive(Reflect)]
//! #[reflect(from_reflect = false)]
//! struct Player {
//! // Now `dyn Equippable` can be used with `ReflectBox`:
//! #[reflect(remote = ReflectBox<dyn Equippable>)]
//! weapon: Box<dyn Equippable>,
//! }
//! ```
//!
//! [`dyn PartialReflect`]: PartialReflect
//! [`dyn Reflect`]: Reflect

use crate::{PartialReflect, Reflect};

/// A trait used to access `Self` as a [`dyn PartialReflect`].
///
/// This is used by [`ReflectBox<T>`] in order to remotely reflect the inner type, `T`.
/// In most cases, [`PartialReflect`] should be used instead of this trait.
///
/// This trait can be implemented on custom trait objects to allow them to be remotely reflected
/// by [`ReflectBox`].
///
/// See the [module-level documentation] for details.
///
/// [`dyn PartialReflect`]: PartialReflect
/// [`ReflectBox<T>`]: crate::boxed::ReflectBox
/// [module-level documentation]: crate::cast
pub trait ToPartialReflect: Send + Sync + 'static {
/// Get a reference to `Self` as a [`&dyn PartialReflect`](PartialReflect).
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect;
/// Get a mutable reference to `Self` as a [`&mut dyn PartialReflect`](PartialReflect).
fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect;
/// Take `Self` as a [`Box<dyn PartialReflect>`](PartialReflect).
fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect>;
}

impl<T: PartialReflect> ToPartialReflect for T {
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect {
self
}

fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
self
}

fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect> {
self
}
}

impl ToPartialReflect for dyn PartialReflect {
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect {
self
}

fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
self
}

fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect> {
self
}
}

/// A trait used to access `Self` as a [`dyn Reflect`].
///
/// This is used by [`ReflectBox<T>`] in order to remotely reflect the inner type, `T`.
/// In most cases, [`Reflect`] should be used instead of this trait.
///
/// This trait can be implemented on custom trait objects to allow them to be remotely reflected
/// by [`ReflectBox`].
///
/// See the [module-level documentation] for details.
///
/// [`dyn Reflect`]: Reflect
/// [`ReflectBox<T>`]: crate::boxed::ReflectBox
/// [module-level documentation]: crate::cast
pub trait ToReflect: ToPartialReflect {
/// Get a reference to `Self` as a [`&dyn Reflect`](Reflect).
fn to_reflect_ref(&self) -> &dyn Reflect;
/// Get a mutable reference to `Self` as a [`&mut dyn Reflect`](Reflect).
fn to_reflect_mut(&mut self) -> &mut dyn Reflect;
/// Take `Self` as a [`Box<dyn Reflect>`](Reflect).
fn to_reflect_box(self: Box<Self>) -> Box<dyn Reflect>;
}

impl<T: Reflect> ToReflect for T {
fn to_reflect_ref(&self) -> &dyn Reflect {
self
}

fn to_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}

fn to_reflect_box(self: Box<Self>) -> Box<dyn Reflect> {
self
}
}

impl ToPartialReflect for dyn Reflect {
fn to_partial_reflect_ref(&self) -> &dyn PartialReflect {
self.as_partial_reflect()
}

fn to_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
self.as_partial_reflect_mut()
}

fn to_partial_reflect_box(self: Box<Self>) -> Box<dyn PartialReflect> {
self.into_partial_reflect()
}
}

impl ToReflect for dyn Reflect {
fn to_reflect_ref(&self) -> &dyn Reflect {
self
}

fn to_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}

fn to_reflect_box(self: Box<Self>) -> Box<dyn Reflect> {
self
}
}
1 change: 1 addition & 0 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@

mod array;
pub mod boxed;
pub mod cast;
mod fields;
mod from_reflect;
#[cfg(feature = "functions")]
Expand Down

0 comments on commit 5affe80

Please sign in to comment.