1use std::fmt::Formatter;
2use std::marker::PhantomData;
3
4use frunk_core::hlist::{HCons, HList, HNil};
5use frunk_core::traits::IntoReverse;
6use serde::de::{MapAccess, Visitor};
7use serde::{Deserialize, Deserializer};
8
9use super::HMap;
10
11struct HMapVisitor<L>(PhantomData<L>);
12
13impl<L> Default for HMapVisitor<L> {
14 fn default() -> Self {
15 Self(PhantomData)
16 }
17}
18
19impl<'de, L> Visitor<'de> for HMapVisitor<L>
20where
21 L: IntoReverse,
22 L::Output: MapDeserializable<'de> + IntoReverse<Output = L>,
23{
24 type Value = HMap<L>;
25
26 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
27 formatter.write_str("a heterogeneous map")
28 }
29
30 fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
31 where
32 A: MapAccess<'de>,
33 {
34 let (reversed, _) = <L::Output as MapDeserializable<'de>>::visit_map(map)?;
35 Ok(HMap(reversed.into_reverse()))
36 }
37}
38
39pub trait MapDeserializable<'de>: HList {
40 fn visit_map<A: MapAccess<'de>>(map: A) -> Result<(Self, A), A::Error>;
41}
42
43impl<'de, K, V, T> MapDeserializable<'de> for HCons<(K, V), T>
44where
45 K: Deserialize<'de>,
46 V: Deserialize<'de>,
47 T: MapDeserializable<'de>,
48{
49 fn visit_map<A: MapAccess<'de>>(map: A) -> Result<(Self, A), A::Error> {
50 let (append, mut map) = T::visit_map(map)?;
51 let (k, v) = map.next_entry()?.expect("unexpected eof");
52 Ok((append.prepend((k, v)), map))
53 }
54}
55
56impl<'de> MapDeserializable<'de> for HNil {
57 fn visit_map<A: MapAccess<'de>>(map: A) -> Result<(Self, A), A::Error> {
58 Ok((HNil, map))
59 }
60}
61
62impl<'de, L> Deserialize<'de> for HMap<L>
63where
64 L: IntoReverse,
65 L::Output: MapDeserializable<'de> + IntoReverse<Output = L>,
66{
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: Deserializer<'de>,
70 {
71 deserializer.deserialize_map(HMapVisitor::default())
72 }
73}