diff --git a/Cargo.toml b/Cargo.toml index eec93ff..f545c0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "sandbox-reflection" +name = "mirror-on-the-wall" version = "0.1.0" edition = "2021" [dependencies] -serde = { version = "1.0.145", features = ["derive"] } -speedy = "0.8.3" +serde = { version = "1.0", features = ["derive"] } +speedy = "0.8" [dev-dependencies] serde_json = "1.0" diff --git a/src/enum_.rs b/src/enum_.rs new file mode 100644 index 0000000..8edaa38 --- /dev/null +++ b/src/enum_.rs @@ -0,0 +1,710 @@ +use crate::{FromReflect, Reflect, Struct, Value, ValueInner}; +use serde::{Deserialize, Serialize}; +use speedy::{Readable, Writable}; +use std::{any::Any, fmt}; + +pub trait Enum: Reflect { + fn variant(&self) -> Variant<'_>; + fn variant_mut(&mut self) -> VariantMut<'_>; +} + +pub struct Variant<'a> { + name: &'a str, + value: &'a dyn Reflect, + get_field_on_variant: for<'b> fn(&'a dyn Reflect, &'b str) -> Option<&'a dyn Reflect>, + get_fields_iter: fn(&'a dyn Reflect) -> VariantFieldsIter<'a>, +} + +impl<'a> fmt::Debug for Variant<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Variant") + .field("name", &self.name) + .field("value", &self.value) + .finish() + } +} + +impl<'a> Variant<'a> { + pub fn new( + name: &'a str, + value: &'a dyn Reflect, + get_field_on_variant: for<'b> fn(&'a dyn Reflect, &'b str) -> Option<&'a dyn Reflect>, + get_fields_iter: fn(&'a dyn Reflect) -> VariantFieldsIter<'a>, + ) -> Self { + Self { + name, + value, + get_field_on_variant, + get_fields_iter, + } + } + + pub fn name(&self) -> &str { + self.name + } + + pub fn field(&self, name: &str) -> Option<&'a dyn Reflect> { + (self.get_field_on_variant)(self.value, name) + } + + pub fn fields(self) -> VariantFieldsIter<'a> { + (self.get_fields_iter)(self.value) + } +} + +pub struct VariantMut<'a> { + name: &'a str, + value: &'a mut dyn Reflect, + get_field_on_variant: for<'b> fn(&'a mut dyn Reflect, &'b str) -> Option<&'a mut dyn Reflect>, + get_fields_iter: fn(&'a mut dyn Reflect) -> VariantFieldsIterMut<'a>, +} + +impl<'a> VariantMut<'a> { + pub fn new( + name: &'a str, + value: &'a mut dyn Reflect, + get_field_on_variant: for<'b> fn( + &'a mut dyn Reflect, + &'b str, + ) -> Option<&'a mut dyn Reflect>, + get_fields_iter: fn(&'a mut dyn Reflect) -> VariantFieldsIterMut<'a>, + ) -> Self { + Self { + name, + value, + get_field_on_variant, + get_fields_iter, + } + } + + pub fn name(&self) -> &str { + self.name + } + + pub fn field_mut(&'a mut self, name: &str) -> Option<&'a mut dyn Reflect> { + (self.get_field_on_variant)(self.value, name) + } + + pub fn into_field_mut(self, name: &str) -> Option<&'a mut dyn Reflect> { + (self.get_field_on_variant)(self.value, name) + } + + pub fn fields_mut(&'a mut self) -> VariantFieldsIterMut<'a> { + (self.get_fields_iter)(self.value) + } + + pub fn into_fields_mut(self) -> VariantFieldsIterMut<'a> { + (self.get_fields_iter)(self.value) + } +} + +pub struct VariantFieldsIter<'a> { + iter: Box + 'a>, +} + +impl<'a> VariantFieldsIter<'a> { + pub fn new(iter: I) -> Self + where + I: IntoIterator + 'a, + { + Self { + iter: Box::new(iter.into_iter()), + } + } +} + +impl<'a> Iterator for VariantFieldsIter<'a> { + type Item = (&'a str, &'a dyn Reflect); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +pub struct VariantFieldsIterMut<'a> { + iter: Box + 'a>, +} + +impl<'a> VariantFieldsIterMut<'a> { + pub fn new(iter: I) -> Self + where + I: IntoIterator + 'a, + { + Self { + iter: Box::new(iter.into_iter()), + } + } +} + +impl<'a> Iterator for VariantFieldsIterMut<'a> { + type Item = (&'a str, &'a mut dyn Reflect); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +#[derive(Clone, Debug, Serialize, Deserialize, Writable, Readable)] +pub struct EnumValue { + name: String, + value: Box, +} + +impl EnumValue { + pub fn new(name: impl Into, value: impl Into) -> Self { + Self { + name: name.into(), + value: Box::new(value.into()), + } + } +} + +impl Reflect for EnumValue { + 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 patch(&mut self, value: &dyn Reflect) { + if let Some(enum_) = value.as_enum() { + if self.variant().name() == enum_.variant().name() { + for (key, value) in self.variant_mut().into_fields_mut() { + if let Some(new_value) = enum_.variant().field(key) { + value.patch(new_value); + } + } + } else if let Some(value) = EnumValue::from_reflect(value) { + *self = value; + } + } + } + + fn to_value(&self) -> Value { + Value(ValueInner::EnumValue(self.clone())) + } + + fn clone_reflect(&self) -> Box { + Box::new(self.clone()) + } + + fn as_struct(&self) -> Option<&dyn Struct> { + None + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + None + } + + fn as_enum(&self) -> Option<&dyn Enum> { + Some(self) + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + Some(self) + } + + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self) + } else { + write!(f, "{:?}", self) + } + } +} + +impl Enum for EnumValue { + fn variant(&self) -> Variant<'_> { + Variant::new( + &self.name, + self.value.as_reflect(), + Self::get_field_on_variant, + Self::get_fields_iter, + ) + } + + fn variant_mut(&mut self) -> VariantMut<'_> { + VariantMut::new( + &self.name, + self.value.as_reflect_mut(), + Self::get_field_on_variant_mut, + Self::get_fields_iter_mut, + ) + } +} + +impl EnumValue { + fn get_field_on_variant<'a>(value: &'a dyn Reflect, name: &str) -> Option<&'a dyn Reflect> { + if let Some(struct_) = value.as_struct() { + struct_.field(name) + } else if let Some(enum_) = value.as_enum() { + enum_.variant().field(name) + } else { + None + } + } + + fn get_field_on_variant_mut<'a>( + value: &'a mut dyn Reflect, + name: &str, + ) -> Option<&'a mut dyn Reflect> { + value.as_struct_mut()?.field_mut(name) + } + + fn get_fields_iter(value: &dyn Reflect) -> VariantFieldsIter<'_> { + if let Some(struct_) = value.as_struct() { + VariantFieldsIter::new(struct_.fields()) + } else if let Some(enum_) = value.as_enum() { + enum_.variant().fields() + } else { + VariantFieldsIter::new(std::iter::empty()) + } + } + + fn get_fields_iter_mut(value: &mut dyn Reflect) -> VariantFieldsIterMut<'_> { + if value.as_struct_mut().is_some() { + VariantFieldsIterMut::new(value.as_struct_mut().unwrap().fields_mut()) + } else if value.as_enum_mut().is_some() { + value.as_enum_mut().unwrap().variant_mut().into_fields_mut() + } else { + VariantFieldsIterMut::new(std::iter::empty()) + } + } +} + +impl FromReflect for EnumValue { + fn from_reflect(reflect: &dyn Reflect) -> Option { + let variant = reflect.as_enum()?.variant(); + Some(Self { + name: variant.name().to_owned(), + value: Box::new(variant.value.to_value()), + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{FromReflect, GetField, Struct, StructValue, Value}; + use std::any::Any; + + #[derive(Clone, Debug, PartialEq, Eq)] + enum Foo { + A { a: i32 }, + B { b: bool }, + } + + impl Reflect for Foo { + 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 patch(&mut self, value: &dyn Reflect) { + if let Some(enum_) = value.as_enum() { + let variant = enum_.variant(); + match self { + Foo::A { a } => { + if variant.name() == "A" { + if let Some(new_value) = variant.field("a") { + a.patch(new_value); + } + return; + } + } + Foo::B { b } => { + if variant.name() == "B" { + if let Some(new_value) = variant.field("b") { + b.patch(new_value); + } + return; + } + } + } + if let Some(new_value) = Self::from_reflect(enum_.as_reflect()) { + *self = new_value; + } + } + } + + fn to_value(&self) -> Value { + match self { + Foo::A { a } => { + EnumValue::new("A", StructValue::default().with_field("a", a.to_owned())).into() + } + Foo::B { b } => { + EnumValue::new("B", StructValue::default().with_field("b", b.to_owned())).into() + } + } + } + + fn clone_reflect(&self) -> Box { + Box::new(self.clone()) + } + + fn as_struct(&self) -> Option<&dyn Struct> { + None + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + None + } + + fn as_enum(&self) -> Option<&dyn Enum> { + Some(self) + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + Some(self) + } + + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self) + } else { + write!(f, "{:?}", self) + } + } + } + + impl Enum for Foo { + fn variant(&self) -> Variant<'_> { + match self { + this @ Foo::A { .. } => { + fn get_field_on_variant<'a>( + this: &'a dyn Reflect, + name: &str, + ) -> Option<&'a dyn Reflect> { + match this.downcast_ref().unwrap() { + Foo::A { a } => (name == "a").then_some(a), + _ => unreachable!(), + } + } + + fn get_fields_iter(this: &dyn Reflect) -> VariantFieldsIter<'_> { + match this.downcast_ref().unwrap() { + Foo::A { a } => { + let iter = [("a", a.as_reflect())]; + VariantFieldsIter::new(iter) + } + _ => unreachable!(), + } + } + + Variant::new("A", this, get_field_on_variant, get_fields_iter) + } + this @ Foo::B { .. } => { + fn get_field_on_variant<'a>( + this: &'a dyn Reflect, + name: &str, + ) -> Option<&'a dyn Reflect> { + match this.downcast_ref().unwrap() { + Foo::B { b } => (name == "b").then_some(b), + _ => unreachable!(), + } + } + + fn get_fields_iter(this: &dyn Reflect) -> VariantFieldsIter<'_> { + match this.downcast_ref().unwrap() { + Foo::B { b } => { + let iter = [("b", b.as_reflect())]; + VariantFieldsIter::new(iter) + } + _ => unreachable!(), + } + } + + Variant::new("B", this, get_field_on_variant, get_fields_iter) + } + } + } + + fn variant_mut(&mut self) -> VariantMut<'_> { + match self { + this @ Foo::A { .. } => { + fn get_field_on_variant<'a>( + this: &'a mut dyn Reflect, + name: &str, + ) -> Option<&'a mut dyn Reflect> { + match this.downcast_mut().unwrap() { + Foo::A { a } => { + if name == "a" { + return Some(a); + } + None + } + _ => unreachable!(), + } + } + + fn get_fields_iter(this: &mut dyn Reflect) -> VariantFieldsIterMut<'_> { + match this.downcast_mut().unwrap() { + Foo::A { a } => { + let iter = [("a", a.as_reflect_mut())]; + VariantFieldsIterMut::new(iter) + } + _ => unreachable!(), + } + } + + VariantMut::new("A", this, get_field_on_variant, get_fields_iter) + } + this @ Foo::B { .. } => { + fn get_field_on_variant<'a>( + this: &'a mut dyn Reflect, + name: &str, + ) -> Option<&'a mut dyn Reflect> { + match this.downcast_mut().unwrap() { + Foo::B { b } => (name == "b").then_some(b), + _ => unreachable!(), + } + } + + fn get_fields_iter(this: &mut dyn Reflect) -> VariantFieldsIterMut<'_> { + match this.downcast_mut().unwrap() { + Foo::B { b } => { + let iter = [("b", b.as_reflect_mut())]; + VariantFieldsIterMut::new(iter) + } + _ => unreachable!(), + } + } + + VariantMut::new("B", this, get_field_on_variant, get_fields_iter) + } + } + } + } + + impl FromReflect for Foo { + fn from_reflect(reflect: &dyn Reflect) -> Option { + let enum_ = reflect.as_enum()?; + let variant = enum_.variant(); + match variant.name() { + "A" => Some(Foo::A { + a: variant.field("a")?.downcast_ref::()?.to_owned(), + }), + "B" => Some(Foo::B { + b: variant.field("b")?.downcast_ref::()?.to_owned(), + }), + _ => None, + } + } + } + + macro_rules! get_field_on_variant { + ($expr:expr, $ident:ident, $ty:ty) => { + *$expr.get_field::<$ty>(stringify!($ident)).unwrap() + }; + } + + #[test] + fn accessing_variants() { + let foo = Foo::A { a: 42 }; + let enum_ = foo.as_enum().unwrap(); + + assert_eq!(get_field_on_variant!(enum_, a, i32), 42); + } + + #[test] + fn accessing_variants_mut() { + let mut foo = Foo::A { a: 42 }; + let enum_ = foo.as_enum_mut().unwrap(); + let mut variant = enum_.variant_mut(); + + variant.field_mut("a").unwrap().patch(&1337); + + assert!(matches!(dbg!(foo), Foo::A { a: 1337 })); + } + + #[test] + fn fields_on_variant() { + let mut foo = Foo::A { a: 42 }; + + for (name, value) in foo.variant().fields() { + if name == "a" { + assert_eq!(value.downcast_ref::().unwrap(), &42); + } else { + panic!("unknown field on variant {name:?}"); + } + } + + for (name, value) in foo.variant_mut().into_fields_mut() { + if name == "a" { + assert_eq!(value.downcast_ref::().unwrap(), &42); + } else { + panic!("unknown field on variant {name:?}"); + } + } + } + + #[test] + fn patch() { + let mut foo = Foo::A { a: 42 }; + foo.patch(&Foo::A { a: 1337 }); + assert!(matches!(dbg!(foo), Foo::A { a: 1337 })); + + let mut foo = Foo::A { a: 1337 }; + foo.patch(&EnumValue::new( + "A", + StructValue::default().with_field("a", 42), + )); + assert!(matches!(dbg!(foo), Foo::A { a: 42 })); + } + + #[test] + fn patch_value() { + let mut value = EnumValue::new("A", StructValue::default().with_field("a", 42)); + value.patch(&Foo::A { a: 1337 }); + assert_eq!(get_field_on_variant!(value, a, i32), 1337,); + + let mut value = EnumValue::new("A", StructValue::default().with_field("a", 42)); + value.patch(&EnumValue::new( + "A", + StructValue::default().with_field("a", 1337), + )); + assert_eq!(get_field_on_variant!(value, a, i32), 1337,); + } + + #[test] + fn patch_change_variant() { + let mut foo = Foo::A { a: 42 }; + + foo.patch(&Foo::B { b: false }); + assert!(matches!(dbg!(&foo), Foo::B { b: false })); + + foo.patch(&Foo::A { a: 1337 }); + assert!(matches!(dbg!(&foo), Foo::A { a: 1337 })); + + foo.patch(&EnumValue::new( + "B", + StructValue::new().with_field("b", true), + )); + assert!(matches!(dbg!(&foo), Foo::B { b: true })); + + foo.patch(&EnumValue::new("A", StructValue::new().with_field("a", 42))); + assert!(matches!(dbg!(&foo), Foo::A { a: 42 })); + } + + #[test] + #[allow(clippy::bool_assert_comparison)] + fn patch_value_change_variant_isnt_allowed() { + let mut foo = EnumValue::new("A", StructValue::new().with_field("a", 42)); + + foo.patch(&Foo::B { b: false }); + assert_eq!(false, get_field_on_variant!(&foo, b, bool)); + + foo.patch(&Foo::A { a: 1337 }); + assert_eq!(1337, get_field_on_variant!(&foo, a, i32)); + + foo.patch(&EnumValue::new( + "B", + StructValue::new().with_field("b", true), + )); + assert_eq!(true, get_field_on_variant!(&foo, b, bool)); + + foo.patch(&EnumValue::new("A", StructValue::new().with_field("a", 42))); + assert_eq!(42, get_field_on_variant!(&foo, a, i32)); + } + + #[test] + fn to_value() { + let foo = Foo::A { a: 42 }; + let value = foo.to_value(); + let new_foo = Foo::from_reflect(&value).unwrap(); + assert_eq!(foo, new_foo); + } + + #[test] + fn from_reflect() { + let value = EnumValue::new("A", StructValue::default().with_field("a", 42)); + let foo = Foo::from_reflect(&value).unwrap(); + assert!(matches!(dbg!(foo), Foo::A { a: 42 })); + } + + #[test] + fn value_from_reflect() { + let foo = Foo::A { a: 42 }; + let value = EnumValue::from_reflect(&foo).unwrap(); + assert_eq!(get_field_on_variant!(value, a, i32), 42); + + let new_foo = Foo::from_reflect(&value).unwrap(); + assert_eq!(foo, new_foo); + } + + #[test] + fn value_field_mut() { + let mut value = EnumValue::new("A", StructValue::default().with_field("a", 42)); + value.variant_mut().field_mut("a").unwrap().patch(&1337); + assert_eq!(get_field_on_variant!(value, a, i32), 1337); + + let foo = Foo::from_reflect(&value).unwrap(); + assert!(matches!(dbg!(foo), Foo::A { a: 1337 })); + } + + #[test] + fn value_fields() { + let mut value = EnumValue::new("A", StructValue::default().with_field("a", 42)); + + for (name, value) in value.variant().fields() { + if name == "a" { + assert_eq!(value.downcast_ref::().unwrap(), &42); + } else { + panic!("unknown field on variant {name:?}"); + } + } + + for (name, value) in value.variant_mut().into_fields_mut() { + if name == "a" { + assert_eq!(value.downcast_ref::().unwrap(), &42); + } else { + panic!("unknown field on variant {name:?}"); + } + } + } + + #[test] + fn iterating_all_kinds_of_fields() { + let mut value = Foo::A { a: 42 }; + assert_eq!(value.variant().fields().count(), 1); + assert_eq!(value.variant_mut().into_fields_mut().count(), 1); + + let mut value = EnumValue::new("A", StructValue::default().with_field("a", 42)); + assert_eq!(value.variant().fields().count(), 1); + assert_eq!(value.variant_mut().into_fields_mut().count(), 1); + + let mut value = EnumValue::from_reflect(&(Foo::A { a: 42 })).unwrap(); + assert_eq!(value.variant().fields().count(), 1); + assert_eq!(value.variant_mut().into_fields_mut().count(), 1); + } + + #[test] + fn accessing_unknown_field() { + let foo = Foo::A { a: 42 }; + assert!(foo.variant().field("b").is_none()); + + let value = EnumValue::new("A", StructValue::default().with_field("a", 42)); + assert!(value.variant().field("b").is_none()); + } +} diff --git a/src/get_field.rs b/src/get_field.rs new file mode 100644 index 0000000..20ae88f --- /dev/null +++ b/src/get_field.rs @@ -0,0 +1,74 @@ +use crate::{Enum, Reflect, Struct}; + +pub trait GetField { + fn get_field(&self, name: &str) -> Option<&T> + where + T: Reflect; + + fn get_field_mut(&mut self, name: &str) -> Option<&mut T> + where + T: Reflect; +} + +impl GetField for K +where + K: Reflect, +{ + fn get_field(&self, name: &str) -> Option<&T> + where + T: Reflect, + { + if let Some(struct_) = self.as_struct() { + struct_.get_field(name) + } else if let Some(enum_) = self.as_enum() { + enum_.get_field(name) + } else { + None + } + } + + fn get_field_mut(&mut self, name: &str) -> Option<&mut T> + where + T: Reflect, + { + if self.as_struct_mut().is_some() { + self.as_struct_mut().unwrap().get_field_mut(name) + } else if self.as_enum_mut().is_some() { + self.as_enum_mut().unwrap().get_field_mut(name) + } else { + None + } + } +} + +impl GetField for dyn Struct { + fn get_field(&self, name: &str) -> Option<&T> + where + T: Reflect, + { + self.field(name)?.downcast_ref() + } + + fn get_field_mut(&mut self, name: &str) -> Option<&mut T> + where + T: Reflect, + { + self.field_mut(name)?.downcast_mut() + } +} + +impl GetField for dyn Enum { + fn get_field(&self, name: &str) -> Option<&T> + where + T: Reflect, + { + self.variant().field(name)?.downcast_ref() + } + + fn get_field_mut<'a, T>(&'a mut self, name: &str) -> Option<&'a mut T> + where + T: Reflect, + { + self.variant_mut().into_field_mut(name)?.downcast_mut() + } +} diff --git a/src/lib.rs b/src/lib.rs index 81652d7..2e28f19 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,37 +1,62 @@ -use std::{any::Any, collections::HashMap, fmt}; +#![deny(unreachable_pub)] +#![warn(clippy::todo)] -use serde::{Deserialize, Serialize}; -use speedy::{Readable, Writable}; +use std::{ + any::{Any, TypeId}, + fmt, +}; // TODO(david): // - tuple structs +// - unit structs +// - unit enum variants +// - tuple enum variants // - vec // - map -// - enums, including option and result // - modifying // - derive -#[cfg(test)] -mod tests; +pub mod enum_; +pub mod struct_; + +mod get_field; +mod value; + +pub use self::{ + enum_::{Enum, EnumValue}, + get_field::*, + struct_::{Struct, StructValue}, + value::*, +}; pub trait Reflect: Any + Send + 'static { 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 as_struct(&self) -> Option<&dyn Struct>; + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct>; + + fn as_enum(&self) -> Option<&dyn Enum>; + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum>; + fn patch(&mut self, value: &dyn Reflect); fn to_value(&self) -> Value; fn clone_reflect(&self) -> Box; - fn as_struct(&self) -> Option<&dyn Struct>; + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result; - fn as_struct_mut(&mut self) -> Option<&mut dyn Struct>; + fn type_id(&self) -> TypeId { + TypeId::of::() + } + + fn type_name(&self) -> &str { + std::any::type_name::() + } } impl dyn Reflect { @@ -50,6 +75,12 @@ impl dyn Reflect { } } +impl fmt::Debug for dyn Reflect { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.debug(f) + } +} + impl Reflect for Box { fn as_any(&self) -> &dyn Any { ::as_any(&**self) @@ -67,6 +98,22 @@ impl Reflect for Box { ::as_reflect_mut(&mut **self) } + fn as_struct(&self) -> Option<&dyn Struct> { + ::as_struct(&**self) + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + ::as_struct_mut(&mut **self) + } + + fn as_enum(&self) -> Option<&dyn Enum> { + ::as_enum(&**self) + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + ::as_enum_mut(&mut **self) + } + fn patch(&mut self, value: &dyn Reflect) { ::patch(&mut **self, value) } @@ -79,12 +126,8 @@ impl Reflect for Box { ::clone_reflect(&**self) } - fn as_struct(&self) -> Option<&dyn Struct> { - ::as_struct(&**self) - } - - fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { - ::as_struct_mut(&mut **self) + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::debug(&**self, f) } } @@ -129,6 +172,22 @@ macro_rules! impl_for_core_types { fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { None } + + fn as_enum(&self) -> Option<&dyn Enum> { + None + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + None + } + + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self) + } else { + write!(f, "{:?}", self) + } + } } impl FromReflect for $ty { @@ -150,325 +209,3 @@ impl_for_core_types! { pub trait FromReflect: Reflect + Sized { fn from_reflect(reflect: &dyn Reflect) -> Option; } - -pub trait Struct: Reflect { - fn field(&self, name: &str) -> Option<&dyn Reflect>; - - fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>; - - fn fields(&self) -> FieldsIter<'_>; - - fn fields_mut(&mut self) -> FieldsIterMut<'_>; -} - -pub struct FieldsIter<'a> { - iter: Box + 'a>, -} - -impl<'a> FieldsIter<'a> { - pub fn new(iter: I) -> Self - where - I: Iterator + 'a, - { - Self { - iter: Box::new(iter), - } - } -} - -impl<'a> Iterator for FieldsIter<'a> { - type Item = (&'a str, &'a dyn Reflect); - - fn next(&mut self) -> Option { - self.iter.next() - } -} - -pub struct FieldsIterMut<'a> { - iter: Box + 'a>, -} - -impl<'a> FieldsIterMut<'a> { - pub fn new(iter: I) -> Self - where - I: Iterator + 'a, - { - Self { - iter: Box::new(iter), - } - } -} - -impl<'a> Iterator for FieldsIterMut<'a> { - type Item = (&'a str, &'a mut dyn Reflect); - - fn next(&mut self) -> Option { - self.iter.next() - } -} - -#[derive(Readable, Writable, Serialize, Deserialize, Debug, Clone)] -pub struct StructValue { - fields: HashMap, -} - -impl StructValue { - pub fn builder() -> StructValueBuilder { - StructValueBuilder::default() - } -} - -impl Reflect for StructValue { - 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 patch(&mut self, value: &dyn Reflect) { - if let Some(struct_) = value.as_struct() { - for (name, value) in &mut self.fields { - if let Some(new_value) = struct_.field(name) { - value.patch(new_value); - } - } - } - } - - fn clone_reflect(&self) -> Box { - Box::new(self.clone()) - } - - fn to_value(&self) -> Value { - Value(ValueInner::StructValue(self.clone())) - } - - fn as_struct(&self) -> Option<&dyn Struct> { - Some(self) - } - - fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { - Some(self) - } -} - -impl Struct for StructValue { - fn field(&self, name: &str) -> Option<&dyn Reflect> { - Some(self.fields.get(name)?) - } - - fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> { - Some(self.fields.get_mut(name)?) - } - - fn fields(&self) -> FieldsIter<'_> { - let iter = self - .fields - .iter() - .map(|(key, value)| (&**key, value.as_reflect())); - FieldsIter::new(iter) - } - - fn fields_mut(&mut self) -> FieldsIterMut<'_> { - let iter = self - .fields - .iter_mut() - .map(|(key, value)| (&**key, value.as_reflect_mut())); - FieldsIterMut::new(iter) - } -} - -impl FromReflect for StructValue { - fn from_reflect(reflect: &dyn Reflect) -> Option { - let struct_ = reflect.as_struct()?; - let this = struct_ - .fields() - .fold(StructValue::builder(), |builder, (name, value)| { - builder.set(name, value.to_value()) - }); - Some(this.build()) - } -} - -#[derive(Default)] -pub struct StructValueBuilder { - fields: HashMap, -} - -impl StructValueBuilder { - pub fn set(mut self, name: impl Into, value: impl Into) -> Self { - self.fields.insert(name.into(), value.into()); - self - } - - pub fn build(self) -> StructValue { - StructValue { - fields: self.fields, - } - } -} - -#[derive(Readable, Writable, Serialize, Deserialize, Clone)] -pub struct Value(ValueInner); - -impl Reflect for Value { - fn as_any(&self) -> &dyn Any { - self.0.as_any() - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self.0.as_any_mut() - } - - fn as_reflect(&self) -> &dyn Reflect { - self.0.as_reflect() - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self.0.as_reflect_mut() - } - - fn patch(&mut self, value: &dyn Reflect) { - self.0.patch(value) - } - - fn clone_reflect(&self) -> Box { - Box::new(self.clone()) - } - - fn to_value(&self) -> Value { - self.clone() - } - - fn as_struct(&self) -> Option<&dyn Struct> { - self.0.as_struct() - } - - fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { - self.0.as_struct_mut() - } -} - -impl fmt::Debug for Value { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -macro_rules! value_inner { - ( - $(#[$m:meta])* - enum ValueInner { - $($ident:ident,)* - } - ) => { - $(#[$m])* - enum ValueInner { - $($ident($ident),)* - } - - impl Reflect for ValueInner { - fn as_any(&self) -> &dyn Any { - match self { - $( - Self::$ident(inner) => inner, - )* - } - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - match self { - $( - Self::$ident(inner) => inner, - )* - } - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn patch(&mut self, value: &dyn Reflect) { - match self { - $( - Self::$ident(inner) => { - if let Some(value) = value.downcast_ref::<$ident>() { - *inner = value.clone(); - } - }, - )* - } - } - - fn to_value(&self) -> Value { - Value(self.clone()) - } - - fn clone_reflect(&self) -> Box { - Box::new(self.clone()) - } - - fn as_struct(&self) -> Option<&dyn Struct> { - if let ValueInner::StructValue(value) = self { - Some(value) - } else { - None - } - } - - fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { - if let ValueInner::StructValue(value) = self { - Some(value) - } else { - None - } - } - } - - $( - impl From<$ident> for Value { - fn from(value: $ident) -> Self { - Self(ValueInner::$ident(value)) - } - } - )* - }; -} - -value_inner! { - #[allow(non_camel_case_types)] - #[derive(Readable, Writable, Serialize, Deserialize, Debug, Clone)] - enum ValueInner { - usize, - u8, - u16, - u32, - u64, - u128, - i8, - i16, - i32, - i64, - i128, - bool, - char, - f32, - f64, - String, - StructValue, - } -} diff --git a/src/struct_.rs b/src/struct_.rs new file mode 100644 index 0000000..e1b697b --- /dev/null +++ b/src/struct_.rs @@ -0,0 +1,399 @@ +use std::{any::Any, collections::HashMap, fmt}; + +use crate::{Enum, FromReflect, Reflect, Value, ValueInner}; +use serde::{Deserialize, Serialize}; +use speedy::{Readable, Writable}; + +pub trait Struct: Reflect { + fn field(&self, name: &str) -> Option<&dyn Reflect>; + fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>; + + fn fields(&self) -> StructFieldsIter<'_>; + fn fields_mut(&mut self) -> StructFieldsIterMut<'_>; +} + +pub struct StructFieldsIter<'a> { + iter: Box + 'a>, +} + +impl<'a> StructFieldsIter<'a> { + pub fn new(iter: I) -> Self + where + I: IntoIterator + 'a, + { + Self { + iter: Box::new(iter.into_iter()), + } + } +} + +impl<'a> Iterator for StructFieldsIter<'a> { + type Item = (&'a str, &'a dyn Reflect); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +pub struct StructFieldsIterMut<'a> { + iter: Box + 'a>, +} + +impl<'a> StructFieldsIterMut<'a> { + pub fn new(iter: I) -> Self + where + I: IntoIterator + 'a, + { + Self { + iter: Box::new(iter.into_iter()), + } + } +} + +impl<'a> Iterator for StructFieldsIterMut<'a> { + type Item = (&'a str, &'a mut dyn Reflect); + + fn next(&mut self) -> Option { + self.iter.next() + } +} + +#[derive(Default, Readable, Writable, Serialize, Deserialize, Debug, Clone)] +pub struct StructValue { + fields: HashMap, +} + +impl StructValue { + pub fn new() -> Self { + Self::default() + } + + pub fn with_field(mut self, name: impl Into, value: impl Into) -> Self { + self.fields.insert(name.into(), value.into()); + self + } +} + +impl Reflect for StructValue { + 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 as_struct(&self) -> Option<&dyn Struct> { + Some(self) + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + Some(self) + } + + fn as_enum(&self) -> Option<&dyn Enum> { + None + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + None + } + + fn patch(&mut self, value: &dyn Reflect) { + if let Some(struct_) = value.as_struct() { + for (name, value) in self.fields_mut() { + if let Some(new_value) = struct_.field(name) { + value.patch(new_value); + } + } + } + } + + fn to_value(&self) -> Value { + Value(ValueInner::StructValue(self.clone())) + } + + fn clone_reflect(&self) -> Box { + Box::new(self.clone()) + } + + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self) + } else { + write!(f, "{:?}", self) + } + } +} + +impl Struct for StructValue { + fn field(&self, name: &str) -> Option<&dyn Reflect> { + Some(self.fields.get(name)?) + } + + fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> { + Some(self.fields.get_mut(name)?) + } + + fn fields(&self) -> StructFieldsIter<'_> { + let iter = self + .fields + .iter() + .map(|(key, value)| (&**key, value.as_reflect())); + StructFieldsIter::new(iter) + } + + fn fields_mut(&mut self) -> StructFieldsIterMut<'_> { + let iter = self + .fields + .iter_mut() + .map(|(key, value)| (&**key, value.as_reflect_mut())); + StructFieldsIterMut::new(iter) + } +} + +impl FromReflect for StructValue { + fn from_reflect(reflect: &dyn Reflect) -> Option { + let struct_ = reflect.as_struct()?; + let this = struct_ + .fields() + .fold(StructValue::default(), |builder, (name, value)| { + builder.with_field(name, value.to_value()) + }); + Some(this) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Default, Clone, Eq, PartialEq, Debug)] + struct Foo { + field: i32, + } + + impl Reflect for Foo { + 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 patch(&mut self, value: &dyn Reflect) { + if let Some(value) = value.as_struct() { + if let Some(field) = value.field("field") { + self.field_mut("field").unwrap().patch(field); + } + } + } + + fn to_value(&self) -> Value { + StructValue::default() + .with_field("field", self.field) + .into() + } + + fn clone_reflect(&self) -> Box { + Box::new(self.clone()) + } + + fn as_struct(&self) -> Option<&dyn Struct> { + Some(self) + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + Some(self) + } + + fn as_enum(&self) -> Option<&dyn Enum> { + None + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + None + } + + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self) + } else { + write!(f, "{:?}", self) + } + } + } + + impl FromReflect for Foo { + fn from_reflect(reflect: &dyn Reflect) -> Option { + let struct_ = reflect.as_struct()?; + Some(Self { + field: struct_.field("field")?.downcast_ref::()?.to_owned(), + }) + } + } + + impl Struct for Foo { + fn field(&self, name: &str) -> Option<&dyn Reflect> { + if name == "field" { + return Some(&self.field); + } + + None + } + + fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> { + if name == "field" { + return Some(&mut self.field); + } + + None + } + + fn fields(&self) -> StructFieldsIter<'_> { + let iter = [("field", self.field.as_reflect())]; + StructFieldsIter::new(iter) + } + + fn fields_mut(&mut self) -> StructFieldsIterMut<'_> { + let iter = [("field", self.field.as_reflect_mut())]; + StructFieldsIterMut::new(iter) + } + } + + #[test] + fn accessing_fields() { + let foo = Foo { field: 42 }; + let struct_ = foo.as_struct().unwrap(); + + let value = struct_ + .field("field") + .unwrap() + .downcast_ref::() + .unwrap(); + + assert_eq!(*value, 42); + } + + #[test] + fn patching() { + let mut foo = Foo { field: 42 }; + + let patch = StructValue::default().with_field("field", 1337); + + foo.patch(&patch); + + assert_eq!(foo.field, 1337); + } + + #[test] + fn patching_struct_value() { + let mut value = StructValue::default().with_field("field", 42); + let patch = StructValue::default().with_field("field", 1337); + value.patch(&patch); + + assert_eq!( + value.field("field").unwrap().downcast_ref::().unwrap(), + &1337 + ); + } + + #[test] + fn from_reflect() { + let foo = Foo::default(); + let foo_reflect: &dyn Reflect = &foo; + + let foo = Foo::from_reflect(foo_reflect).unwrap(); + + assert_eq!(foo.field, 0); + } + + #[test] + fn serialize_deserialize() { + let foo = Foo::default(); + let struct_value = foo.to_value(); + + let json = serde_json::to_string(&struct_value).unwrap(); + + let struct_value = serde_json::from_str::(&json).unwrap(); + let foo = Foo::from_reflect(&struct_value).unwrap(); + + assert_eq!(foo.field, 0); + } + + #[test] + fn fields() { + let foo = Foo::default(); + + for (name, value) in foo.fields() { + if name == "field" { + assert_eq!(foo.field, i32::from_reflect(value).unwrap()); + } else { + panic!("Unknown field {name:?}"); + } + } + } + + #[test] + fn struct_value_from_reflect() { + let value = StructValue::default().with_field("foo", 42); + let reflect = value.as_reflect(); + + let value = StructValue::from_reflect(reflect).unwrap(); + + assert_eq!( + value.field("foo").unwrap().downcast_ref::().unwrap(), + &42, + ); + } + + #[test] + fn box_dyn_reflect_as_reflect() { + let foo = Foo::default(); + let mut box_dyn_reflect = Box::new(foo) as Box; + + assert_eq!( + box_dyn_reflect + .as_struct() + .unwrap() + .field("field") + .unwrap() + .downcast_ref::() + .unwrap(), + &0, + ); + + box_dyn_reflect.patch(&StructValue::default().with_field("field", 42)); + + assert_eq!( + box_dyn_reflect + .as_struct() + .unwrap() + .field("field") + .unwrap() + .downcast_ref::() + .unwrap(), + &42, + ); + + let foo = Foo::from_reflect(&box_dyn_reflect).unwrap(); + assert_eq!(foo, Foo { field: 42 }); + } +} diff --git a/src/tests.rs b/src/tests.rs deleted file mode 100644 index 0933037..0000000 --- a/src/tests.rs +++ /dev/null @@ -1,209 +0,0 @@ -use std::any::Any; - -use crate::{FieldsIter, FieldsIterMut, FromReflect, Reflect, Struct, StructValue, Value}; - -#[derive(Default, Clone, Eq, PartialEq, Debug)] -struct Foo { - field: i32, -} - -impl Reflect for Foo { - 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 patch(&mut self, value: &dyn Reflect) { - if let Some(value) = value.as_struct() { - if let Some(field) = value.field("field") { - self.field_mut("field").unwrap().patch(field); - } - } - } - - fn clone_reflect(&self) -> Box { - Box::new(self.clone()) - } - - fn to_value(&self) -> Value { - StructValue::builder() - .set("field", self.field) - .build() - .to_value() - } - - fn as_struct(&self) -> Option<&dyn Struct> { - Some(self) - } - - fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { - Some(self) - } -} - -impl FromReflect for Foo { - fn from_reflect(reflect: &dyn Reflect) -> Option { - let struct_ = reflect.as_struct()?; - Some(Self { - field: struct_.field("field")?.downcast_ref::()?.to_owned(), - }) - } -} - -impl Struct for Foo { - fn field(&self, name: &str) -> Option<&dyn Reflect> { - if name == "field" { - return Some(&self.field); - } - - None - } - - fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> { - if name == "field" { - return Some(&mut self.field); - } - - None - } - - fn fields(&self) -> FieldsIter<'_> { - let iter = std::iter::once(("field", self.field.as_reflect())); - FieldsIter::new(iter) - } - - fn fields_mut(&mut self) -> FieldsIterMut<'_> { - let iter = std::iter::once(("field", self.field.as_reflect_mut())); - FieldsIterMut::new(iter) - } -} - -#[test] -fn accessing_fields() { - let foo = Foo { field: 42 }; - let struct_: &dyn Struct = foo.as_struct().unwrap(); - - let value = struct_ - .field("field") - .unwrap() - .downcast_ref::() - .unwrap(); - - assert_eq!(*value, 42); -} - -#[test] -fn patching() { - let mut foo = Foo { field: 42 }; - - let patch = StructValue::builder().set("field", 1337).build(); - - foo.patch(&patch); - - assert_eq!(foo.field, 1337); -} - -#[test] -fn patching_struct_value() { - let mut value = StructValue::builder().set("field", 42).build(); - let patch = StructValue::builder().set("field", 1337).build(); - value.patch(&patch); - - assert_eq!( - value.field("field").unwrap().downcast_ref::().unwrap(), - &1337 - ); -} - -#[test] -fn from_reflect() { - let foo = Foo::default(); - let foo_reflect: &dyn Reflect = &foo; - - let foo = Foo::from_reflect(foo_reflect).unwrap(); - - assert_eq!(foo.field, 0); -} - -#[test] -fn serialize_deserialize() { - let foo = Foo::default(); - let struct_value = foo.to_value(); - - let json = serde_json::to_string(&struct_value).unwrap(); - - let struct_value = serde_json::from_str::(&json).unwrap(); - let foo = Foo::from_reflect(&struct_value).unwrap(); - - assert_eq!(foo.field, 0); -} - -#[test] -fn fields() { - let foo = Foo::default(); - - for (name, value) in foo.fields() { - if name == "field" { - assert_eq!(foo.field, i32::from_reflect(value).unwrap()); - } else { - panic!("Unknown field {name:?}"); - } - } -} - -#[test] -fn struct_value_from_reflect() { - let value = StructValue::builder().set("foo", 42).build(); - let reflect = value.as_reflect(); - - let value = StructValue::from_reflect(reflect).unwrap(); - - assert_eq!( - value.field("foo").unwrap().downcast_ref::().unwrap(), - &42, - ); -} - -#[test] -fn box_dyn_reflect_as_reflect() { - let foo = Foo::default(); - let mut box_dyn_reflect = Box::new(foo) as Box; - - assert_eq!( - box_dyn_reflect - .as_struct() - .unwrap() - .field("field") - .unwrap() - .downcast_ref::() - .unwrap(), - &0, - ); - - box_dyn_reflect.patch(&StructValue::builder().set("field", 42).build()); - - assert_eq!( - box_dyn_reflect - .as_struct() - .unwrap() - .field("field") - .unwrap() - .downcast_ref::() - .unwrap(), - &42, - ); - - let foo = Foo::from_reflect(&box_dyn_reflect).unwrap(); - assert_eq!(foo, Foo { field: 42 }); -} diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000..8e4d74c --- /dev/null +++ b/src/value.rs @@ -0,0 +1,201 @@ +use serde::{Deserialize, Serialize}; +use speedy::{Readable, Writable}; +use std::{any::Any, fmt}; + +use crate::{Enum, EnumValue, Reflect, Struct, StructValue}; + +#[derive(Readable, Writable, Serialize, Deserialize, Clone)] +pub struct Value(pub(crate) ValueInner); + +impl Reflect for Value { + fn as_any(&self) -> &dyn Any { + self.0.as_any() + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self.0.as_any_mut() + } + + fn as_reflect(&self) -> &dyn Reflect { + self.0.as_reflect() + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self.0.as_reflect_mut() + } + + fn patch(&mut self, value: &dyn Reflect) { + self.0.patch(value) + } + + fn clone_reflect(&self) -> Box { + Box::new(self.clone()) + } + + fn to_value(&self) -> Value { + self.clone() + } + + fn as_struct(&self) -> Option<&dyn Struct> { + self.0.as_struct() + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + self.0.as_struct_mut() + } + + fn as_enum(&self) -> Option<&dyn Enum> { + self.0.as_enum() + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + self.0.as_enum_mut() + } + + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self) + } else { + write!(f, "{:?}", self) + } + } +} + +impl fmt::Debug for Value { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +macro_rules! value_inner { + ( + $(#[$m:meta])* + pub(crate) enum ValueInner { + $($ident:ident,)* + } + ) => { + $(#[$m])* + pub(crate) enum ValueInner { + $($ident($ident),)* + } + + impl Reflect for ValueInner { + fn as_any(&self) -> &dyn Any { + match self { + $( + Self::$ident(inner) => inner, + )* + } + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + match self { + $( + Self::$ident(inner) => inner, + )* + } + } + + fn as_reflect(&self) -> &dyn Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self + } + + fn patch(&mut self, value: &dyn Reflect) { + match self { + $( + Self::$ident(inner) => { + if let Some(value) = value.downcast_ref::<$ident>() { + *inner = value.clone(); + } + }, + )* + } + } + + fn to_value(&self) -> Value { + Value(self.clone()) + } + + fn clone_reflect(&self) -> Box { + Box::new(self.clone()) + } + + fn as_struct(&self) -> Option<&dyn Struct> { + if let ValueInner::StructValue(value) = self { + Some(value) + } else { + None + } + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + if let ValueInner::StructValue(value) = self { + Some(value) + } else { + None + } + } + + fn as_enum(&self) -> Option<&dyn Enum> { + if let ValueInner::EnumValue(value) = self { + Some(value) + } else { + None + } + } + + fn as_enum_mut(&mut self) -> Option<&mut dyn Enum> { + if let ValueInner::EnumValue(value) = self { + Some(value) + } else { + None + } + } + + fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if f.alternate() { + write!(f, "{:#?}", self) + } else { + write!(f, "{:?}", self) + } + } + } + + $( + impl From<$ident> for Value { + fn from(value: $ident) -> Self { + Self(ValueInner::$ident(value)) + } + } + )* + }; +} + +value_inner! { + #[allow(non_camel_case_types)] + #[derive(Readable, Writable, Serialize, Deserialize, Debug, Clone)] + pub(crate) enum ValueInner { + usize, + u8, + u16, + u32, + u64, + u128, + i8, + i16, + i32, + i64, + i128, + bool, + char, + f32, + f64, + String, + StructValue, + EnumValue, + } +}