use serde::{de::Visitor, Deserialize, Serialize};
use std::{collections::HashMap, marker::PhantomData};
#[derive(Debug, Clone, Default, Serialize)]
#[serde(transparent)]
pub struct SkippableMap<K, V>(pub HashMap<K, V>);
impl<K, V> SkippableMap<K, V> {
pub fn inner(self) -> HashMap<K, V> {
self.0
}
}
struct SkippableMapVisitor<K, V> {
marker: PhantomData<fn() -> SkippableMap<K, V>>,
}
impl<K, V> SkippableMapVisitor<K, V> {
fn new() -> Self {
Self {
marker: PhantomData,
}
}
}
impl<'de, K, V> Visitor<'de> for SkippableMapVisitor<K, V>
where
K: Deserialize<'de> + std::hash::Hash + std::cmp::Eq,
V: Deserialize<'de>,
{
type Value = SkippableMap<K, V>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
formatter,
"a data structure which contains some mappings from {} to {}",
std::any::type_name::<K>(),
std::any::type_name::<V>(),
)
}
fn visit_map<A>(self, mut access: A) -> std::result::Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut map = HashMap::with_capacity(access.size_hint().unwrap_or(0));
loop {
let r = access.next_entry();
match r {
Ok(Some((key, value))) => {
map.insert(key, value);
}
Err(_) => {}
Ok(None) => {
return Ok(SkippableMap(map));
}
};
}
}
}
impl<K, V> From<SkippableMap<K, V>> for HashMap<K, V> {
fn from(value: SkippableMap<K, V>) -> Self {
value.0
}
}
impl<K, V> AsRef<HashMap<K, V>> for SkippableMap<K, V> {
fn as_ref(&self) -> &HashMap<K, V> {
&self.0
}
}
impl<'de, K, V> Deserialize<'de> for SkippableMap<K, V>
where
K: Deserialize<'de> + std::hash::Hash + std::cmp::Eq,
V: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(SkippableMapVisitor::new())
}
}