use crate::{ Properties, Property, PropertyIter, PropertyTypeRegistration, PropertyTypeRegistry, PropertyVal, }; use serde::{ de::{self, DeserializeSeed, MapAccess, Visitor}, ser::SerializeMap, Serialize, }; use std::{any::Any, borrow::Cow, cell::RefCell, collections::HashMap, rc::Rc}; #[derive(Default)] pub struct DynamicProperties { pub type_name: String, pub props: Vec<(Cow<'static, str>, Box)>, pub prop_indices: HashMap, usize>, } impl DynamicProperties { fn push(&mut self, name: &str, prop: Box) { let name: Cow<'static, str> = Cow::Owned(name.to_string()); self.props.push((name.clone(), prop)); self.prop_indices.insert(name, self.props.len()); } pub fn set(&mut self, name: &str, prop: T) { if let Some(index) = self.prop_indices.get(name) { self.props[*index].1 = Box::new(prop); } else { self.push(name, Box::new(prop)); } } pub fn set_box(&mut self, name: &str, prop: Box) { if let Some(index) = self.prop_indices.get(name) { self.props[*index].1 = prop; } else { self.push(name, prop); } } } impl Properties for DynamicProperties { #[inline] fn type_name(&self) -> &str { &self.type_name } #[inline] fn prop(&self, name: &str) -> Option<&dyn Property> { if let Some(index) = self.prop_indices.get(name) { Some(&*self.props[*index].1) } else { None } } #[inline] fn prop_mut(&mut self, name: &str) -> Option<&mut dyn Property> { if let Some(index) = self.prop_indices.get(name) { Some(&mut *self.props[*index].1) } else { None } } #[inline] fn prop_with_index(&self, index: usize) -> Option<&dyn Property> { self.props.get(index).map(|(_i, prop)| &**prop) } #[inline] fn prop_with_index_mut(&mut self, index: usize) -> Option<&mut dyn Property> { self.props.get_mut(index).map(|(_i, prop)| &mut **prop) } #[inline] fn prop_name(&self, index: usize) -> Option<&str> { self.props.get(index).map(|(name, _)| name.as_ref()) } #[inline] fn prop_len(&self) -> usize { self.props.len() } fn iter_props(&self) -> PropertyIter { PropertyIter { props: self, index: 0, } } } impl Serialize for DynamicProperties { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { let mut state = serializer.serialize_map(Some(self.props.len()))?; state.serialize_entry("type", self.type_name())?; for (name, prop) in self.iter_props() { state.serialize_entry(name, prop)?; } state.end() } } pub struct DynamicPropertiesDeserializer<'a> { pub property_type_registry: &'a PropertyTypeRegistry, pub current_type_name: Rc>>, } impl<'a, 'de> DeserializeSeed<'de> for DynamicPropertiesDeserializer<'a> { type Value = DynamicProperties; fn deserialize(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { let mut dynamic_properties = DynamicProperties::default(); deserializer.deserialize_map(PropMapVisiter { dynamic_properties: &mut dynamic_properties, property_type_registry: self.property_type_registry, current_type_name: self.current_type_name, })?; Ok(dynamic_properties) } } struct PropMapVisiter<'a> { dynamic_properties: &'a mut DynamicProperties, property_type_registry: &'a PropertyTypeRegistry, current_type_name: Rc>>, } impl<'a, 'de> Visitor<'de> for PropMapVisiter<'a> { type Value = (); fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("map of properties") } fn visit_map(self, mut map: V) -> Result<(), V::Error> where V: MapAccess<'de>, { let mut type_name: Option = None; while let Some(key) = map.next_key::()? { if &key == "type" { type_name = Some(map.next_value()?); } else { let prop = map.next_value_seed(MapValueDeserializer { property_type_registry: self.property_type_registry, current_type_name: self.current_type_name.clone(), })?; self.dynamic_properties.set_box(&key, prop); } } let type_name = type_name.ok_or_else(|| de::Error::missing_field("type"))?; self.dynamic_properties.type_name = type_name.to_string(); Ok(()) } } pub struct MapValueDeserializer<'a> { property_type_registry: &'a PropertyTypeRegistry, current_type_name: Rc>>, } impl<'a, 'de> DeserializeSeed<'de> for MapValueDeserializer<'a> { type Value = Box; fn deserialize(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { if self.current_type_name.borrow().is_some() { let registration = { let current_type_name= self.current_type_name.borrow(); let type_name = current_type_name.as_ref().unwrap(); self .property_type_registry .get(type_name) .ok_or_else(|| { de::Error::custom(format!( "TypeRegistration is missing for {}", type_name )) })? }; let mut erased = erased_serde::Deserializer::erase(deserializer); let res = (registration.deserialize)(&mut erased) .map_err(<>::Error as serde::de::Error>::custom); res } else { deserializer.deserialize_any(AnyPropVisiter { property_type_registry: self.property_type_registry, current_type_name: self.current_type_name, }) } } } struct AnyPropVisiter<'a> { property_type_registry: &'a PropertyTypeRegistry, current_type_name: Rc>>, } impl<'a, 'de> Visitor<'de> for AnyPropVisiter<'a> { type Value = Box; fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_str("property value") } fn visit_u8(self, v: u8) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_u16(self, v: u16) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_u32(self, v: u32) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_u64(self, v: u64) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_i8(self, v: i8) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_i16(self, v: i16) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_i32(self, v: i32) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_i64(self, v: i64) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_f32(self, v: f32) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_f64(self, v: f64) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_string(self, v: String) -> Result where E: de::Error, { Ok(Box::new(v)) } fn visit_str(self, v: &str) -> Result where E: de::Error, { Ok(Box::new(v.to_string())) } fn visit_map(self, mut map: V) -> Result where V: MapAccess<'de>, { let mut dynamic_properties = DynamicProperties::default(); while let Some(key) = map.next_key()? { let prop = map.next_value_seed(MapValueDeserializer { property_type_registry: self.property_type_registry, current_type_name: self.current_type_name.clone(), })?; if key == "type" { dynamic_properties.type_name = prop .val::() .map(|s| s.clone()) .ok_or_else(|| de::Error::custom("type must be a string"))?; } else { dynamic_properties.set_box(key, prop); } } Ok(Box::new(dynamic_properties)) } } struct PropertyTypeDeserializer<'a> { registration: &'a PropertyTypeRegistration, } impl<'a, 'de> DeserializeSeed<'de> for PropertyTypeDeserializer<'a> { type Value = Box; fn deserialize(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { let mut erased = erased_serde::Deserializer::erase(deserializer); (self.registration.deserialize)(&mut erased) .map_err(<>::Error as serde::de::Error>::custom) } } impl Property for DynamicProperties { #[inline] fn any(&self) -> &dyn Any { self } #[inline] fn any_mut(&mut self) -> &mut dyn Any { self } #[inline] fn clone_prop(&self) -> Box { Box::new(self.to_dynamic()) } #[inline] fn set(&mut self, value: &dyn Property) { if let Some(properties) = value.as_properties() { *self = properties.to_dynamic(); } else { panic!("attempted to apply non-Properties type to Properties type"); } } #[inline] fn apply(&mut self, value: &dyn Property) { if let Some(properties) = value.as_properties() { for (name, prop) in properties.iter_props() { self.prop_mut(name).map(|p| p.apply(prop)); } } else { panic!("attempted to apply non-Properties type to Properties type"); } } fn as_properties(&self) -> Option<&dyn Properties> { Some(self) } }