use crate::{
DefaultHashBuilder, TriHashItem, TriHashMap,
support::alloc::{Allocator, Global},
};
use core::{fmt, hash::BuildHasher, marker::PhantomData};
use serde_core::{
Deserialize, Deserializer, Serialize, Serializer,
de::{MapAccess, SeqAccess, Visitor},
ser::SerializeMap,
};
impl<T: TriHashItem, S: Clone + BuildHasher, A: Allocator> Serialize
for TriHashMap<T, S, A>
where
T: Serialize,
{
fn serialize<Ser: Serializer>(
&self,
serializer: Ser,
) -> Result<Ser::Ok, Ser::Error> {
self.items.serialize(serializer)
}
}
impl<
'de,
T: TriHashItem + fmt::Debug,
S: Clone + BuildHasher + Default,
A: Default + Clone + Allocator,
> Deserialize<'de> for TriHashMap<T, S, A>
where
T: Deserialize<'de>,
{
fn deserialize<D: Deserializer<'de>>(
deserializer: D,
) -> Result<Self, D::Error> {
deserializer.deserialize_any(SeqVisitor {
_marker: PhantomData,
hasher: S::default(),
alloc: A::default(),
})
}
}
impl<
'de,
T: TriHashItem + fmt::Debug + Deserialize<'de>,
S: Clone + BuildHasher,
A: Clone + Allocator,
> TriHashMap<T, S, A>
{
pub fn deserialize_in<D: Deserializer<'de>>(
deserializer: D,
alloc: A,
) -> Result<Self, D::Error>
where
S: Default,
{
deserializer.deserialize_any(SeqVisitor {
_marker: PhantomData,
hasher: S::default(),
alloc,
})
}
pub fn deserialize_with_hasher<D: Deserializer<'de>>(
deserializer: D,
hasher: S,
) -> Result<Self, D::Error>
where
A: Default,
{
deserializer.deserialize_any(SeqVisitor {
_marker: PhantomData,
hasher,
alloc: A::default(),
})
}
pub fn deserialize_with_hasher_in<D: Deserializer<'de>>(
deserializer: D,
hasher: S,
alloc: A,
) -> Result<Self, D::Error> {
deserializer.deserialize_any(SeqVisitor {
_marker: PhantomData,
hasher,
alloc,
})
}
}
struct SeqVisitor<T, S, A> {
_marker: PhantomData<fn() -> T>,
hasher: S,
alloc: A,
}
impl<'de, T, S, A> Visitor<'de> for SeqVisitor<T, S, A>
where
T: TriHashItem + Deserialize<'de> + fmt::Debug,
S: Clone + BuildHasher,
A: Clone + Allocator,
{
type Value = TriHashMap<T, S, A>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.write_str("a sequence or map of items representing a TriHashMap")
}
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) => TriHashMap::with_capacity_and_hasher_in(
size,
self.hasher,
self.alloc,
),
None => TriHashMap::with_hasher_in(self.hasher, self.alloc),
};
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 = match map_access.size_hint() {
Some(size) => TriHashMap::with_capacity_and_hasher_in(
size,
self.hasher,
self.alloc,
),
None => TriHashMap::with_hasher_in(self.hasher, self.alloc),
};
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 TriHashMapAsMap<T, S = DefaultHashBuilder, A: Allocator = Global> {
#[expect(clippy::type_complexity)]
_marker: PhantomData<fn() -> (T, S, A)>,
}
struct MapVisitorAsMap<T, S, A> {
_marker: PhantomData<fn() -> T>,
hasher: S,
alloc: A,
}
impl<'de, T, S, A> Visitor<'de> for MapVisitorAsMap<T, S, A>
where
T: TriHashItem + Deserialize<'de> + fmt::Debug,
S: Clone + BuildHasher,
A: Clone + Allocator,
{
type Value = TriHashMap<T, S, A>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a map with items representing a TriHashMap")
}
fn visit_map<Access>(
self,
mut map_access: Access,
) -> Result<Self::Value, Access::Error>
where
Access: MapAccess<'de>,
{
let mut map = match map_access.size_hint() {
Some(size) => TriHashMap::with_capacity_and_hasher_in(
size,
self.hasher,
self.alloc,
),
None => TriHashMap::with_hasher_in(self.hasher, self.alloc),
};
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, S, A> TriHashMapAsMap<T, S, A>
where
S: Clone + BuildHasher,
A: Allocator,
{
pub fn serialize<'a, Ser>(
map: &TriHashMap<T, S, A>,
serializer: Ser,
) -> Result<Ser::Ok, Ser::Error>
where
T: 'a + TriHashItem + Serialize,
T::K1<'a>: Serialize,
Ser: Serializer,
{
let mut ser_map = serializer.serialize_map(Some(map.len()))?;
for item in map.iter() {
let key1 = item.key1();
let key1 =
unsafe { core::mem::transmute::<T::K1<'_>, T::K1<'a>>(key1) };
ser_map.serialize_entry(&key1, item)?;
}
ser_map.end()
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<TriHashMap<T, S, A>, D::Error>
where
T: TriHashItem + Deserialize<'de> + fmt::Debug,
S: Default,
A: Clone + Default,
D: Deserializer<'de>,
{
deserializer.deserialize_map(MapVisitorAsMap {
_marker: PhantomData,
hasher: S::default(),
alloc: A::default(),
})
}
}