为自定义 map 类型实现 Deserialize

use std::fmt;
use std::marker::PhantomData;

use serde::de::{Deserialize, Deserializer, Visitor, MapAccess};

struct MyMap<K, V>(PhantomData<K>, PhantomData<V>);

impl<K, V> MyMap<K, V> {
    fn with_capacity(_: usize) -> Self {
        unimplemented!()
    }

    fn insert(&mut self, _: K, _: V) {
        unimplemented!()
    }
}

// Visitor 是一个类型,其中包含 Deserializer 可以根据输入数据的内容驱动的方法。
//
// 在 map 的情况下,我们需要泛型类型参数 K 和 V 来正确设置输出类型,但不需要任何状态。
// 这是 Rust 中的 “零大小类型” 的一个例子。PhantomData
// 防止编译器因未使用的泛型类型参数而抱怨。
struct MyMapVisitor<K, V> {
    marker: PhantomData<fn() -> MyMap<K, V>>
}

impl<K, V> MyMapVisitor<K, V> {
    fn new() -> Self {
        MyMapVisitor {
            marker: PhantomData
        }
    }
}

// 这是Deserializers将驱动的特质。每种类型的数据都有一个与之对应的方法
// 我们的类型知道如何从中反序列化。这里有许多其他未在此处实现的方法,例如从整数或字符串反序列化。
// 默认情况下,这些方法将返回错误,这是有道理的,因为我们无法从整数或字符串反序列化MyMap。
impl<'de, K, V> Visitor<'de> for MyMapVisitor<K, V>
where
    K: Deserialize<'de>,
    V: Deserialize<'de>,
{
    //我们的Visitor将生成的类型。
    type Value = MyMap<K, V>;

    //格式化一条消息,说明该 Visitor 希望接收哪些数据。
    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("一个非常特殊的 map")
    }

    // 从Deserializer提供的抽象“地图”中反序列化MyMap。MapAccess输入是Deserializer提供的回调,让我们可以看到地图中的每个条目。
    fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
    where
        M: MapAccess<'de>,
    {
        let mut map = MyMap::with_capacity(access.size_hint().unwrap_or(0));

        // 在输入中还有条目时,将它们添加到我们的地图中。
        while let Some((key, value)) = access.next_entry()? {
            map.insert(key, value);
        }

        Ok(map)
    }
}

// 这是告诉 Serde 如何反序列化 MyMap 的特质。
impl<'de, K, V> Deserialize<'de> for MyMap<K, V>
where
    K: Deserialize<'de>,
    V: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        //实例化我们的 Visitor,并要求 Deserializer 在输入数据上驱动它,从而生成 MyMap 的实例。
        deserializer.deserialize_map(MyMapVisitor::new())
    }
}

fn main() {}