use std::{
hash::{BuildHasher, Hash},
marker::PhantomData,
};
use crate::{ExtractKey, ExtractMap};
pub(crate) struct WithSizeHint<I> {
inner: I,
hint: Option<usize>,
}
impl<Item, I: Iterator<Item = Item>> Iterator for WithSizeHint<I> {
type Item = Item;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.hint.unwrap_or_default(), self.hint)
}
}
pub(crate) trait IteratorExt: Iterator + Sized {
fn with_size_hint(self, hint: Option<usize>) -> WithSizeHint<Self>;
}
impl<Item, I: Iterator<Item = Item>> IteratorExt for I {
fn with_size_hint(self, hint: Option<usize>) -> WithSizeHint<I> {
WithSizeHint { inner: self, hint }
}
}
#[cfg(feature = "serde")]
impl<'de, K, V, S> serde::Deserialize<'de> for ExtractMap<K, V, S>
where
K: Hash + Eq,
V: ExtractKey<K> + serde::Deserialize<'de>,
S: BuildHasher + Default,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::{IgnoredAny, MapAccess, SeqAccess};
struct Visitor<K, V, S>(PhantomData<(K, V, S)>);
impl<'de, K, V, S> serde::de::Visitor<'de> for Visitor<K, V, S>
where
K: Hash + Eq,
V: ExtractKey<K> + serde::Deserialize<'de>,
S: BuildHasher + Default,
{
type Value = ExtractMap<K, V, S>;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("a sequence")
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
let size_hint = map.size_hint();
std::iter::from_fn(|| map.next_entry::<IgnoredAny, V>().transpose())
.map(|res| res.map(|(_, v)| v))
.with_size_hint(size_hint)
.collect()
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let size_hint = seq.size_hint();
std::iter::from_fn(|| seq.next_element().transpose())
.with_size_hint(size_hint)
.collect()
}
}
deserializer.deserialize_any(Visitor(PhantomData))
}
}
#[cfg(feature = "serde")]
impl<K, V: serde::Serialize, H> serde::Serialize for ExtractMap<K, V, H> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.collect_seq(self)
}
}
#[cfg(feature = "serde")]
pub fn serialize_as_map<K, V, H, S>(map: &ExtractMap<K, V, H>, ser: S) -> Result<S::Ok, S::Error>
where
K: serde::Serialize + Hash + Eq,
V: serde::Serialize + ExtractKey<K>,
S: serde::Serializer,
{
ser.collect_map(map.iter().map(|v| (v.extract_key(), v)))
}