use crate::{
reflect::{prelude::*, ReflectArray, ReflectInheritableVariable, ReflectList},
visitor::prelude::*,
};
use bitflags::bitflags;
use std::{
any::{Any, TypeId},
cell::Cell,
fmt::Debug,
ops::{Deref, DerefMut},
};
bitflags! {
#[derive(Reflect)]
pub struct VariableFlags: u8 {
const NONE = 0;
const MODIFIED = 0b0000_0001;
const NEED_SYNC = 0b0000_0010;
}
}
#[derive(Debug)]
pub enum InheritError {
TypesMismatch {
left_type: TypeId,
right_type: TypeId,
},
}
#[derive(Debug)]
pub struct InheritableVariable<T> {
value: T,
flags: Cell<VariableFlags>,
}
impl<T: Clone> Clone for InheritableVariable<T> {
fn clone(&self) -> Self {
Self {
value: self.value.clone(),
flags: self.flags.clone(),
}
}
}
impl<T> From<T> for InheritableVariable<T> {
fn from(v: T) -> Self {
InheritableVariable::new(v)
}
}
impl<T: PartialEq> PartialEq for InheritableVariable<T> {
fn eq(&self, other: &Self) -> bool {
self.value.eq(&other.value)
}
}
impl<T: Eq> Eq for InheritableVariable<T> {}
impl<T: Default> Default for InheritableVariable<T> {
fn default() -> Self {
Self {
value: T::default(),
flags: Cell::new(VariableFlags::NONE),
}
}
}
impl<T: Clone> InheritableVariable<T> {
pub fn clone_inner(&self) -> T {
self.value.clone()
}
pub fn try_sync_model<S: FnOnce(T)>(&self, setter: S) -> bool {
if self.need_sync() {
let mut flags = self.flags.get();
flags.remove(VariableFlags::NEED_SYNC);
self.flags.set(flags);
(setter)(self.value.clone());
true
} else {
false
}
}
}
impl<T> InheritableVariable<T> {
pub fn new(value: T) -> Self {
Self {
value,
flags: Cell::new(VariableFlags::NONE),
}
}
pub fn new_modified(value: T) -> Self {
Self {
value,
flags: Cell::new(VariableFlags::MODIFIED),
}
}
pub fn new_with_flags(value: T, flags: VariableFlags) -> Self {
Self {
value,
flags: Cell::new(flags),
}
}
pub fn set_value_and_mark_modified(&mut self, value: T) -> T {
self.mark_modified_and_need_sync();
std::mem::replace(&mut self.value, value)
}
pub fn set_value_with_flags(&mut self, value: T, flags: VariableFlags) -> T {
self.flags.set(flags);
std::mem::replace(&mut self.value, value)
}
pub fn set_value_silent(&mut self, value: T) -> T {
std::mem::replace(&mut self.value, value)
}
pub fn need_sync(&self) -> bool {
self.flags.get().contains(VariableFlags::NEED_SYNC)
}
pub fn get_value_ref(&self) -> &T {
&self.value
}
pub fn get_value_mut_and_mark_modified(&mut self) -> &mut T {
self.mark_modified_and_need_sync();
&mut self.value
}
pub fn get_value_mut_silent(&mut self) -> &mut T {
&mut self.value
}
pub fn is_modified(&self) -> bool {
self.flags.get().contains(VariableFlags::MODIFIED)
}
pub fn mark_modified(&mut self) {
self.flags
.get_mut()
.insert(VariableFlags::MODIFIED | VariableFlags::NEED_SYNC);
}
fn mark_modified_and_need_sync(&mut self) {
self.flags
.get_mut()
.insert(VariableFlags::MODIFIED | VariableFlags::NEED_SYNC);
}
}
impl<T> Deref for InheritableVariable<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T> DerefMut for InheritableVariable<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.mark_modified_and_need_sync();
&mut self.value
}
}
impl<T> Visit for InheritableVariable<T>
where
T: Visit,
{
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
let mut region = visitor.enter_region(name)?;
self.value.visit("Value", &mut region)?;
self.flags.get_mut().bits.visit("Flags", &mut region)?;
Ok(())
}
}
impl<T> Reflect for InheritableVariable<T>
where
T: Reflect + Clone + PartialEq + Debug,
{
fn type_name(&self) -> &'static str {
self.value.type_name()
}
fn fields_info(&self) -> Vec<FieldInfo> {
self.value.fields_info()
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
Box::new(self.value).into_any()
}
fn as_any(&self) -> &dyn Any {
self.value.as_any()
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self.value.as_any_mut()
}
fn as_reflect(&self) -> &dyn Reflect {
self.value.as_reflect()
}
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self.value.as_reflect_mut()
}
fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
self.mark_modified_and_need_sync();
self.value.set(value)
}
fn set_field(
&mut self,
field: &str,
value: Box<dyn Reflect>,
) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
self.mark_modified_and_need_sync();
self.value.set_field(field, value)
}
fn fields(&self) -> Vec<&dyn Reflect> {
self.value.fields()
}
fn fields_mut(&mut self) -> Vec<&mut dyn Reflect> {
self.value.fields_mut()
}
fn field(&self, name: &str) -> Option<&dyn Reflect> {
self.value.field(name)
}
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
self.mark_modified_and_need_sync();
self.value.field_mut(name)
}
fn as_array(&self) -> Option<&dyn ReflectArray> {
self.value.as_array()
}
fn as_array_mut(&mut self) -> Option<&mut dyn ReflectArray> {
self.mark_modified_and_need_sync();
self.value.as_array_mut()
}
fn as_list(&self) -> Option<&dyn ReflectList> {
self.value.as_list()
}
fn as_list_mut(&mut self) -> Option<&mut dyn ReflectList> {
self.mark_modified_and_need_sync();
self.value.as_list_mut()
}
fn as_inheritable_variable(&self) -> Option<&dyn ReflectInheritableVariable> {
Some(self)
}
fn as_inheritable_variable_mut(&mut self) -> Option<&mut dyn ReflectInheritableVariable> {
Some(self)
}
}
impl<T> ReflectInheritableVariable for InheritableVariable<T>
where
T: Reflect + Clone + PartialEq + Debug,
{
fn try_inherit(
&mut self,
parent: &dyn ReflectInheritableVariable,
) -> Result<Option<Box<dyn Reflect>>, InheritError> {
if let Some(parent_value) = parent.as_reflect().downcast_ref::<T>() {
if !self.is_modified() {
Ok(Some(Box::new(std::mem::replace(
&mut self.value,
parent_value.clone(),
))))
} else {
Ok(None)
}
} else {
Err(InheritError::TypesMismatch {
left_type: TypeId::of::<Self>(),
right_type: parent.type_id(),
})
}
}
fn reset_modified_flag(&mut self) {
self.flags.get_mut().remove(VariableFlags::MODIFIED)
}
fn flags(&self) -> VariableFlags {
self.flags.get()
}
fn is_modified(&self) -> bool {
self.is_modified()
}
fn value_equals(&self, other: &dyn ReflectInheritableVariable) -> bool {
other
.as_reflect()
.downcast_ref::<T>()
.map_or(false, |other| &self.value == other)
}
fn clone_value_box(&self) -> Box<dyn Reflect> {
Box::new(self.value.clone())
}
fn mark_modified(&mut self) {
self.mark_modified()
}
fn inner_value_mut(&mut self) -> &mut dyn Reflect {
&mut self.value
}
fn inner_value_ref(&self) -> &dyn Reflect {
&self.value
}
}
pub fn try_inherit_properties(
child: &mut dyn Reflect,
parent: &dyn Reflect,
) -> Result<(), InheritError> {
if (*child).type_id() != (*parent).type_id() {
return Err(InheritError::TypesMismatch {
left_type: (*child).type_id(),
right_type: (*parent).type_id(),
});
}
if let (Some(inheritable_child), Some(inheritable_parent)) = (
child.as_inheritable_variable_mut(),
parent.as_inheritable_variable(),
) {
try_inherit_properties(
inheritable_child.inner_value_mut(),
inheritable_parent.inner_value_ref(),
)
} else if let (Some(child_collection), Some(parent_collection)) =
(child.as_array_mut(), parent.as_array())
{
if child_collection.reflect_len() == parent_collection.reflect_len() {
for i in 0..child_collection.reflect_len() {
if let (Some(child_item), Some(parent_item)) = (
child_collection.reflect_index_mut(i),
parent_collection.reflect_index(i),
) {
try_inherit_properties(child_item, parent_item)?;
}
}
}
Ok(())
} else {
for (child_field, parent_field) in child.fields_mut().iter_mut().zip(parent.fields()) {
if let (Some(child_inheritable_field), Some(parent_inheritable_field)) = (
child_field.as_inheritable_variable_mut(),
parent_field.as_inheritable_variable(),
) {
child_inheritable_field.try_inherit(parent_inheritable_field)?;
}
try_inherit_properties(child_field.as_reflect_mut(), parent_field.as_reflect())?;
}
Ok(())
}
}
pub fn reset_inheritable_properties(object: &mut dyn Reflect) {
for field in object.fields_mut() {
if let Some(inheritable_field) = field.as_inheritable_variable_mut() {
inheritable_field.reset_modified_flag();
}
reset_inheritable_properties(field);
}
}
#[cfg(test)]
mod test {
use crate::{
reflect::{prelude::*, ReflectInheritableVariable},
variable::{try_inherit_properties, InheritableVariable},
};
#[derive(Reflect, Clone, Debug, PartialEq)]
struct Foo {
value: InheritableVariable<f32>,
}
#[derive(Reflect, Clone, Debug, PartialEq)]
struct Bar {
foo: Foo,
other_value: InheritableVariable<String>,
}
#[test]
fn test_property_inheritance_via_reflection() {
let mut parent = Bar {
foo: Foo {
value: InheritableVariable::new(1.23),
},
other_value: InheritableVariable::new("Foobar".to_string()),
};
let mut child = parent.clone();
try_inherit_properties(&mut child, &parent).unwrap();
assert_eq!(parent, child);
parent
.other_value
.set_value_and_mark_modified("Baz".to_string());
assert!(ReflectInheritableVariable::is_modified(&parent.other_value),);
child.foo.value.set_value_and_mark_modified(3.21);
assert!(ReflectInheritableVariable::is_modified(&child.foo.value));
try_inherit_properties(&mut child, &parent).unwrap();
assert_eq!(child.other_value.value, "Baz".to_string());
assert_eq!(child.foo.value.value, 3.21);
}
#[test]
fn test_inheritable_variable_equality() {
let va = InheritableVariable::new(1.23);
let vb = InheritableVariable::new(1.23);
assert!(va.value_equals(&vb))
}
#[derive(Reflect, Debug)]
enum SomeEnum {
Bar(InheritableVariable<f32>),
Baz {
foo: InheritableVariable<f32>,
foobar: InheritableVariable<u32>,
},
}
#[test]
fn test_enum_inheritance_tuple() {
let mut child = SomeEnum::Bar(InheritableVariable::new(1.23));
let parent = SomeEnum::Bar(InheritableVariable::new(3.21));
try_inherit_properties(child.as_reflect_mut(), parent.as_reflect()).unwrap();
if let SomeEnum::Bar(value) = child {
assert_eq!(*value, 3.21);
} else {
unreachable!()
}
}
#[test]
fn test_enum_inheritance_struct() {
let mut child = SomeEnum::Baz {
foo: InheritableVariable::new(1.23),
foobar: InheritableVariable::new(123),
};
let parent = SomeEnum::Baz {
foo: InheritableVariable::new(3.21),
foobar: InheritableVariable::new(321),
};
try_inherit_properties(child.as_reflect_mut(), parent.as_reflect()).unwrap();
if let SomeEnum::Baz { foo, foobar } = child {
assert_eq!(*foo, 3.21);
assert_eq!(*foobar, 321);
} else {
unreachable!()
}
}
#[test]
fn test_compound_inheritance() {
#[derive(Reflect, Clone, Debug, PartialEq, Eq)]
struct SomeComplexData {
foo: InheritableVariable<u32>,
}
#[derive(Reflect, Clone, Debug, PartialEq)]
struct MyEntity {
some_field: InheritableVariable<f32>,
incorrectly_inheritable_data: InheritableVariable<SomeComplexData>,
inheritable_data: SomeComplexData,
}
let mut child = MyEntity {
some_field: InheritableVariable::new(1.23),
incorrectly_inheritable_data: InheritableVariable::new(SomeComplexData {
foo: InheritableVariable::new_modified(222),
}),
inheritable_data: SomeComplexData {
foo: InheritableVariable::new_modified(222),
},
};
let parent = MyEntity {
some_field: InheritableVariable::new(3.21),
incorrectly_inheritable_data: InheritableVariable::new(SomeComplexData {
foo: InheritableVariable::new(321),
}),
inheritable_data: SomeComplexData {
foo: InheritableVariable::new(321),
},
};
assert!(try_inherit_properties(&mut child, &parent).is_ok());
assert_eq!(child.some_field.value, 3.21);
assert_eq!(
child.incorrectly_inheritable_data.foo.value,
parent.incorrectly_inheritable_data.foo.value
);
assert_ne!(
child.inheritable_data.foo.value,
parent.inheritable_data.foo.value
);
}
}