use std::collections::HashMap;
use std::fmt::{self, Debug, Display, Formatter};
use std::hash::Hash;
use std::marker::PhantomData;
use serde::de::{self, Deserializer, DeserializeSeed, MapAccess, SeqAccess, Visitor};
use serde::Deserialize;
use crate::{DeserializeFn, Registry};
#[repr(transparent)]
pub struct DeserializeTraitObject<'r, R>(pub &'r R);
impl<'de, R: Registry> DeserializeSeed<'de> for DeserializeTraitObject<'_, R> where
R::Identifier: Deserialize<'de> + Debug,
{
type Value = Box<R::TraitObject>;
#[inline]
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
deserializer.deserialize_map(self)
}
}
impl<'de, R: Registry> Visitor<'de> for DeserializeTraitObject<'_, R> where
R::Identifier: Deserialize<'de> + Debug,
{
type Value = Box<R::TraitObject>;
#[inline]
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "an id-value pair for `Box<dyn {}>`", self.0.get_trait_object_name())
}
#[inline]
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
let Some(deserialize_fn) = map.next_key_seed(IdToDeserializeFn(self.0))? else {
return Err(de::Error::custom(&self));
};
map.next_value_seed(DeserializeWithFn(deserialize_fn))
}
}
impl<R> Copy for DeserializeTraitObject<'_, R> {}
impl<R> Clone for DeserializeTraitObject<'_, R> {
#[inline]
fn clone(&self) -> Self { *self }
}
impl<'de, R: Registry> Display for DeserializeTraitObject<'_, R> where
R::Identifier: Deserialize<'de> + Debug,
{
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.expecting(f) }
}
#[repr(transparent)]
struct IdToDeserializeFn<'r, R>(&'r R);
impl<'de, R: Registry> DeserializeSeed<'de> for IdToDeserializeFn<'_, R> where
R::Identifier: Deserialize<'de> + Debug,
{
type Value = DeserializeFn<R::TraitObject>;
#[inline]
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
let id = R::Identifier::deserialize(deserializer)?;
self.0.get_deserialize_fn(id).copied().map_err(|e| de::Error::custom(e))
}
}
#[repr(transparent)]
pub(crate) struct DeserializeWithFn<O: ?Sized>(pub DeserializeFn<O>);
impl<'de, O: ?Sized> DeserializeSeed<'de> for DeserializeWithFn<O> {
type Value = Box<O>;
#[inline]
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
let mut erased = <dyn erased_serde::Deserializer>::erase(deserializer);
self.0(&mut erased).map_err(de::Error::custom)
}
}
#[repr(transparent)]
pub struct DeserializeVecWithTraitObject<'r, R>(pub &'r R);
impl<'de, R: Registry> DeserializeSeed<'de> for DeserializeVecWithTraitObject<'_, R> where
R::Identifier: Deserialize<'de> + Debug,
{
type Value = Vec<Box<R::TraitObject>>;
#[inline]
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
deserializer.deserialize_seq(self)
}
}
impl<'de, R: Registry> Visitor<'de> for DeserializeVecWithTraitObject<'_, R> where
R::Identifier: Deserialize<'de> + Debug,
{
type Value = Vec<Box<R::TraitObject>>;
#[inline]
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a sequence of '")?;
DeserializeTraitObject(self.0).expecting(formatter)?;
formatter.write_str("'")
}
#[inline]
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut vec = if let Some(capacity) = seq.size_hint() {
Vec::with_capacity(capacity)
} else {
Vec::new()
};
while let Some(trait_object) = seq.next_element_seed(DeserializeTraitObject(self.0))? {
vec.push(trait_object);
}
Ok(vec)
}
}
pub struct DeserializeMapWith<K, V> {
key_deserialize_seed: K,
value_deserialize_seed: V,
}
impl<'k, K, V, R> DeserializeMapWith<DeserializeTraitObject<'k, R>, PhantomData<V>> where
K: Eq + Hash + ?Sized,
R: Registry<TraitObject=K>
{
#[inline]
pub fn trait_object_key(registry: &'k R) -> Self {
Self {
key_deserialize_seed: DeserializeTraitObject(registry),
value_deserialize_seed: PhantomData::default(),
}
}
}
impl<'v, K, V, R> DeserializeMapWith<PhantomData<K>, DeserializeTraitObject<'v, R>> where
K: Eq + Hash,
V: ?Sized,
R: Registry<TraitObject=V>
{
#[inline]
pub fn trait_object_value(registry: &'v R) -> Self {
Self {
key_deserialize_seed: PhantomData::default(),
value_deserialize_seed: DeserializeTraitObject(registry),
}
}
}
impl<'k, 'v, K, RK, V, RV> DeserializeMapWith<DeserializeTraitObject<'k, RK>, DeserializeTraitObject<'v, RV>> where
K: Eq + Hash + ?Sized,
V: ?Sized,
RK: Registry<TraitObject=K>,
RV: Registry<TraitObject=V>
{
#[inline]
pub fn trait_object_key_and_value(key_registry: &'k RK, value_registry: &'v RV) -> Self {
Self {
key_deserialize_seed: DeserializeTraitObject(key_registry),
value_deserialize_seed: DeserializeTraitObject(value_registry),
}
}
}
impl<'de, K, V> DeserializeSeed<'de> for DeserializeMapWith<K, V> where
K: DeserializeSeed<'de> + Copy,
K::Value: Eq + Hash,
V: DeserializeSeed<'de> + Copy,
{
type Value = HashMap<K::Value, V::Value>;
#[inline]
fn deserialize<D: Deserializer<'de>>(self, deserializer: D) -> Result<Self::Value, D::Error> {
deserializer.deserialize_map(self)
}
}
impl<'de, K, V> Visitor<'de> for DeserializeMapWith<K, V> where
K: DeserializeSeed<'de> + Copy,
K::Value: Eq + Hash,
V: DeserializeSeed<'de> + Copy,
{
type Value = HashMap<K::Value, V::Value>;
#[inline]
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "a map with custom key and value `DeserializeSeed` impls")
}
#[inline]
fn visit_map<A: MapAccess<'de>>(self, mut map_access: A) -> Result<Self::Value, A::Error> {
let mut map = if let Some(capacity) = map_access.size_hint() {
HashMap::with_capacity(capacity)
} else {
HashMap::new()
};
while let Some(key) = map_access.next_key_seed(self.key_deserialize_seed)? {
let value = map_access.next_value_seed(self.value_deserialize_seed)?;
map.insert(key, value);
}
Ok(map)
}
}