Skip to content

Commit

Permalink
Alter Reflect::*_any methods to return remote type
Browse files Browse the repository at this point in the history
  • Loading branch information
MrGVSV committed Sep 21, 2022
1 parent 232866b commit 626fd81
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 52 deletions.
42 changes: 42 additions & 0 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/any.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use quote::quote;

/// A helper function for quickly implementing the `Reflect::*_any` methods while taking remote types into account.
///
/// Specifically, this handles `Reflect::into_any`, `Reflect::as_any`, and `Reflect::as_any_mut`.
pub(crate) fn impl_reflect_any_methods(is_remote_wrapper: bool) -> proc_macro2::TokenStream {
if is_remote_wrapper {
quote! {
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn ::std::any::Any> {
Box::new(self.0)
}

#[inline]
fn as_any(&self) -> &dyn ::std::any::Any {
&self.0
}

#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
&mut self.0
}
}
} else {
quote! {
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn ::std::any::Any> {
self
}

#[inline]
fn as_any(&self) -> &dyn ::std::any::Any {
self
}

#[inline]
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
self
}
}
}
}
18 changes: 4 additions & 14 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::derive_data::{EnumVariantFields, ReflectEnum, StructField};
use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors};
use crate::impls::any::impl_reflect_any_methods;
use crate::impls::impl_typed;
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
Expand Down Expand Up @@ -88,6 +89,8 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
bevy_reflect_path,
);

let any_impls = impl_reflect_any_methods(reflect_enum.is_remote_wrapper());

let get_type_registration_impl = reflect_enum.meta().get_type_registration();
let (impl_generics, ty_generics, where_clause) =
reflect_enum.meta().generics().split_for_impl();
Expand Down Expand Up @@ -192,20 +195,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
<Self as #bevy_reflect_path::Typed>::type_info()
}

#[inline]
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}

#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}

#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#any_impls

#[inline]
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod any;
mod enums;
mod structs;
mod tuple_structs;
Expand Down
20 changes: 5 additions & 15 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::impls::any::impl_reflect_any_methods;
use crate::impls::impl_typed;
use crate::struct_utility::FieldAccessors;
use crate::ReflectStruct;
Expand Down Expand Up @@ -25,7 +26,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
fields_ref,
fields_mut,
field_indices,
field_count
field_count,
} = FieldAccessors::new(reflect_struct);
let field_types = reflect_struct.active_types();

Expand Down Expand Up @@ -59,6 +60,8 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
bevy_reflect_path,
);

let any_impls = impl_reflect_any_methods(reflect_struct.is_remote_wrapper());

let get_type_registration_impl = reflect_struct.get_type_registration();
let (impl_generics, ty_generics, where_clause) =
reflect_struct.meta().generics().split_for_impl();
Expand Down Expand Up @@ -131,20 +134,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
<Self as #bevy_reflect_path::Typed>::type_info()
}

#[inline]
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}

#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}

#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#any_impls

#[inline]
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
Expand Down
18 changes: 4 additions & 14 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::impls::any::impl_reflect_any_methods;
use crate::impls::impl_typed;
use crate::struct_utility::FieldAccessors;
use crate::ReflectStruct;
Expand Down Expand Up @@ -50,6 +51,8 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
bevy_reflect_path,
);

let any_impls = impl_reflect_any_methods(reflect_struct.is_remote_wrapper());

let (impl_generics, ty_generics, where_clause) =
reflect_struct.meta().generics().split_for_impl();

Expand Down Expand Up @@ -100,20 +103,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
<Self as #bevy_reflect_path::Typed>::type_info()
}

#[inline]
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
self
}

#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}

#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
#any_impls

#[inline]
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,12 +1141,14 @@ bevy_reflect::tests::should_reflect_debug::Test {
value: "Hello".to_string(),
}));

let output: MyType = input.take().expect("data should be of type `MyType`");
let output: external_crate::TheirType = input
.take()
.expect("should downcast to `external_crate::TheirType`");
assert_eq!(
external_crate::TheirType {
value: "Hello".to_string(),
},
output.0
output
);
}

Expand Down
20 changes: 13 additions & 7 deletions crates/bevy_reflect/src/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,18 @@ pub trait Reflect: Any + Send + Sync {
fn get_type_info(&self) -> &'static TypeInfo;

/// Returns the value as a [`Box<dyn Any>`][std::any::Any].
///
/// For remote wrapper types, this will return the remote type instead.
fn into_any(self: Box<Self>) -> Box<dyn Any>;

/// Returns the value as a [`&dyn Any`][std::any::Any].
///
/// For remote wrapper types, this will return the remote type instead.
fn as_any(&self) -> &dyn Any;

/// Returns the value as a [`&mut dyn Any`][std::any::Any].
///
/// For remote wrapper types, this will return the remote type instead.
fn as_any_mut(&mut self) -> &mut dyn Any;

/// Casts this type to a reflected value
Expand Down Expand Up @@ -223,7 +229,7 @@ impl dyn Reflect {
/// Downcasts the value to type `T`, consuming the trait object.
///
/// If the underlying value is not of type `T`, returns `Err(self)`.
pub fn downcast<T: Reflect>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
pub fn downcast<T: Any>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
if self.is::<T>() {
Ok(self.into_any().downcast().unwrap())
} else {
Expand All @@ -234,7 +240,7 @@ impl dyn Reflect {
/// Downcasts the value to type `T`, unboxing and consuming the trait object.
///
/// If the underlying value is not of type `T`, returns `Err(self)`.
pub fn take<T: Reflect>(self: Box<dyn Reflect>) -> Result<T, Box<dyn Reflect>> {
pub fn take<T: Any>(self: Box<dyn Reflect>) -> Result<T, Box<dyn Reflect>> {
self.downcast::<T>().map(|value| *value)
}

Expand All @@ -243,7 +249,7 @@ impl dyn Reflect {
///
/// Read `is` for more information on underlying values and represented types.
#[inline]
pub fn represents<T: Reflect>(&self) -> bool {
pub fn represents<T: Any>(&self) -> bool {
self.type_name() == any::type_name::<T>()
}

Expand All @@ -256,23 +262,23 @@ impl dyn Reflect {
/// to determine what type they represent. Represented types cannot be downcasted
/// to, but you can use [`FromReflect`] to create a value of the represented type from them.
#[inline]
pub fn is<T: Reflect>(&self) -> bool {
self.type_id() == TypeId::of::<T>()
pub fn is<T: Any>(&self) -> bool {
self.as_any().type_id() == TypeId::of::<T>()
}

/// Downcasts the value to type `T` by reference.
///
/// If the underlying value is not of type `T`, returns `None`.
#[inline]
pub fn downcast_ref<T: Reflect>(&self) -> Option<&T> {
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
self.as_any().downcast_ref::<T>()
}

/// Downcasts the value to type `T` by mutable reference.
///
/// If the underlying value is not of type `T`, returns `None`.
#[inline]
pub fn downcast_mut<T: Reflect>(&mut self) -> Option<&mut T> {
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
self.as_any_mut().downcast_mut::<T>()
}
}

0 comments on commit 626fd81

Please sign in to comment.