use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::error::Error;
use std::fmt::Debug;
use std::sync::LazyLock;
use serde_flexitos::ser::require_erased_serialize_impl;
use serde_flexitos::{serialize_trait_object, MapRegistry, Registry};
pub trait Example1Obj: erased_serde::Serialize + Debug {
fn id(&self) -> &'static str;
}
pub trait Example2Obj: erased_serde::Serialize + Debug {
fn id(&self) -> &'static str;
}
#[derive(Clone, Serialize, Deserialize, Debug)]
struct Foo(String);
impl Foo {
const ID: &'static str = "Foo";
}
impl Example1Obj for Foo {
fn id(&self) -> &'static str { Self::ID }
}
impl Example2Obj for Foo {
fn id(&self) -> &'static str { Self::ID }
}
#[derive(Clone, Serialize, Deserialize, Debug)]
struct Bar(usize);
impl Bar {
const ID: &'static str = "Bar";
}
impl Example1Obj for Bar {
fn id(&self) -> &'static str { Self::ID }
}
impl Example2Obj for Bar {
fn id(&self) -> &'static str { Self::ID }
}
static EXAMPLE_1_OBJ_REGISTRY: LazyLock<MapRegistry<dyn Example1Obj>> = LazyLock::new(|| {
let mut registry = MapRegistry::<dyn Example1Obj>::new("Example1Obj");
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
});
static EXAMPLE_2_OBJ_REGISTRY: LazyLock<MapRegistry<dyn Example2Obj>> = LazyLock::new(|| {
let mut registry = MapRegistry::<dyn Example2Obj>::new("Example2Obj");
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 Example1Obj + 'a {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
const fn __check_erased_serialize_supertrait<T: ?Sized + Example1Obj>() {
require_erased_serialize_impl::<T>();
}
serialize_trait_object(serializer, self.id(), self)
}
}
impl<'de> Deserialize<'de> for Box<dyn Example1Obj> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
EXAMPLE_1_OBJ_REGISTRY.deserialize_trait_object(deserializer)
}
}
impl<'a> Serialize for dyn Example2Obj + 'a {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
const fn __check_erased_serialize_supertrait<T: ?Sized + Example2Obj>() {
require_erased_serialize_impl::<T>();
}
serialize_trait_object(serializer, self.id(), self)
}
}
impl<'de> Deserialize<'de> for Box<dyn Example2Obj> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
EXAMPLE_2_OBJ_REGISTRY.deserialize_trait_object(deserializer)
}
}
#[derive(Debug, Serialize, Deserialize)]
struct Combined {
example_1_obj: Box<dyn Example1Obj>,
example_2_obj: Box<dyn Example2Obj>,
}
impl Combined {
pub fn new(example_1_obj: impl Example1Obj + 'static, example_2_obj: impl Example2Obj + 'static) -> Self {
Self { example_1_obj: Box::new(example_1_obj), example_2_obj: Box::new(example_2_obj) }
}
}
fn main() -> Result<(), Box<dyn Error>> {
{
let json = serde_json::to_string(&Combined::new(Foo("A".to_string()), Bar(0)))?;
println!("`Combined` serialized: {}", json);
let roundtrip: Combined = serde_json::from_str(&json)?;
println!("`Combined` deserialized: {:?}", roundtrip);
}
{
let json = serde_json::to_string(&Combined::new(Bar(1337), Foo("asd".to_string())))?;
println!("`Combined` serialized: {}", json);
let roundtrip: Combined = serde_json::from_str(&json)?;
println!("`Combined` deserialized: {:?}", roundtrip);
}
Ok(())
}