use crate::{
reflect::{prelude::*, ReflectArray, ReflectInheritableVariable, ReflectList},
visitor::prelude::*,
};
use bitflags::bitflags;
use std::{
any::{Any, TypeId},
cell::Cell,
fmt::Debug,
ops::{Deref, DerefMut},
};
#[derive(Reflect, Debug, Copy, Clone, Ord, PartialOrd, PartialEq, Eq)]
#[repr(transparent)]
pub struct VariableFlags(u8);
bitflags! {
impl 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_modified(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::MODIFIED),
}
}
}
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_modified(value: T) -> Self {
Self {
value,
flags: Cell::new(VariableFlags::MODIFIED),
}
}
pub fn new_non_modified(value: T) -> Self {
Self {
value,
flags: Cell::new(VariableFlags::NONE),
}
}
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);
}
pub fn take(self) -> T {
self.value
}
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 visited = false;
if visitor.is_reading() {
visited = self.value.visit(name, visitor).is_ok();
self.flags.get_mut().insert(VariableFlags::MODIFIED);
}
if !visited {
if visitor.is_reading() {
if let Ok(mut region) = visitor.enter_region(name) {
let _ = self.value.visit("Value", &mut region);
self.flags.get_mut().0.visit("Flags", &mut region)?;
} else {
self.flags.get_mut().remove(VariableFlags::MODIFIED);
}
} else if self.flags.get().contains(VariableFlags::MODIFIED) {
let mut region = visitor.enter_region(name)?;
self.value.visit("Value", &mut region)?;
self.flags.get_mut().0.visit("Flags", &mut region)?;
} else {
}
}
Ok(())
}
}
impl<T> Reflect for InheritableVariable<T>
where
T: Reflect + Clone + PartialEq + Debug,
{
fn type_name(&self) -> &'static str {
self.value.type_name()
}
fn doc(&self) -> &'static str {
self.value.doc()
}
fn fields_info(&self, func: &mut dyn FnMut(Vec<FieldInfo>)) {
self.value.fields_info(func)
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
Box::new(self.value).into_any()
}
fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
self.value.as_any(func)
}
fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
self.value.as_any_mut(func)
}
fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
self.value.as_reflect(func)
}
fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
self.value.as_reflect_mut(func)
}
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>,
func: &mut dyn FnMut(Result<Box<dyn Reflect>, Box<dyn Reflect>>),
) {
self.mark_modified_and_need_sync();
self.value.set_field(field, value, func)
}
fn fields(&self, func: &mut dyn FnMut(Vec<&dyn Reflect>)) {
self.value.fields(func)
}
fn fields_mut(&mut self, func: &mut dyn FnMut(Vec<&mut dyn Reflect>)) {
self.value.fields_mut(func)
}
fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>)) {
self.value.field(name, func)
}
fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
self.mark_modified_and_need_sync();
self.value.field_mut(name, func)
}
fn as_array(&self, func: &mut dyn FnMut(Option<&dyn ReflectArray>)) {
self.value.as_array(func)
}
fn as_array_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectArray>)) {
self.mark_modified_and_need_sync();
self.value.as_array_mut(func)
}
fn as_list(&self, func: &mut dyn FnMut(Option<&dyn ReflectList>)) {
self.value.as_list(func)
}
fn as_list_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectList>)) {
self.mark_modified_and_need_sync();
self.value.as_list_mut(func)
}
fn as_inheritable_variable(
&self,
func: &mut dyn FnMut(Option<&dyn ReflectInheritableVariable>),
) {
func(Some(self))
}
fn as_inheritable_variable_mut(
&mut self,
func: &mut dyn FnMut(Option<&mut dyn ReflectInheritableVariable>),
) {
func(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> {
let mut result: Result<Option<Box<dyn Reflect>>, InheritError> = Ok(None);
parent.as_reflect(&mut |parent| {
parent.downcast_ref::<T>(&mut |downcasted| match downcasted {
Some(parent_value) => {
if !self.is_modified() {
let mut parent_value_clone = parent_value.clone();
mark_inheritable_properties_non_modified(&mut parent_value_clone);
result = Ok(Some(Box::new(std::mem::replace(
&mut self.value,
parent_value_clone,
))));
}
}
None => {
result = Err(InheritError::TypesMismatch {
left_type: TypeId::of::<Self>(),
right_type: parent.type_id(),
});
}
});
});
result
}
fn reset_modified_flag(&mut self) {
self.flags.get_mut().remove(VariableFlags::MODIFIED)
}
fn flags(&self) -> VariableFlags {
self.flags.get()
}
fn set_flags(&mut self, flags: VariableFlags) {
self.flags.set(flags)
}
fn is_modified(&self) -> bool {
self.is_modified()
}
fn value_equals(&self, other: &dyn ReflectInheritableVariable) -> bool {
let mut output_result = false;
other.as_reflect(&mut |reflect| {
reflect.downcast_ref::<T>(&mut |result| {
output_result = match result {
Some(other) => &self.value == other,
None => false,
};
})
});
output_result
}
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,
ignored_types: &[TypeId],
) -> Result<(), InheritError> {
let child_type_id = (*child).type_id();
let parent_type_id = (*parent).type_id();
if ignored_types.contains(&child_type_id) || ignored_types.contains(&parent_type_id) {
return Ok(());
}
if child_type_id != parent_type_id {
return Err(InheritError::TypesMismatch {
left_type: (*child).type_id(),
right_type: (*parent).type_id(),
});
}
let mut result = None;
child.as_inheritable_variable_mut(&mut |inheritable_child| {
if let Some(inheritable_child) = inheritable_child {
parent.as_inheritable_variable(&mut |inheritable_parent| {
if let Some(inheritable_parent) = inheritable_parent {
if let Err(e) = inheritable_child.try_inherit(inheritable_parent) {
result = Some(Err(e));
}
if !matches!(result, Some(Err(_))) {
result = Some(try_inherit_properties(
inheritable_child.inner_value_mut(),
inheritable_parent.inner_value_ref(),
ignored_types,
));
}
}
})
}
});
if result.is_none() {
child.as_array_mut(&mut |child_collection| {
if let Some(child_collection) = child_collection {
parent.as_array(&mut |parent_collection| {
if let Some(parent_collection) = parent_collection {
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),
) {
if let Err(e) = try_inherit_properties(
child_item,
parent_item,
ignored_types,
) {
result = Some(Err(e));
break;
}
}
}
}
}
})
}
})
}
if result.is_none() {
child.fields_mut(&mut |mut child_fields| {
parent.fields(&mut |parent_fields| {
for (child_field, parent_field) in child_fields.iter_mut().zip(parent_fields) {
if let Err(e) =
try_inherit_properties(*child_field, parent_field, ignored_types)
{
result = Some(Err(e));
}
if matches!(result, Some(Err(_))) {
break;
}
}
})
});
}
result.unwrap_or(Ok(()))
}
pub fn do_with_inheritable_variables<F>(root: &mut dyn Reflect, func: &mut F)
where
F: FnMut(&mut dyn ReflectInheritableVariable),
{
root.apply_recursively_mut(&mut |object| {
object.as_inheritable_variable_mut(&mut |variable| {
if let Some(variable) = variable {
func(variable);
}
});
})
}
pub fn mark_inheritable_properties_non_modified(object: &mut dyn Reflect) {
do_with_inheritable_variables(object, &mut |variable| variable.reset_modified_flag());
}
pub fn mark_inheritable_properties_modified(object: &mut dyn Reflect) {
do_with_inheritable_variables(object, &mut |variable| variable.mark_modified());
}
#[cfg(test)]
mod test {
use std::{cell::Cell, ops::DerefMut};
use crate::{
reflect::{prelude::*, ReflectInheritableVariable},
variable::{try_inherit_properties, InheritableVariable, VariableFlags},
visitor::{Visit, Visitor},
};
#[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_non_modified(1.23),
},
other_value: InheritableVariable::new_non_modified("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_non_modified(1.23);
let vb = InheritableVariable::new_non_modified(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_non_modified(1.23));
let parent = SomeEnum::Bar(InheritableVariable::new_non_modified(3.21));
try_inherit_properties(&mut child, &parent, &[]).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_non_modified(1.23),
foobar: InheritableVariable::new_non_modified(123),
};
let parent = SomeEnum::Baz {
foo: InheritableVariable::new_non_modified(3.21),
foobar: InheritableVariable::new_non_modified(321),
};
try_inherit_properties(&mut child, &parent, &[]).unwrap();
if let SomeEnum::Baz { foo, foobar } = child {
assert_eq!(*foo, 3.21);
assert_eq!(*foobar, 321);
} else {
unreachable!()
}
}
#[test]
fn test_collection_inheritance() {
#[derive(Reflect, Clone, Debug, PartialEq)]
struct Foo {
some_data: f32,
}
#[derive(Reflect, Clone, Debug, PartialEq)]
struct CollectionItem {
foo: InheritableVariable<Foo>,
bar: InheritableVariable<u32>,
}
#[derive(Reflect, Clone, Debug, PartialEq)]
struct MyEntity {
collection: InheritableVariable<Vec<CollectionItem>>,
}
let parent = MyEntity {
collection: InheritableVariable::new_modified(vec![CollectionItem {
foo: InheritableVariable::new_modified(Foo { some_data: 123.321 }),
bar: InheritableVariable::new_modified(321),
}]),
};
let mut child = MyEntity {
collection: InheritableVariable::new_modified(vec![CollectionItem {
foo: InheritableVariable::new_modified(Foo { some_data: 321.123 }),
bar: InheritableVariable::new_non_modified(321),
}]),
};
try_inherit_properties(&mut child, &parent, &[]).unwrap();
let item = &child.collection[0];
assert!(!item.bar.is_modified());
assert_eq!(item.bar.value, 321);
assert_eq!(item.foo.value, Foo { some_data: 321.123 });
assert!(item.foo.is_modified());
}
#[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_non_modified(1.23),
incorrectly_inheritable_data: InheritableVariable::new_non_modified(SomeComplexData {
foo: InheritableVariable::new_modified(222),
}),
inheritable_data: SomeComplexData {
foo: InheritableVariable::new_modified(222),
},
};
let parent = MyEntity {
some_field: InheritableVariable::new_non_modified(3.21),
incorrectly_inheritable_data: InheritableVariable::new_non_modified(SomeComplexData {
foo: InheritableVariable::new_non_modified(321),
}),
inheritable_data: SomeComplexData {
foo: InheritableVariable::new_modified(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
);
}
#[test]
fn inheritable_variable_from_t() {
assert_eq!(
InheritableVariable::from(42),
InheritableVariable {
value: 42,
..Default::default()
}
);
}
#[test]
fn default_for_inheritable_variable() {
assert_eq!(
InheritableVariable::<i32>::default(),
InheritableVariable {
value: 0,
flags: Cell::new(VariableFlags::MODIFIED),
}
);
}
#[test]
fn inheritable_variable_clone_inner() {
let v = InheritableVariable::from(42);
assert_eq!(v.clone_inner(), 42);
}
#[test]
fn inheritable_variable_try_sync_model() {
let v = InheritableVariable::from(42);
assert!(!v.try_sync_model(|s| println!("{}", s)));
let v = InheritableVariable::new_with_flags(42, VariableFlags::NEED_SYNC);
assert!(v.try_sync_model(|s| println!("{}", s)));
}
#[test]
fn inheritable_variable_new_with_flags() {
let v = InheritableVariable::new_with_flags(42, VariableFlags::MODIFIED);
assert_eq!(
v,
InheritableVariable {
value: 42,
flags: Cell::new(VariableFlags::MODIFIED),
}
);
}
#[test]
fn inheritable_variable_set_value_with_flags() {
let mut v = InheritableVariable::from(42);
let res = v.set_value_with_flags(15, VariableFlags::NEED_SYNC);
assert_eq!(res, 42);
assert_eq!(
v,
InheritableVariable {
value: 15,
flags: Cell::new(VariableFlags::NEED_SYNC),
}
);
}
#[test]
fn inheritable_variable_set_value_silent() {
let mut v = InheritableVariable::from(42);
let res = v.set_value_silent(15);
assert_eq!(res, 42);
assert_eq!(
v,
InheritableVariable {
value: 15,
flags: Cell::new(VariableFlags::MODIFIED),
}
);
}
#[test]
fn inheritable_variable_need_sync() {
let v = InheritableVariable::from(42);
assert!(!v.need_sync());
let v = InheritableVariable::new_with_flags(42, VariableFlags::NEED_SYNC);
assert!(v.need_sync());
}
#[test]
fn inheritable_variable_get_value_ref() {
let v = InheritableVariable::from(42);
assert_eq!(v.get_value_ref(), &42);
}
#[test]
fn inheritable_variable_get_value_mut_and_mark_modified() {
let mut v = InheritableVariable::from(42);
assert_eq!(v.get_value_mut_and_mark_modified(), &mut 42);
assert_eq!(
v,
InheritableVariable {
value: 42,
flags: Cell::new(VariableFlags::MODIFIED),
}
);
}
#[test]
fn inheritable_variable_get_value_mut_silent() {
let mut v = InheritableVariable::from(42);
assert_eq!(v.get_value_mut_silent(), &mut 42);
}
#[test]
fn inheritable_variable_is_modified() {
let v = InheritableVariable::new_with_flags(42, VariableFlags::NONE);
assert!(!v.is_modified());
let v = InheritableVariable::new_with_flags(42, VariableFlags::MODIFIED);
assert!(v.is_modified());
}
#[test]
fn inheritable_variable_mark_modified() {
let mut v = InheritableVariable::new_with_flags(42, VariableFlags::NONE);
v.mark_modified();
assert_eq!(
v,
InheritableVariable {
value: 42,
flags: Cell::new(VariableFlags::MODIFIED),
}
);
}
#[test]
fn inheritable_variable_take() {
let v = InheritableVariable::from(42);
assert_eq!(v.take(), 42);
}
#[test]
fn deref_mut_for_inheritable_variable() {
let mut v = InheritableVariable::new_with_flags(42, VariableFlags::NONE);
let res = v.deref_mut();
assert_eq!(res, &mut 42);
assert_eq!(
v,
InheritableVariable {
value: 42,
flags: Cell::new(VariableFlags::MODIFIED),
}
);
}
#[test]
fn visit_for_inheritable_variable() {
let mut v = InheritableVariable::from(42);
let mut visitor = Visitor::default();
assert!(v.visit("name", &mut visitor).is_ok());
}
#[test]
fn inheritable_variable_type_name() {
let v = InheritableVariable::from(42);
assert_eq!(v.type_name(), "i32");
}
#[test]
fn inheritable_variable_doc() {
let v = InheritableVariable::from(42);
assert_eq!(v.doc(), "");
}
#[test]
fn inheritable_variable_flags() {
let v = InheritableVariable::new_with_flags(42, VariableFlags::NONE);
assert_eq!(v.flags(), VariableFlags::NONE);
}
#[test]
fn inheritable_variable_set_flags() {
let mut v = InheritableVariable::new_with_flags(42, VariableFlags::NONE);
v.set_flags(VariableFlags::NEED_SYNC);
assert_eq!(v.flags(), VariableFlags::NEED_SYNC);
}
}