Skip to content
758 changes: 709 additions & 49 deletions crates/bevy_reflect/bevy_reflect_derive/src/lib.rs

Large diffs are not rendered by default.

103 changes: 103 additions & 0 deletions crates/bevy_reflect/src/enum_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use crate::{Reflect, ReflectRef, Struct, Tuple};

pub trait Enum: Reflect {
fn variant(&self) -> EnumVariant<'_>;
fn variant_mut(&mut self) -> EnumVariantMut<'_>;
fn variant_info(&self) -> VariantInfo<'_>;
fn iter_variants_info(&self) -> VariantInfoIter<'_>;
fn get_index_name(&self, index: usize) -> Option<&str>;
fn get_index_from_name(&self, name: &str) -> Option<usize>;
}
#[derive(PartialEq, Eq)]
pub struct VariantInfo<'a> {
pub index: usize,
pub name: &'a str,
}
pub struct VariantInfoIter<'a> {
pub(crate) value: &'a dyn Enum,
pub(crate) index: usize,
}
impl<'a> VariantInfoIter<'a> {
pub fn new(value: &'a dyn Enum) -> Self {
Self { value, index: 0 }
}
}
impl<'a> Iterator for VariantInfoIter<'a> {
type Item = VariantInfo<'a>;

fn next(&mut self) -> Option<Self::Item> {
let value = self
.value
.get_index_name(self.index)
.map(|name| VariantInfo {
index: self.index,
name,
});
self.index += 1;
value
}
}

pub enum EnumVariant<'a> {
Unit,
NewType(&'a dyn Reflect),
Tuple(&'a dyn Tuple),
Struct(&'a dyn Struct),
}
pub enum EnumVariantMut<'a> {
Unit,
NewType(&'a mut dyn Reflect),
Tuple(&'a mut dyn Tuple),
Struct(&'a mut dyn Struct),
}

#[inline]
pub fn enum_partial_eq<E: Enum>(enum_a: &E, reflect_b: &dyn Reflect) -> Option<bool> {
let enum_b = if let ReflectRef::Enum(e) = reflect_b.reflect_ref() {
e
} else {
return Some(false);
};

if enum_a.variant_info() != enum_b.variant_info() {
return Some(false);
}

let variant_b = enum_b.variant();
match enum_a.variant() {
EnumVariant::Unit => {
if let EnumVariant::Unit = variant_b {
} else {
return Some(false);
}
}
EnumVariant::NewType(t_a) => {
if let EnumVariant::NewType(t_b) = variant_b {
if let Some(false) | None = t_b.reflect_partial_eq(t_a) {
return Some(false);
}
} else {
return Some(false);
}
}
EnumVariant::Tuple(t_a) => {
if let EnumVariant::Tuple(t_b) = variant_b {
if let Some(false) | None = t_b.reflect_partial_eq(t_a.as_reflect()) {
return Some(false);
}
} else {
return Some(false);
}
}
EnumVariant::Struct(s_a) => {
if let EnumVariant::Struct(s_b) = variant_b {
if let Some(false) | None = s_b.reflect_partial_eq(s_a.as_reflect()) {
return Some(false);
}
} else {
return Some(false);
}
}
}
Some(true)
}
8 changes: 8 additions & 0 deletions crates/bevy_reflect/src/impls/smallvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,12 @@ where
fn serializable(&self) -> Option<Serializable> {
None
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
}
149 changes: 146 additions & 3 deletions crates/bevy_reflect/src/impls/std.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
map_partial_eq, serde::Serializable, DynamicMap, List, ListIter, Map, MapIter, Reflect,
ReflectDeserialize, ReflectMut, ReflectRef,
map_partial_eq, serde::Serializable, DynamicMap, Enum, EnumVariant, EnumVariantMut,
GetTypeRegistration, List, ListIter, Map, MapIter, Reflect, ReflectDeserialize, ReflectMut,
ReflectRef, TypeRegistration, VariantInfo, VariantInfoIter,
};

use bevy_reflect_derive::impl_reflect_value;
Expand Down Expand Up @@ -29,7 +30,6 @@ impl_reflect_value!(isize(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(f32(Serialize, Deserialize));
impl_reflect_value!(f64(Serialize, Deserialize));
impl_reflect_value!(String(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(Option<T: Serialize + Clone + for<'de> Deserialize<'de> + Reflect + 'static>(Serialize, Deserialize));
impl_reflect_value!(HashSet<T: Serialize + Hash + Eq + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>(Serialize, Deserialize));
impl_reflect_value!(Range<T: Serialize + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>(Serialize, Deserialize));

Expand Down Expand Up @@ -109,6 +109,14 @@ impl<T: Reflect> Reflect for Vec<T> {
fn serializable(&self) -> Option<Serializable> {
None
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

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

impl<K: Reflect + Clone + Eq + Hash, V: Reflect + Clone> Map for HashMap<K, V> {
Expand Down Expand Up @@ -203,6 +211,14 @@ impl<K: Reflect + Clone + Eq + Hash, V: Reflect + Clone> Reflect for HashMap<K,
fn serializable(&self) -> Option<Serializable> {
None
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

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

impl Reflect for Cow<'static, str> {
Expand Down Expand Up @@ -263,4 +279,131 @@ impl Reflect for Cow<'static, str> {
fn serializable(&self) -> Option<Serializable> {
Some(Serializable::Borrowed(self))
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

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

impl<T: Reflect + Clone + Send + Sync + 'static> GetTypeRegistration for Option<T> {
fn get_type_registration() -> TypeRegistration {
TypeRegistration::of::<Option<T>>()
}
}
impl<T: Reflect + Clone + Send + Sync + 'static> Enum for Option<T> {
fn variant(&self) -> EnumVariant<'_> {
match self {
Option::Some(new_type) => EnumVariant::NewType(new_type as &dyn Reflect),
Option::None => EnumVariant::Unit,
}
}

fn variant_mut(&mut self) -> EnumVariantMut<'_> {
match self {
Option::Some(new_type) => EnumVariantMut::NewType(new_type as &mut dyn Reflect),
Option::None => EnumVariantMut::Unit,
}
}

fn variant_info(&self) -> VariantInfo<'_> {
let index = match self {
Option::Some(_) => 0usize,
Option::None => 1usize,
};
VariantInfo {
index,
name: self.get_index_name(index).unwrap(),
}
}

fn get_index_name(&self, index: usize) -> Option<&'_ str> {
match index {
0usize => Some("Option::Some"),
1usize => Some("Option::None"),
_ => None,
}
}

fn get_index_from_name(&self, name: &str) -> Option<usize> {
match name {
"Option::Some" => Some(0usize),
"Option::None" => Some(1usize),
_ => None,
}
}

fn iter_variants_info(&self) -> VariantInfoIter<'_> {
VariantInfoIter::new(self)
}
}
impl<T: Reflect + Clone + Send + Sync + 'static> Reflect for Option<T> {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}

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

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

#[inline]
fn clone_value(&self) -> Box<dyn Reflect> {
Box::new(self.clone())
}

#[inline]
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
*self = value.take()?;
Ok(())
}

#[inline]
fn apply(&mut self, value: &dyn Reflect) {
let value = value.any();
if let Some(value) = value.downcast_ref::<Self>() {
*self = value.clone();
} else {
{
panic!("Enum is not {}.", &std::any::type_name::<Self>());
};
}
}

fn reflect_ref(&self) -> ReflectRef {
ReflectRef::Enum(self)
}

fn reflect_mut(&mut self) -> ReflectMut {
ReflectMut::Enum(self)
}

fn serializable(&self) -> Option<Serializable> {
None
}

fn reflect_hash(&self) -> Option<u64> {
None
}

fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
crate::enum_partial_eq(self, value)
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
}
2 changes: 2 additions & 0 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod enum_trait;
mod list;
mod map;
mod path;
Expand Down Expand Up @@ -41,6 +42,7 @@ pub mod prelude {
};
}

pub use enum_trait::*;
pub use impls::*;
pub use list::*;
pub use map::*;
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_reflect/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ impl Reflect for DynamicList {
fn serializable(&self) -> Option<Serializable> {
None
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

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

pub struct ListIter<'a> {
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_reflect/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ impl Reflect for DynamicMap {
fn serializable(&self) -> Option<Serializable> {
None
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

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

pub struct MapIter<'a> {
Expand Down
6 changes: 5 additions & 1 deletion crates/bevy_reflect/src/reflect.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{serde::Serializable, List, Map, Struct, Tuple, TupleStruct};
use crate::{serde::Serializable, Enum, List, Map, Struct, Tuple, TupleStruct};
use std::{any::Any, fmt::Debug};

pub use bevy_utils::AHasher as ReflectHasher;
Expand All @@ -9,6 +9,7 @@ pub enum ReflectRef<'a> {
Tuple(&'a dyn Tuple),
List(&'a dyn List),
Map(&'a dyn Map),
Enum(&'a dyn Enum),
Value(&'a dyn Reflect),
}

Expand All @@ -18,6 +19,7 @@ pub enum ReflectMut<'a> {
Tuple(&'a mut dyn Tuple),
List(&'a mut dyn List),
Map(&'a mut dyn Map),
Enum(&'a mut dyn Enum),
Value(&'a mut dyn Reflect),
}

Expand All @@ -37,6 +39,8 @@ pub trait Reflect: Any + Send + Sync {
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>;
fn as_reflect(&self) -> &dyn Reflect;
fn as_reflect_mut(&mut self) -> &mut dyn Reflect;
}

impl Debug for dyn Reflect {
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_reflect/src/serde/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ impl<'a> Serialize for ReflectSerializer<'a> {
value,
}
.serialize(serializer),
ReflectRef::Enum(_value) => {
todo!()
}
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions crates/bevy_reflect/src/struct_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,14 @@ impl Reflect for DynamicStruct {
fn serializable(&self) -> Option<Serializable> {
None
}

fn as_reflect(&self) -> &dyn Reflect {
self
}

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

#[inline]
Expand Down
Loading