diff --git a/src/lib.rs b/src/lib.rs index 63cf030..81652d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,14 @@ use std::{any::Any, collections::HashMap, fmt}; use serde::{Deserialize, Serialize}; use speedy::{Readable, Writable}; +// TODO(david): +// - tuple structs +// - vec +// - map +// - enums, including option and result +// - modifying +// - derive + #[cfg(test)] mod tests; @@ -17,13 +25,13 @@ pub trait Reflect: Any + Send + 'static { fn patch(&mut self, value: &dyn Reflect); - fn as_struct(&self) -> Option<&dyn Struct> { - None - } + fn to_value(&self) -> Value; - fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { - None - } + fn clone_reflect(&self) -> Box; + + fn as_struct(&self) -> Option<&dyn Struct>; + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct>; } impl dyn Reflect { @@ -42,6 +50,44 @@ impl dyn Reflect { } } +impl Reflect for Box { + fn as_any(&self) -> &dyn Any { + ::as_any(&**self) + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + ::as_any_mut(&mut **self) + } + + fn as_reflect(&self) -> &dyn Reflect { + ::as_reflect(&**self) + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + ::as_reflect_mut(&mut **self) + } + + fn patch(&mut self, value: &dyn Reflect) { + ::patch(&mut **self, value) + } + + fn to_value(&self) -> Value { + ::to_value(&**self) + } + + fn clone_reflect(&self) -> 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) + } +} + macro_rules! impl_for_core_types { ($($ty:ident)*) => { $( @@ -64,24 +110,32 @@ macro_rules! impl_for_core_types { fn patch(&mut self, value: &dyn Reflect) { if let Some(value) = value.as_any().downcast_ref::() { - *self = value.to_owned(); + *self = value.clone(); } } - } - impl FromReflect for $ty { - fn from_reflect(reflect: &dyn Reflect) -> Option { - Some(reflect.downcast_ref::<$ty>()?.to_owned()) + fn clone_reflect(&self) -> Box { + Box::new(self.clone()) } - } - impl IntoValue for $ty { - fn into_value(self) -> Value { - Value(ValueInner::$ty(self)) + fn to_value(&self) -> Value { + Value::from(self.to_owned()) + } + + fn as_struct(&self) -> Option<&dyn Struct> { + None + } + + fn as_struct_mut(&mut self) -> Option<&mut dyn Struct> { + None } } - impl private::Sealed for $ty {} + impl FromReflect for $ty { + fn from_reflect(reflect: &dyn Reflect) -> Option { + Some(reflect.downcast_ref::<$ty>()?.clone()) + } + } )* }; } @@ -102,8 +156,6 @@ pub trait Struct: Reflect { fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>; - fn into_value(self) -> StructValue; - fn fields(&self) -> FieldsIter<'_>; fn fields_mut(&mut self) -> FieldsIterMut<'_>; @@ -193,6 +245,14 @@ impl Reflect for StructValue { } } + 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) } @@ -211,10 +271,6 @@ impl Struct for StructValue { Some(self.fields.get_mut(name)?) } - fn into_value(self) -> StructValue { - self - } - fn fields(&self) -> FieldsIter<'_> { let iter = self .fields @@ -232,14 +288,26 @@ impl Struct for StructValue { } } +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 IntoValue) -> Self { - self.fields.insert(name.into(), value.into_value()); + pub fn set(mut self, name: impl Into, value: impl Into) -> Self { + self.fields.insert(name.into(), value.into()); self } @@ -270,10 +338,25 @@ impl Reflect for Value { self.0.as_reflect_mut() } - #[allow(warnings)] 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 { @@ -324,13 +407,45 @@ macro_rules! value_inner { $( Self::$ident(inner) => { if let Some(value) = value.downcast_ref::<$ident>() { - *inner = value.to_owned(); + *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)) + } + } + )* }; } @@ -357,19 +472,3 @@ value_inner! { StructValue, } } - -mod private { - pub trait Sealed {} -} - -pub trait IntoValue: private::Sealed { - fn into_value(self) -> Value; -} - -impl IntoValue for StructValue { - fn into_value(self) -> Value { - Value(ValueInner::StructValue(self)) - } -} - -impl private::Sealed for StructValue {} diff --git a/src/tests.rs b/src/tests.rs index 7a10e24..0933037 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,8 +1,8 @@ use std::any::Any; -use crate::{FieldsIter, FieldsIterMut, FromReflect, Reflect, Struct, StructValue}; +use crate::{FieldsIter, FieldsIterMut, FromReflect, Reflect, Struct, StructValue, Value}; -#[derive(Default)] +#[derive(Default, Clone, Eq, PartialEq, Debug)] struct Foo { field: i32, } @@ -32,6 +32,17 @@ impl Reflect for Foo { } } + 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) } @@ -67,10 +78,6 @@ impl Struct for Foo { None } - fn into_value(self) -> StructValue { - StructValue::builder().set("field", self.field).build() - } - fn fields(&self) -> FieldsIter<'_> { let iter = std::iter::once(("field", self.field.as_reflect())); FieldsIter::new(iter) @@ -119,11 +126,6 @@ fn patching_struct_value() { ); } -// #[test] -// fn patching_value() { -// todo!() -// } - #[test] fn from_reflect() { let foo = Foo::default(); @@ -137,11 +139,11 @@ fn from_reflect() { #[test] fn serialize_deserialize() { let foo = Foo::default(); - let struct_value = foo.into_value(); + 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 struct_value = serde_json::from_str::(&json).unwrap(); let foo = Foo::from_reflect(&struct_value).unwrap(); assert_eq!(foo.field, 0); @@ -159,3 +161,49 @@ fn fields() { } } } + +#[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 }); +}