use super::{IdOrdItem, IdOrdMap};
use core::{fmt, marker::PhantomData};
use serde_core::{
Deserialize, Deserializer, Serialize, Serializer,
de::{MapAccess, SeqAccess, Visitor},
ser::{SerializeMap, SerializeSeq},
};
impl<T: IdOrdItem> Serialize for IdOrdMap<T>
where
T: Serialize,
{
fn serialize<S: Serializer>(
&self,
serializer: S,
) -> Result<S::Ok, S::Error> {
let mut seq = serializer.serialize_seq(Some(self.len()))?;
for item in self {
seq.serialize_element(item)?;
}
seq.end()
}
}
impl<'de, T: IdOrdItem + fmt::Debug> Deserialize<'de> for IdOrdMap<T>
where
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(SeqVisitor { _marker: PhantomData })
}
}
struct SeqVisitor<T> {
_marker: PhantomData<fn() -> T>,
}
impl<'de, T> Visitor<'de> for SeqVisitor<T>
where
T: IdOrdItem + Deserialize<'de> + fmt::Debug,
{
type Value = IdOrdMap<T>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.write_str("a sequence or map of items representing an IdOrdMap")
}
fn visit_seq<Access>(
self,
mut seq: Access,
) -> Result<Self::Value, Access::Error>
where
Access: SeqAccess<'de>,
{
let mut map = match seq.size_hint() {
Some(size) => IdOrdMap::with_capacity(size),
None => IdOrdMap::new(),
};
while let Some(element) = seq.next_element()? {
map.insert_unique(element)
.map_err(serde_core::de::Error::custom)?;
}
Ok(map)
}
fn visit_map<Access>(
self,
mut map_access: Access,
) -> Result<Self::Value, Access::Error>
where
Access: MapAccess<'de>,
{
let mut map = IdOrdMap::new();
while let Some((_, value)) =
map_access.next_entry::<serde_core::de::IgnoredAny, T>()?
{
map.insert_unique(value).map_err(serde_core::de::Error::custom)?;
}
Ok(map)
}
}
pub struct IdOrdMapAsMap<T> {
_marker: PhantomData<fn() -> T>,
}
struct MapVisitorAsMap<T> {
_marker: PhantomData<fn() -> T>,
}
impl<'de, T> Visitor<'de> for MapVisitorAsMap<T>
where
T: IdOrdItem + Deserialize<'de> + fmt::Debug,
{
type Value = IdOrdMap<T>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a map with items representing an IdOrdMap")
}
fn visit_map<Access>(
self,
mut map_access: Access,
) -> Result<Self::Value, Access::Error>
where
Access: MapAccess<'de>,
{
let mut map = IdOrdMap::new();
while let Some((_, value)) =
map_access.next_entry::<serde_core::de::IgnoredAny, T>()?
{
map.insert_unique(value).map_err(serde_core::de::Error::custom)?;
}
Ok(map)
}
}
impl<T> IdOrdMapAsMap<T> {
pub fn serialize<'a, Ser>(
map: &IdOrdMap<T>,
serializer: Ser,
) -> Result<Ser::Ok, Ser::Error>
where
T: 'a + IdOrdItem + Serialize,
T::Key<'a>: Serialize,
Ser: Serializer,
{
let mut ser_map = serializer.serialize_map(Some(map.len()))?;
for item in map.iter() {
let key1 = unsafe {
core::mem::transmute::<T::Key<'_>, T::Key<'a>>(item.key())
};
ser_map.serialize_entry(&key1, item)?;
}
ser_map.end()
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<IdOrdMap<T>, D::Error>
where
T: IdOrdItem + Deserialize<'de> + fmt::Debug,
D: Deserializer<'de>,
{
deserializer.deserialize_map(MapVisitorAsMap { _marker: PhantomData })
}
}