Add reflect_owned (#6494)

# Objective

There is no way to gen an owned value of `Reflect`.

## Solution

Add it! This was originally a part of #6421, but @MrGVSV asked me to create a separate for it to implement reflect diffing.

---

## Changelog

### Added

- `Reflect::reflect_owned` to get an owned version of `Reflect`.
This commit is contained in:
Hennadii Chernyshchyk 2022-11-06 16:58:38 +00:00
parent 694c980c82
commit feebbc5ea9
16 changed files with 124 additions and 14 deletions

View File

@ -264,6 +264,10 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
#bevy_reflect_path::ReflectMut::Enum(self) #bevy_reflect_path::ReflectMut::Enum(self)
} }
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Enum(self)
}
#hash_fn #hash_fn
#partial_eq_fn #partial_eq_fn

View File

@ -223,6 +223,10 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
#bevy_reflect_path::ReflectMut::Struct(self) #bevy_reflect_path::ReflectMut::Struct(self)
} }
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Struct(self)
}
#hash_fn #hash_fn
#partial_eq_fn #partial_eq_fn

View File

@ -184,6 +184,10 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
#bevy_reflect_path::ReflectMut::TupleStruct(self) #bevy_reflect_path::ReflectMut::TupleStruct(self)
} }
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::TupleStruct(self)
}
#hash_fn #hash_fn
#partial_eq_fn #partial_eq_fn

View File

@ -103,6 +103,10 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
#bevy_reflect_path::ReflectMut::Value(self) #bevy_reflect_path::ReflectMut::Value(self)
} }
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Value(self)
}
#hash_fn #hash_fn
#partial_eq_fn #partial_eq_fn

View File

@ -1,5 +1,6 @@
use crate::{ use crate::{
utility::NonGenericTypeInfoCell, DynamicInfo, Reflect, ReflectMut, ReflectRef, TypeInfo, Typed, utility::NonGenericTypeInfoCell, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef,
TypeInfo, Typed,
}; };
use std::{ use std::{
any::{Any, TypeId}, any::{Any, TypeId},
@ -226,6 +227,11 @@ impl Reflect for DynamicArray {
ReflectMut::Array(self) ReflectMut::Array(self)
} }
#[inline]
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Array(self)
}
#[inline] #[inline]
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic()) Box::new(self.clone_dynamic())

View File

@ -1,7 +1,8 @@
use crate::utility::NonGenericTypeInfoCell; use crate::utility::NonGenericTypeInfoCell;
use crate::{ use crate::{
enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum,
Reflect, ReflectMut, ReflectRef, Struct, Tuple, TypeInfo, Typed, VariantFieldIter, VariantType, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, Typed,
VariantFieldIter, VariantType,
}; };
use std::any::Any; use std::any::Any;
use std::fmt::Formatter; use std::fmt::Formatter;
@ -390,6 +391,11 @@ impl Reflect for DynamicEnum {
ReflectMut::Enum(self) ReflectMut::Enum(self)
} }
#[inline]
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Enum(self)
}
#[inline] #[inline]
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic()) Box::new(self.clone_dynamic())

View File

@ -4,7 +4,7 @@ use std::any::Any;
use crate::utility::GenericTypeInfoCell; use crate::utility::GenericTypeInfoCell;
use crate::{ use crate::{
Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Reflect, Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Reflect,
ReflectFromPtr, ReflectMut, ReflectRef, TypeInfo, TypeRegistration, Typed, ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed,
}; };
impl<T: smallvec::Array + Send + Sync + 'static> Array for SmallVec<T> impl<T: smallvec::Array + Send + Sync + 'static> Array for SmallVec<T>
@ -115,6 +115,10 @@ where
ReflectMut::List(self) ReflectMut::List(self)
} }
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::List(self)
}
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(List::clone_dynamic(self)) Box::new(List::clone_dynamic(self))
} }

View File

@ -1,5 +1,5 @@
use crate::std_traits::ReflectDefault; use crate::std_traits::ReflectDefault;
use crate::{self as bevy_reflect, ReflectFromPtr}; use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned};
use crate::{ use crate::{
map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum,
EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter,
@ -270,6 +270,10 @@ impl<T: FromReflect> Reflect for Vec<T> {
ReflectMut::List(self) ReflectMut::List(self)
} }
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::List(self)
}
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(List::clone_dynamic(self)) Box::new(List::clone_dynamic(self))
} }
@ -434,6 +438,10 @@ impl<K: FromReflect + Eq + Hash, V: FromReflect> Reflect for HashMap<K, V> {
ReflectMut::Map(self) ReflectMut::Map(self)
} }
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Map(self)
}
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic()) Box::new(self.clone_dynamic())
} }
@ -566,6 +574,11 @@ impl<T: Reflect, const N: usize> Reflect for [T; N] {
ReflectMut::Array(self) ReflectMut::Array(self)
} }
#[inline]
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Array(self)
}
#[inline] #[inline]
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic()) Box::new(self.clone_dynamic())
@ -678,6 +691,10 @@ impl Reflect for Cow<'static, str> {
ReflectMut::Value(self) ReflectMut::Value(self)
} }
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Value(self)
}
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone()) Box::new(self.clone())
} }
@ -868,6 +885,10 @@ impl<T: FromReflect> Reflect for Option<T> {
ReflectMut::Enum(self) ReflectMut::Enum(self)
} }
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Enum(self)
}
#[inline] #[inline]
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(Enum::clone_dynamic(self)) Box::new(Enum::clone_dynamic(self))

View File

@ -3,8 +3,8 @@ use std::fmt::{Debug, Formatter};
use crate::utility::NonGenericTypeInfoCell; use crate::utility::NonGenericTypeInfoCell;
use crate::{ use crate::{
Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectRef, Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned,
TypeInfo, Typed, ReflectRef, TypeInfo, Typed,
}; };
/// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`]. /// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`].
@ -246,6 +246,11 @@ impl Reflect for DynamicList {
ReflectMut::List(self) ReflectMut::List(self)
} }
#[inline]
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::List(self)
}
#[inline] #[inline]
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(List::clone_dynamic(self)) Box::new(List::clone_dynamic(self))

View File

@ -5,7 +5,7 @@ use std::hash::Hash;
use bevy_utils::{Entry, HashMap}; use bevy_utils::{Entry, HashMap};
use crate::utility::NonGenericTypeInfoCell; use crate::utility::NonGenericTypeInfoCell;
use crate::{DynamicInfo, Reflect, ReflectMut, ReflectRef, TypeInfo, Typed}; use crate::{DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed};
/// An ordered mapping between [`Reflect`] values. /// An ordered mapping between [`Reflect`] values.
/// ///
@ -300,6 +300,10 @@ impl Reflect for DynamicMap {
ReflectMut::Map(self) ReflectMut::Map(self)
} }
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Map(self)
}
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic()) Box::new(self.clone_dynamic())
} }

View File

@ -45,6 +45,23 @@ pub enum ReflectMut<'a> {
Value(&'a mut dyn Reflect), Value(&'a mut dyn Reflect),
} }
/// An owned enumeration of "kinds" of reflected type.
///
/// Each variant contains a trait object with methods specific to a kind of
/// type.
///
/// A `ReflectOwned` is obtained via [`Reflect::reflect_owned`].
pub enum ReflectOwned {
Struct(Box<dyn Struct>),
TupleStruct(Box<dyn TupleStruct>),
Tuple(Box<dyn Tuple>),
List(Box<dyn List>),
Array(Box<dyn Array>),
Map(Box<dyn Map>),
Enum(Box<dyn Enum>),
Value(Box<dyn Reflect>),
}
/// A reflected Rust type. /// A reflected Rust type.
/// ///
/// Methods for working with particular kinds of Rust type are available using the [`Array`], [`List`], /// Methods for working with particular kinds of Rust type are available using the [`Array`], [`List`],
@ -139,6 +156,11 @@ pub trait Reflect: Any + Send + Sync {
/// See [`ReflectMut`]. /// See [`ReflectMut`].
fn reflect_mut(&mut self) -> ReflectMut; fn reflect_mut(&mut self) -> ReflectMut;
/// Returns an owned enumeration of "kinds" of type.
///
/// See [`ReflectOwned`].
fn reflect_owned(self: Box<Self>) -> ReflectOwned;
/// Clones the value as a `Reflect` trait object. /// Clones the value as a `Reflect` trait object.
/// ///
/// When deriving `Reflect` for a struct, tuple struct or enum, the value is /// When deriving `Reflect` for a struct, tuple struct or enum, the value is

View File

@ -1,5 +1,7 @@
use crate::utility::NonGenericTypeInfoCell; use crate::utility::NonGenericTypeInfoCell;
use crate::{DynamicInfo, NamedField, Reflect, ReflectMut, ReflectRef, TypeInfo, Typed}; use crate::{
DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed,
};
use bevy_utils::{Entry, HashMap}; use bevy_utils::{Entry, HashMap};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::{ use std::{
@ -427,6 +429,11 @@ impl Reflect for DynamicStruct {
ReflectMut::Struct(self) ReflectMut::Struct(self)
} }
#[inline]
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Struct(self)
}
fn apply(&mut self, value: &dyn Reflect) { fn apply(&mut self, value: &dyn Reflect) {
if let ReflectRef::Struct(struct_value) = value.reflect_ref() { if let ReflectRef::Struct(struct_value) = value.reflect_ref() {
for (i, value) in struct_value.iter_fields().enumerate() { for (i, value) in struct_value.iter_fields().enumerate() {

View File

@ -1,7 +1,7 @@
use crate::utility::NonGenericTypeInfoCell; use crate::utility::NonGenericTypeInfoCell;
use crate::{ use crate::{
DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectRef, TypeInfo, DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef,
TypeRegistration, Typed, UnnamedField, TypeInfo, TypeRegistration, Typed, UnnamedField,
}; };
use std::any::{Any, TypeId}; use std::any::{Any, TypeId};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
@ -341,6 +341,11 @@ impl Reflect for DynamicTuple {
ReflectMut::Tuple(self) ReflectMut::Tuple(self)
} }
#[inline]
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Tuple(self)
}
fn apply(&mut self, value: &dyn Reflect) { fn apply(&mut self, value: &dyn Reflect) {
tuple_apply(self, value); tuple_apply(self, value);
} }
@ -540,6 +545,10 @@ macro_rules! impl_reflect_tuple {
ReflectMut::Tuple(self) ReflectMut::Tuple(self)
} }
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::Tuple(self)
}
fn clone_value(&self) -> Box<dyn Reflect> { fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone_dynamic()) Box::new(self.clone_dynamic())
} }

View File

@ -1,5 +1,7 @@
use crate::utility::NonGenericTypeInfoCell; use crate::utility::NonGenericTypeInfoCell;
use crate::{DynamicInfo, Reflect, ReflectMut, ReflectRef, TypeInfo, Typed, UnnamedField}; use crate::{
DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField,
};
use std::any::{Any, TypeId}; use std::any::{Any, TypeId};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::slice::Iter; use std::slice::Iter;
@ -330,6 +332,11 @@ impl Reflect for DynamicTupleStruct {
ReflectMut::TupleStruct(self) ReflectMut::TupleStruct(self)
} }
#[inline]
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::TupleStruct(self)
}
fn apply(&mut self, value: &dyn Reflect) { fn apply(&mut self, value: &dyn Reflect) {
if let ReflectRef::TupleStruct(tuple_struct) = value.reflect_ref() { if let ReflectRef::TupleStruct(tuple_struct) = value.reflect_ref() {
for (i, value) in tuple_struct.iter_fields().enumerate() { for (i, value) in tuple_struct.iter_fields().enumerate() {

View File

@ -23,7 +23,7 @@ use std::any::{Any, TypeId};
/// ///
/// ``` /// ```
/// # use std::any::Any; /// # use std::any::Any;
/// # use bevy_reflect::{NamedField, Reflect, ReflectMut, ReflectRef, StructInfo, TypeInfo, ValueInfo}; /// # use bevy_reflect::{NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, ValueInfo};
/// # use bevy_reflect::utility::NonGenericTypeInfoCell; /// # use bevy_reflect::utility::NonGenericTypeInfoCell;
/// use bevy_reflect::Typed; /// use bevy_reflect::Typed;
/// ///
@ -59,6 +59,7 @@ use std::any::{Any, TypeId};
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() } /// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
/// # fn reflect_ref(&self) -> ReflectRef { todo!() } /// # fn reflect_ref(&self) -> ReflectRef { todo!() }
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } /// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() } /// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
/// # } /// # }
/// ``` /// ```

View File

@ -16,7 +16,7 @@ use std::any::{Any, TypeId};
/// ///
/// ``` /// ```
/// # use std::any::Any; /// # use std::any::Any;
/// # use bevy_reflect::{NamedField, Reflect, ReflectMut, ReflectRef, StructInfo, Typed, TypeInfo}; /// # use bevy_reflect::{NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo};
/// use bevy_reflect::utility::NonGenericTypeInfoCell; /// use bevy_reflect::utility::NonGenericTypeInfoCell;
/// ///
/// struct Foo { /// struct Foo {
@ -46,6 +46,7 @@ use std::any::{Any, TypeId};
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() } /// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
/// # fn reflect_ref(&self) -> ReflectRef { todo!() } /// # fn reflect_ref(&self) -> ReflectRef { todo!() }
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } /// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() } /// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
/// # } /// # }
/// ``` /// ```
@ -79,7 +80,7 @@ impl NonGenericTypeInfoCell {
/// ///
/// ``` /// ```
/// # use std::any::Any; /// # use std::any::Any;
/// # use bevy_reflect::{Reflect, ReflectMut, ReflectRef, TupleStructInfo, Typed, TypeInfo, UnnamedField}; /// # use bevy_reflect::{Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, UnnamedField};
/// use bevy_reflect::utility::GenericTypeInfoCell; /// use bevy_reflect::utility::GenericTypeInfoCell;
/// ///
/// struct Foo<T: Reflect>(T); /// struct Foo<T: Reflect>(T);
@ -107,6 +108,7 @@ impl NonGenericTypeInfoCell {
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() } /// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
/// # fn reflect_ref(&self) -> ReflectRef { todo!() } /// # fn reflect_ref(&self) -> ReflectRef { todo!() }
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } /// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() } /// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
/// # } /// # }
/// ``` /// ```