mod external_impls;
mod std_impls;
pub use fyrox_core_derive::Reflect;
use std::{
any::{Any, TypeId},
fmt::{self, Debug, Display, Formatter},
};
pub mod prelude {
pub use super::{FieldInfo, Reflect};
}
pub trait FieldValue: Any + 'static {
fn as_any(&self) -> &dyn Any;
}
impl<T: 'static> FieldValue for T {
fn as_any(&self) -> &dyn Any {
self
}
}
#[derive(Debug)]
pub enum CastError {
TypeMismatch {
property_name: String,
expected_type_id: TypeId,
actual_type_id: TypeId,
},
}
pub struct FieldInfo<'a> {
pub owner_type_id: TypeId,
pub name: &'static str,
pub display_name: &'static str,
pub description: &'static str,
pub type_name: &'static str,
pub value: &'a dyn FieldValue,
pub read_only: bool,
pub min_value: Option<f64>,
pub max_value: Option<f64>,
pub step: Option<f64>,
pub precision: Option<usize>,
}
impl<'a> FieldInfo<'a> {
pub fn cast_value<T: 'static>(&self) -> Result<&T, CastError> {
match self.value.as_any().downcast_ref::<T>() {
Some(value) => Ok(value),
None => Err(CastError::TypeMismatch {
property_name: self.name.to_string(),
expected_type_id: TypeId::of::<T>(),
actual_type_id: self.value.type_id(),
}),
}
}
}
impl<'a> fmt::Debug for FieldInfo<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PropertyInfo")
.field("owner_type_id", &self.owner_type_id)
.field("name", &self.name)
.field("display_name", &self.display_name)
.field("value", &format_args!("{:?}", self.value as *const _))
.field("read_only", &self.read_only)
.field("min_value", &self.min_value)
.field("max_value", &self.max_value)
.field("step", &self.step)
.field("precision", &self.precision)
.field("description", &self.description)
.finish()
}
}
impl<'a> PartialEq<Self> for FieldInfo<'a> {
fn eq(&self, other: &Self) -> bool {
let value_ptr_a = self.value as *const _ as *const ();
let value_ptr_b = other.value as *const _ as *const ();
self.owner_type_id == other.owner_type_id
&& self.name == other.name
&& self.display_name == other.display_name
&& std::ptr::eq(value_ptr_a, value_ptr_b)
&& self.read_only == other.read_only
&& self.min_value == other.min_value
&& self.max_value == other.max_value
&& self.step == other.step
&& self.precision == other.precision
&& self.description == other.description
}
}
pub trait Reflect: Any + Debug {
fn type_name(&self) -> &'static str;
fn fields_info(&self) -> Vec<FieldInfo>;
fn into_any(self: Box<Self>) -> Box<dyn Any>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn as_reflect(&self) -> &dyn Reflect;
fn as_reflect_mut(&mut self) -> &mut dyn Reflect;
fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>>;
fn set_field(
&mut self,
field: &str,
value: Box<dyn Reflect>,
) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
match self.field_mut(field) {
Some(f) => f.set(value),
None => Err(value),
}
}
fn fields(&self) -> Vec<&dyn Reflect> {
vec![]
}
fn fields_mut(&mut self) -> Vec<&mut dyn Reflect> {
vec![]
}
fn field(&self, _name: &str) -> Option<&dyn Reflect> {
None
}
fn field_mut(&mut self, _name: &str) -> Option<&mut dyn Reflect> {
None
}
fn as_array(&self) -> Option<&dyn ReflectArray> {
None
}
fn as_array_mut(&mut self) -> Option<&mut dyn ReflectArray> {
None
}
fn as_list(&self) -> Option<&dyn ReflectList> {
None
}
fn as_list_mut(&mut self) -> Option<&mut dyn ReflectList> {
None
}
fn as_inheritable_variable(&self) -> Option<&dyn ReflectInheritableVariable> {
None
}
fn as_inheritable_variable_mut(&mut self) -> Option<&mut dyn ReflectInheritableVariable> {
None
}
}
pub trait ReflectArray: Reflect {
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect>;
fn reflect_index_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
fn reflect_len(&self) -> usize;
}
pub trait ReflectList: ReflectArray {
fn reflect_push(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>;
fn reflect_pop(&mut self) -> Option<Box<dyn Reflect>>;
fn reflect_remove(&mut self, index: usize) -> Option<Box<dyn Reflect>>;
fn reflect_insert(
&mut self,
index: usize,
value: Box<dyn Reflect>,
) -> Result<(), Box<dyn Reflect>>;
}
pub trait ReflectInheritableVariable: Reflect + Debug {
fn try_inherit(
&mut self,
parent: &dyn ReflectInheritableVariable,
) -> Result<Option<Box<dyn Reflect>>, InheritError>;
fn reset_modified_flag(&mut self);
fn flags(&self) -> VariableFlags;
fn is_modified(&self) -> bool;
fn value_equals(&self, other: &dyn ReflectInheritableVariable) -> bool;
fn clone_value_box(&self) -> Box<dyn Reflect>;
fn mark_modified(&mut self);
fn inner_value_mut(&mut self) -> &mut dyn Reflect;
fn inner_value_ref(&self) -> &dyn Reflect;
}
#[derive(Debug, PartialEq, Eq)]
pub enum ReflectPathError<'a> {
UnclosedBrackets { s: &'a str },
InvalidIndexSyntax { s: &'a str },
UnknownField { s: &'a str },
NoItemForIndex { s: &'a str },
InvalidDowncast,
NotAnArray,
}
impl<'a> Display for ReflectPathError<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
ReflectPathError::UnclosedBrackets { s } => {
write!(f, "unclosed brackets: `{s}`")
}
ReflectPathError::InvalidIndexSyntax { s } => {
write!(f, "not index syntax: `{s}`")
}
ReflectPathError::UnknownField { s } => {
write!(f, "given unknown field: `{s}`")
}
ReflectPathError::NoItemForIndex { s } => {
write!(f, "no item for index: `{s}`")
}
ReflectPathError::InvalidDowncast => {
write!(
f,
"failed to downcast to the target type after path resolution"
)
}
ReflectPathError::NotAnArray => {
write!(f, "tried to resolve index access, but the reflect type does not implement list API")
}
}
}
}
pub trait ResolvePath {
fn resolve_path<'r, 'p>(
&'r self,
path: &'p str,
) -> Result<&'r dyn Reflect, ReflectPathError<'p>>;
fn resolve_path_mut<'r, 'p>(
&'r mut self,
path: &'p str,
) -> Result<&'r mut dyn Reflect, ReflectPathError<'p>>;
fn get_resolve_path<'r, 'p, T: Reflect>(
&'r self,
path: &'p str,
) -> Result<&'r T, ReflectPathError<'p>> {
self.resolve_path(path)
.and_then(|r| r.downcast_ref().ok_or(ReflectPathError::InvalidDowncast))
}
fn get_resolve_path_mut<'r, 'p, T: Reflect>(
&'r mut self,
path: &'p str,
) -> Result<&'r mut T, ReflectPathError<'p>> {
self.resolve_path_mut(path)
.and_then(|r| r.downcast_mut().ok_or(ReflectPathError::InvalidDowncast))
}
}
impl<T: Reflect> ResolvePath for T {
fn resolve_path<'r, 'p>(
&'r self,
path: &'p str,
) -> Result<&'r dyn Reflect, ReflectPathError<'p>> {
(self as &dyn Reflect).resolve_path(path)
}
fn resolve_path_mut<'r, 'p>(
&'r mut self,
path: &'p str,
) -> Result<&'r mut dyn Reflect, ReflectPathError<'p>> {
(self as &mut dyn Reflect).resolve_path_mut(path)
}
}
pub fn path_to_components(path: &str) -> Vec<Component> {
let mut components = Vec::new();
let mut current_path = path;
while let Ok((component, sub_path)) = Component::next(current_path) {
if let Component::Field(field) = component {
if field.is_empty() {
break;
}
}
current_path = sub_path;
components.push(component);
}
components
}
pub trait GetField {
fn get_field<T: 'static>(&self, name: &str) -> Option<&T>;
fn get_field_mut<T: 'static>(&mut self, _name: &str) -> Option<&mut T>;
}
impl<R: Reflect> GetField for R {
fn get_field<T: 'static>(&self, name: &str) -> Option<&T> {
self.field(name)
.and_then(|reflect| reflect.as_any().downcast_ref())
}
fn get_field_mut<T: 'static>(&mut self, name: &str) -> Option<&mut T> {
self.field_mut(name)
.and_then(|reflect| reflect.as_any_mut().downcast_mut())
}
}
pub enum Component<'p> {
Field(&'p str),
Index(&'p str),
}
impl<'p> Component<'p> {
fn next(mut path: &'p str) -> Result<(Self, &'p str), ReflectPathError<'p>> {
if path.bytes().next() == Some(b'.') {
path = &path[1..];
}
let mut bytes = path.bytes().enumerate();
while let Some((i, b)) = bytes.next() {
if b == b'.' {
let (l, r) = path.split_at(i);
return Ok((Self::Field(l), &r[1..]));
}
if b == b'[' {
if i != 0 {
let (l, r) = path.split_at(i);
return Ok((Self::Field(l), r));
}
if let Some((end, _)) = bytes.find(|(_, b)| *b == b']') {
let l = &path[1..end];
let r = &path[end + 1..];
return Ok((Self::Index(l), r));
} else {
return Err(ReflectPathError::UnclosedBrackets { s: path });
}
}
}
Ok((Self::Field(path), ""))
}
fn resolve<'r>(
&self,
reflect: &'r dyn Reflect,
) -> Result<&'r dyn Reflect, ReflectPathError<'p>> {
match self {
Self::Field(path) => reflect
.field(path)
.ok_or(ReflectPathError::UnknownField { s: path }),
Self::Index(path) => {
let list = reflect.as_array().ok_or(ReflectPathError::NotAnArray)?;
let index = path
.parse::<usize>()
.map_err(|_| ReflectPathError::InvalidIndexSyntax { s: path })?;
list.reflect_index(index)
.ok_or(ReflectPathError::NoItemForIndex { s: path })
}
}
}
fn resolve_mut<'r>(
&self,
reflect: &'r mut dyn Reflect,
) -> Result<&'r mut dyn Reflect, ReflectPathError<'p>> {
match self {
Self::Field(path) => reflect
.field_mut(path)
.ok_or(ReflectPathError::UnknownField { s: path }),
Self::Index(path) => {
let list = reflect.as_array_mut().ok_or(ReflectPathError::NotAnArray)?;
let index = path
.parse::<usize>()
.map_err(|_| ReflectPathError::InvalidIndexSyntax { s: path })?;
list.reflect_index_mut(index)
.ok_or(ReflectPathError::NoItemForIndex { s: path })
}
}
}
}
impl ResolvePath for dyn Reflect {
fn resolve_path<'r, 'p>(
&'r self,
path: &'p str,
) -> Result<&'r dyn Reflect, ReflectPathError<'p>> {
let (component, r) = Component::next(path)?;
let child = component.resolve(self)?;
if r.is_empty() {
Ok(child)
} else {
child.resolve_path(r)
}
}
fn resolve_path_mut<'r, 'p>(
&'r mut self,
path: &'p str,
) -> Result<&'r mut dyn Reflect, ReflectPathError<'p>> {
let (component, r) = Component::next(path)?;
let child = component.resolve_mut(self)?;
if r.is_empty() {
Ok(child)
} else {
child.resolve_path_mut(r)
}
}
}
pub enum SetFieldByPathError<'p> {
InvalidPath {
value: Box<dyn Reflect>,
reason: ReflectPathError<'p>,
},
InvalidValue(Box<dyn Reflect>),
}
impl dyn Reflect {
pub fn downcast<T: Reflect>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
if self.is::<T>() {
Ok(self.into_any().downcast().unwrap())
} else {
Err(self)
}
}
pub fn take<T: Reflect>(self: Box<dyn Reflect>) -> Result<T, Box<dyn Reflect>> {
self.downcast::<T>().map(|value| *value)
}
#[inline]
pub fn is<T: Reflect>(&self) -> bool {
self.type_id() == TypeId::of::<T>()
}
#[inline]
pub fn downcast_ref<T: Reflect>(&self) -> Option<&T> {
self.as_any().downcast_ref::<T>()
}
#[inline]
pub fn downcast_mut<T: Reflect>(&mut self) -> Option<&mut T> {
self.as_any_mut().downcast_mut::<T>()
}
#[inline]
pub fn set_field_by_path<'p>(
&mut self,
path: &'p str,
value: Box<dyn Reflect>,
) -> Result<Box<dyn Reflect>, SetFieldByPathError<'p>> {
let (parent_entity, field_path) = if let Some(separator_position) = path.rfind('.') {
let parent_path = &path[..separator_position];
let field = &path[(separator_position + 1)..];
let parent_entity = match self.resolve_path_mut(parent_path) {
Err(reason) => {
return Err(SetFieldByPathError::InvalidPath { reason, value });
}
Ok(property) => property,
};
(parent_entity, field)
} else {
(self, path)
};
parent_entity
.set_field(field_path, value)
.map_err(|e| SetFieldByPathError::InvalidValue(e))
}
}
impl dyn ReflectList {
pub fn get_reflect_index<T: Reflect + 'static>(&self, index: usize) -> Option<&T> {
self.reflect_index(index)
.and_then(|reflect| reflect.downcast_ref())
}
pub fn get_reflect_index_mut<T: Reflect + 'static>(&mut self, index: usize) -> Option<&mut T> {
self.reflect_index_mut(index)
.and_then(|reflect| reflect.downcast_mut())
}
}
#[macro_export]
macro_rules! blank_reflect {
() => {
fn type_name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn fields_info(&self) -> Vec<FieldInfo> {
vec![]
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_reflect(&self) -> &dyn Reflect {
self
}
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
fn field(&self, name: &str) -> Option<&dyn Reflect> {
if name == "self" {
Some(self)
} else {
None
}
}
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
if name == "self" {
Some(self)
} else {
None
}
}
fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
let this = std::mem::replace(self, value.take()?);
Ok(Box::new(this))
}
};
}
#[macro_export]
macro_rules! delegate_reflect {
() => {
fn type_name(&self) -> &'static str {
self.deref().type_name()
}
fn fields_info(&self) -> Vec<FieldInfo> {
self.deref().fields_info()
}
fn into_any(self: Box<Self>) -> Box<dyn Any> {
(*self).into_any()
}
fn as_any(&self) -> &dyn Any {
self.deref().as_any()
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self.deref_mut().as_any_mut()
}
fn as_reflect(&self) -> &dyn Reflect {
self.deref().as_reflect()
}
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self.deref_mut().as_reflect_mut()
}
fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
self.deref_mut().set(value)
}
fn field(&self, name: &str) -> Option<&dyn Reflect> {
self.deref().field(name)
}
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
self.deref_mut().field_mut(name)
}
fn as_array(&self) -> Option<&dyn ReflectArray> {
self.deref().as_array()
}
fn as_array_mut(&mut self) -> Option<&mut dyn ReflectArray> {
self.deref_mut().as_array_mut()
}
fn as_list(&self) -> Option<&dyn ReflectList> {
self.deref().as_list()
}
fn as_list_mut(&mut self) -> Option<&mut dyn ReflectList> {
self.deref_mut().as_list_mut()
}
};
}
use crate::variable::{InheritError, VariableFlags};
pub use blank_reflect;
pub use delegate_reflect;