#![feature(const_type_id)] use std::any::{Any, TypeId}; use xreflect_core::{Builder, EnumBuildable, EnumReflect, Reflect, ReflectError, StructType}; enum Test { Unit, Tuple(i32), Struct { field: u8 }, } impl Reflect for Test { fn amount_of_fields(&self) -> usize { match self { Test::Unit => 0, Test::Tuple(_) => 1, Test::Struct { .. } => 1, } } fn try_get_index_of_field(&self, member_name: &str) -> Result { match self { Test::Unit => Err(ReflectError::FieldNotFound), Test::Tuple(_) => { match member_name { "0" => Ok(0), _ => Err(ReflectError::FieldNotFound), } } Test::Struct { .. } => { match member_name { "field" => Ok(0), _ => Err(ReflectError::FieldNotFound), } } } } fn try_get_field_at(&self, index: usize) -> Result<&T, ReflectError> { match self { Self::Unit => { return Err(ReflectError::FieldNotFound); } Self::Struct { field } => match index { 0 => (field as &dyn Any) .downcast_ref::() .ok_or(ReflectError::WrongType), _ => Err(ReflectError::FieldNotFound), }, Self::Tuple(field) => match index { 0 => (field as &dyn Any) .downcast_ref::() .ok_or(ReflectError::WrongType), _ => Err(ReflectError::FieldNotFound), }, } } fn try_get_field_mut_at(&mut self, index: usize) -> Result<&mut T, ReflectError> { match self { Self::Unit => { return Err(ReflectError::FieldNotFound); } Self::Struct { field } => match index { 0 => (field as &mut dyn Any) .downcast_mut::() .ok_or(ReflectError::WrongType), _ => Err(ReflectError::FieldNotFound), }, Self::Tuple(field) => match index { 0 => (field as &mut dyn Any) .downcast_mut::() .ok_or(ReflectError::WrongType), _ => Err(ReflectError::FieldNotFound), }, } } fn try_get_type_of_field_at(&self, field_index: usize) -> Result { match self { Self::Unit => { return Err(ReflectError::FieldNotFound); } Self::Struct { .. } => match field_index { 0 => Ok(TypeId::of::()), _ => Err(ReflectError::FieldNotFound), }, Self::Tuple(_) => match field_index { 0 => Ok(TypeId::of::()), _ => Err(ReflectError::FieldNotFound), }, } } } impl EnumBuildable for Test { fn build(enum_member_name: &'static str) -> impl Builder { match enum_member_name { "Unit" => { return __xreflect_builders::TestBuilder::Unit; } "Tuple" => { return __xreflect_builders::TestBuilder::Tuple(None); } "Struct" => { return __xreflect_builders::TestBuilder::Struct { field: None, }; } _ => panic!(), } } } impl EnumReflect for Test { const MEMBER_NAMES: &'static [&'static str] = &["Unit", "Tuple", "Struct"]; const MEMBER_TYPES: &'static [StructType] = &[ StructType::Unit, StructType::Tuple(&[TypeId::of::()]), StructType::Record(&[("field", TypeId::of::())]), ]; fn get_index_of_member(member_name: &str) -> Result { match member_name { "Unit" => Ok(0), "Tuple" => Ok(1), "Struct" => Ok(2), _ => Err(ReflectError::EnumMemberNotFound), } } } mod __xreflect_builders { // reflect actual visibility pub(crate) enum TestBuilder { Unit, Tuple(Option), Struct { field: Option }, } use ::xreflect_core::Builder; use super::Test; impl Builder for TestBuilder { fn with_field(mut self, field_name: &'static str, field_value: T) -> Self { match self { Self::Unit => {} Self::Tuple(ref mut field0) => match field_name { "0" => { if std::any::TypeId::of::() == std::any::TypeId::of::() { *field0 = Some(unsafe { std::mem::transmute_copy::(&field_value) }); } else { panic!() } } _ => panic!(), }, Self::Struct { ref mut field } => match field_name { "field" => { if std::any::TypeId::of::() == std::any::TypeId::of::() { *field = Some(unsafe { std::mem::transmute_copy::(&field_value) }); } else { panic!() } } _ => panic!(), }, } self } fn with_field_at(mut self, field_index: usize, field_value: T) -> Self { match self { Self::Unit => {} Self::Tuple(ref mut field0) => match field_index { 0 => { if std::any::TypeId::of::() == std::any::TypeId::of::() { *field0 = Some(unsafe { std::mem::transmute_copy::(&field_value) }); } else { panic!() } } _ => panic!(), }, Self::Struct { ref mut field } => match field_index { 0 => { if std::any::TypeId::of::() == std::any::TypeId::of::() { *field = Some(unsafe { std::mem::transmute_copy::(&field_value) }); } else { panic!() } } _ => panic!(), }, } self } fn try_build(self) -> Result { match self { TestBuilder::Unit => Ok(Test::Unit), TestBuilder::Tuple(field0) => { let Some(field0) = field0 else { panic!() }; Ok(Test::Tuple(field0)) } TestBuilder::Struct { field } => { let Some(field) = field else { panic!() }; Ok(Test::Struct { field }) } } } } } #[test] fn main() { let a = Test::Tuple(36); let b = a.get_field::("0"); dbg!(b); Test::build("Tuple").with_field_at(0, 100i32).build(); }