use std::collections::HashMap;
use std::error::Error;
use std::fmt::Debug;
use std::sync::LazyLock;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::DeserializeOwned;
use serde_flexitos::{MapRegistry, Registry, serialize_trait_object};
use serde_flexitos::ser::require_erased_serialize_impl;
pub trait Example: Serialize + DeserializeOwned + Debug {
const ID: &'static str;
}
pub trait ExampleObj: erased_serde::Serialize + Debug {
fn id(&self) -> &'static str;
}
impl<T: Example> ExampleObj for T {
fn id(&self) -> &'static str {
T::ID
}
}
#[derive(Clone, Serialize, Deserialize, Debug)]
struct Foo(String);
impl Example for Foo {
const ID: &'static str = "Foo";
}
#[derive(Clone, Serialize, Deserialize, Debug)]
struct Bar(usize);
impl Example for Bar {
const ID: &'static str = "Bar";
}
static EXAMPLE_OBJ_REGISTRY: LazyLock<MapRegistry<dyn ExampleObj>> = LazyLock::new(|| {
let mut registry = MapRegistry::<dyn ExampleObj>::new("ExampleObj");
registry.register(Foo::ID, |d| Ok(Box::new(erased_serde::deserialize::<Foo>(d)?)));
registry.register(Bar::ID, |d| Ok(Box::new(erased_serde::deserialize::<Bar>(d)?)));
registry
});
impl<'a> Serialize for dyn ExampleObj + 'a {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
const fn __check_erased_serialize_supertrait<T: ?Sized + ExampleObj>() {
require_erased_serialize_impl::<T>();
}
serialize_trait_object(serializer, self.id(), self)
}
}
impl<'de> Deserialize<'de> for Box<dyn ExampleObj> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
EXAMPLE_OBJ_REGISTRY.deserialize_trait_object(deserializer)
}
}
fn main() -> Result<(), Box<dyn Error>> {
let foo = Foo("A".to_string());
let bar = Bar(0);
{ let json = serde_json::to_string(&foo)?;
println!("`Foo` serialized: {}", json);
let roundtrip: Foo = serde_json::from_str(&json)?;
println!("`Foo` deserialized: {:?}", roundtrip);
}
{ let example: Box<dyn ExampleObj> = Box::new(foo.clone());
let json = serde_json::to_string(&example)?;
println!("`Box<dyn ExampleObj>` serialized: {}", json);
let roundtrip: Box<dyn ExampleObj> = serde_json::from_str(&json)?;
println!("`Box<dyn ExampleObj>` deserialized: {:?}", roundtrip);
}
{ let examples: Vec<Box<dyn ExampleObj>> = vec![Box::new(foo.clone()), Box::new(bar.clone())];
let json = serde_json::to_string(&examples)?;
println!("`Vec<Box<dyn ExampleObj>>` serialized: {}", json);
let roundtrip: Vec<Box<dyn ExampleObj>> = serde_json::from_str(&json)?;
println!("`Vec<Box<dyn ExampleObj>>` deserialized: {:?}", roundtrip);
}
{ let mut examples = HashMap::<String, Box<dyn ExampleObj>>::new();
examples.insert("foo".to_string(), Box::new(foo.clone()));
examples.insert("bar".to_string(), Box::new(bar.clone()));
let json = serde_json::to_string(&examples)?;
println!("`HashMap<String, Box<dyn ExampleObj>>` serialized: {}", json);
let roundtrip: HashMap::<String, Box<dyn ExampleObj>> = serde_json::from_str(&json)?;
println!("`HashMap<String, Box<dyn ExampleObj>>` deserialized: {:?}", roundtrip);
}
Ok(())
}