use std::error::Error; use std::fmt::Debug; use once_cell::sync::Lazy; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::ser::{SerializeMap, SerializeTupleStruct}; use serde_flexitos::{deserialize_trait_object, Registry, serialize_trait_object}; use serde_flexitos::id::{Id, IdObj}; /// Object-safe example trait. pub trait Example: erased_serde::Serialize + IdObj + Debug {} /// Example implementation that returns a constant. #[derive(Debug)] pub struct Constant(pub T); impl Example for Constant {} impl Id for Constant { // TODO: this impl does not actually depend on T, but it must be included, meaning we can only get the ID if we // provide a generic type argument... const ID: &'static str = "Constant"; } // Hand-written serialize implementation for Constant. impl Serialize for Constant { fn serialize(&self, serializer: S) -> Result { struct IdValue<'a, T: Serialize + Id>(&'a T); impl<'a, T: Serialize + Id> Serialize for IdValue<'a, T> { fn serialize(&self, serializer: S) -> Result { let mut map = serializer.serialize_map(Some(1))?; map.serialize_entry(T::ID, self.0)?; // Serialize (ID, value) pair. map.end() } } let mut ts = serializer.serialize_tuple_struct("Constant", 1)?; ts.serialize_field(&IdValue(&self.0))?; ts.end() } } static EXAMPLE_REGISTRY: Lazy> = Lazy::new(|| { let mut registry = Registry::::new("Example"); // TODO: the hard part, register a deserializer that can handle Constant generically. //registry.register(Constant::ID, |d| Ok(Box::new(erased_serde::deserialize::>(d)?))); registry }); impl Serialize for dyn Example { fn serialize(&self, serializer: S) -> Result { serialize_trait_object(serializer, self.id(), self) } } impl<'de> Deserialize<'de> for Box { fn deserialize>(deserializer: D) -> Result { deserialize_trait_object(deserializer, &EXAMPLE_REGISTRY) } } // Run serialization roundtrips fn main() -> Result<(), Box> { let constant_bool = Constant(true); { // `Box` serialization roundtrip let example: Box = Box::new(constant_bool); let json = serde_json::to_string(&example)?; println!("`Box` serialized: {}", json); let roundtrip: Box = serde_json::from_str(&json)?; println!("`Box` deserialized: {:?}", roundtrip); } Ok(()) }