split reflect mod into smaller modules

This commit is contained in:
Dmitry Stepanov
2026-05-06 10:55:33 +03:00
parent 46192f2edb
commit e9b389be77
4 changed files with 298 additions and 246 deletions
+129
View File
@@ -0,0 +1,129 @@
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use crate::blank_reflect;
use crate::reflect::Reflect;
use crate::reflect::*;
use fyrox_core_derive::impl_reflect;
/// [`Reflect`] sub trait for working with slices.
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;
}
/// [`Reflect`] sub trait for working with `Vec`-like types
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>>;
}
impl<const N: usize, T: Reflect + Clone> ReflectArray for [T; N] {
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect> {
if let Some(item) = self.get(index) {
Some(item)
} else {
None
}
}
fn reflect_index_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
if let Some(item) = self.get_mut(index) {
Some(item)
} else {
None
}
}
fn reflect_len(&self) -> usize {
self.len()
}
}
impl<const N: usize, T: Reflect + Clone> Reflect for [T; N] {
blank_reflect!();
fn as_array(&self, func: &mut dyn FnMut(Option<&dyn ReflectArray>)) {
func(Some(self))
}
fn as_array_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectArray>)) {
func(Some(self))
}
}
impl_reflect! {
#[reflect(ReflectList, ReflectArray)]
pub struct Vec<T: Reflect + Clone>;
}
impl<T: Reflect + Clone> ReflectArray for Vec<T> {
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect> {
self.get(index).map(|x| x as &dyn Reflect)
}
fn reflect_index_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
self.get_mut(index).map(|x| x as &mut dyn Reflect)
}
fn reflect_len(&self) -> usize {
self.len()
}
}
/// REMARK: `Reflect` is implemented for `Vec<T>` where `T: Reflect` only.
impl<T: Reflect + Clone> ReflectList for Vec<T> {
fn reflect_push(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
self.push(*value.downcast::<T>()?);
Ok(())
}
fn reflect_pop(&mut self) -> Option<Box<dyn Reflect>> {
if let Some(item) = self.pop() {
Some(Box::new(item))
} else {
None
}
}
fn reflect_remove(&mut self, index: usize) -> Option<Box<dyn Reflect>> {
if index < self.len() {
Some(Box::new(self.remove(index)))
} else {
None
}
}
fn reflect_insert(
&mut self,
index: usize,
value: Box<dyn Reflect>,
) -> Result<(), Box<dyn Reflect>> {
self.insert(index, *value.downcast::<T>()?);
Ok(())
}
}
+164
View File
@@ -0,0 +1,164 @@
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
use crate::reflect::Reflect;
use std::any::TypeId;
use std::fmt;
use std::fmt::{Display, Formatter};
/// An error returned from a failed path string query.
#[derive(Debug, PartialEq, Eq)]
pub enum ReflectPathError<'a> {
// syntax errors
UnclosedBrackets { s: &'a str },
InvalidIndexSyntax { s: &'a str },
// access errors
UnknownField { s: &'a str },
NoItemForIndex { s: &'a str },
// type cast errors
InvalidDowncast,
NotAnArray,
}
impl std::error::Error for ReflectPathError<'_> {}
impl Display for ReflectPathError<'_> {
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")
}
}
}
}
/// An error that can occur during "type casting"
#[derive(Debug)]
pub enum CastError {
/// Given type does not match expected.
TypeMismatch {
/// A name of the field.
property_name: String,
/// Expected type identifier.
expected_type_id: TypeId,
/// Actual type identifier.
actual_type_id: TypeId,
},
}
impl std::error::Error for CastError {}
impl Display for CastError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
CastError::TypeMismatch { property_name, .. } => {
write!(
f,
"Given type does not match expected for property {property_name:?}"
)
}
}
}
}
#[derive(Debug)]
pub enum SetFieldError {
NoSuchField {
name: String,
value: Box<dyn Reflect>,
},
InvalidValue {
field_type_name: &'static str,
value: Box<dyn Reflect>,
},
}
impl std::error::Error for SetFieldError {}
impl Display for SetFieldError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SetFieldError::NoSuchField { name, value } => {
write!(f, "No such field as {name:?} for value {value:?}")
}
SetFieldError::InvalidValue {
field_type_name,
value,
} => write!(
f,
"Invalid value for field type {field_type_name}: {value:?}"
),
}
}
}
#[derive(Debug)]
pub enum SetFieldByPathError<'p> {
InvalidPath {
value: Box<dyn Reflect>,
reason: ReflectPathError<'p>,
},
InvalidValue {
field_type_name: &'static str,
value: Box<dyn Reflect>,
},
SetFieldError(SetFieldError),
}
impl std::error::Error for SetFieldByPathError<'_> {}
impl Display for SetFieldByPathError<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SetFieldByPathError::InvalidPath { value, reason } => {
write!(f, "Invalid path: {value:?}. Reason: {reason}")
}
SetFieldByPathError::InvalidValue {
field_type_name,
value,
} => {
write!(f, "Invalid value: {value:?}. Type: {field_type_name}")
}
SetFieldByPathError::SetFieldError(set_field_error) => Display::fmt(set_field_error, f),
}
}
}
+5 -160
View File
@@ -20,6 +20,8 @@
//! Runtime reflection
mod array;
mod error;
mod external_impls;
mod macros;
mod map;
@@ -34,11 +36,13 @@ use crate::{
pub use fyrox_core_derive::Reflect;
use std::{
any::{Any, TypeId},
fmt::{self, Debug, Display, Formatter},
fmt::{self, Debug},
mem::ManuallyDrop,
ops::Deref,
};
pub use array::*;
pub use error::*;
pub use macros::*;
pub use map::*;
@@ -85,37 +89,6 @@ impl<T: Reflect> FieldValue for T {
}
}
/// An error that can occur during "type casting"
#[derive(Debug)]
pub enum CastError {
/// Given type does not match expected.
TypeMismatch {
/// A name of the field.
property_name: String,
/// Expected type identifier.
expected_type_id: TypeId,
/// Actual type identifier.
actual_type_id: TypeId,
},
}
impl std::error::Error for CastError {}
impl Display for CastError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
CastError::TypeMismatch { property_name, .. } => {
write!(
f,
"Given type does not match expected for property {property_name:?}"
)
}
}
}
}
#[derive(Debug)]
pub struct FieldMetadata<'s> {
/// A name of the property.
@@ -446,25 +419,6 @@ pub trait ReflectHandle: Reflect {
fn reflect_as_erased(&self) -> ErasedHandle;
}
/// [`Reflect`] sub trait for working with slices.
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;
}
/// [`Reflect`] sub trait for working with `Vec`-like types
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 {
/// Tries to inherit a value from parent. It will succeed only if the current variable is
/// not marked as modified.
@@ -501,52 +455,6 @@ pub trait ReflectInheritableVariable: Reflect {
fn inner_value_ref(&self) -> &dyn Reflect;
}
/// An error returned from a failed path string query.
#[derive(Debug, PartialEq, Eq)]
pub enum ReflectPathError<'a> {
// syntax errors
UnclosedBrackets { s: &'a str },
InvalidIndexSyntax { s: &'a str },
// access errors
UnknownField { s: &'a str },
NoItemForIndex { s: &'a str },
// type cast errors
InvalidDowncast,
NotAnArray,
}
impl std::error::Error for ReflectPathError<'_> {}
impl Display for ReflectPathError<'_> {
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<'p>(
&self,
@@ -860,69 +768,6 @@ impl ResolvePath for dyn Reflect {
}
}
#[derive(Debug)]
pub enum SetFieldError {
NoSuchField {
name: String,
value: Box<dyn Reflect>,
},
InvalidValue {
field_type_name: &'static str,
value: Box<dyn Reflect>,
},
}
impl std::error::Error for SetFieldError {}
impl Display for SetFieldError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SetFieldError::NoSuchField { name, value } => {
write!(f, "No such field as {name:?} for value {value:?}")
}
SetFieldError::InvalidValue {
field_type_name,
value,
} => write!(
f,
"Invalid value for field type {field_type_name}: {value:?}"
),
}
}
}
#[derive(Debug)]
pub enum SetFieldByPathError<'p> {
InvalidPath {
value: Box<dyn Reflect>,
reason: ReflectPathError<'p>,
},
InvalidValue {
field_type_name: &'static str,
value: Box<dyn Reflect>,
},
SetFieldError(SetFieldError),
}
impl std::error::Error for SetFieldByPathError<'_> {}
impl Display for SetFieldByPathError<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
SetFieldByPathError::InvalidPath { value, reason } => {
write!(f, "Invalid path: {value:?}. Reason: {reason}")
}
SetFieldByPathError::InvalidValue {
field_type_name,
value,
} => {
write!(f, "Invalid value: {value:?}. Type: {field_type_name}")
}
SetFieldByPathError::SetFieldError(set_field_error) => Display::fmt(set_field_error, f),
}
}
}
/// Type-erased API
impl dyn Reflect {
pub fn downcast<T: Reflect>(self: Box<dyn Reflect>) -> Result<Box<T>, Box<dyn Reflect>> {
-86
View File
@@ -81,92 +81,6 @@ impl_reflect_tuple! {
(T0, T1, T2, T3, T4,);
}
impl<const N: usize, T: Reflect + Clone> Reflect for [T; N] {
blank_reflect!();
fn as_array(&self, func: &mut dyn FnMut(Option<&dyn ReflectArray>)) {
func(Some(self))
}
fn as_array_mut(&mut self, func: &mut dyn FnMut(Option<&mut dyn ReflectArray>)) {
func(Some(self))
}
}
impl<const N: usize, T: Reflect + Clone> ReflectArray for [T; N] {
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect> {
if let Some(item) = self.get(index) {
Some(item)
} else {
None
}
}
fn reflect_index_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
if let Some(item) = self.get_mut(index) {
Some(item)
} else {
None
}
}
fn reflect_len(&self) -> usize {
self.len()
}
}
impl_reflect! {
#[reflect(ReflectList, ReflectArray)]
pub struct Vec<T: Reflect + Clone>;
}
impl<T: Reflect + Clone> ReflectArray for Vec<T> {
fn reflect_index(&self, index: usize) -> Option<&dyn Reflect> {
self.get(index).map(|x| x as &dyn Reflect)
}
fn reflect_index_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
self.get_mut(index).map(|x| x as &mut dyn Reflect)
}
fn reflect_len(&self) -> usize {
self.len()
}
}
/// REMARK: `Reflect` is implemented for `Vec<T>` where `T: Reflect` only.
impl<T: Reflect + Clone> ReflectList for Vec<T> {
fn reflect_push(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
self.push(*value.downcast::<T>()?);
Ok(())
}
fn reflect_pop(&mut self) -> Option<Box<dyn Reflect>> {
if let Some(item) = self.pop() {
Some(Box::new(item))
} else {
None
}
}
fn reflect_remove(&mut self, index: usize) -> Option<Box<dyn Reflect>> {
if index < self.len() {
Some(Box::new(self.remove(index)))
} else {
None
}
}
fn reflect_insert(
&mut self,
index: usize,
value: Box<dyn Reflect>,
) -> Result<(), Box<dyn Reflect>> {
self.insert(index, *value.downcast::<T>()?);
Ok(())
}
}
impl Reflect for () {
blank_reflect!();
}