zlink_core/call/
de.rs

1use core::{cell::Cell, fmt, marker::PhantomData};
2
3use serde::{
4    de::{
5        self, value::MapAccessDeserializer, DeserializeSeed, IntoDeserializer, MapAccess, Visitor,
6    },
7    Deserialize, Deserializer,
8};
9
10use super::Call;
11
12impl<'de, M> Deserialize<'de> for Call<M>
13where
14    M: Deserialize<'de>,
15{
16    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
17    where
18        D: Deserializer<'de>,
19    {
20        struct CallVisitor<M>(PhantomData<M>);
21
22        impl<'de, M> Visitor<'de> for CallVisitor<M>
23        where
24            M: Deserialize<'de>,
25        {
26            type Value = Call<M>;
27
28            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29                write!(
30                    f,
31                    "a map with optional booleans and flattened method fields"
32                )
33            }
34
35            fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
36            where
37                A: MapAccess<'de>,
38            {
39                // 1) Prepare interior-mutable storage for optionals
40                let oneway_cell = Cell::new(None);
41                let more_cell = Cell::new(None);
42                let upgrade_cell = Cell::new(None);
43
44                // 2) Streaming adapter capturing booleans by Cell refs
45                struct FilterMap<'a, MAcc> {
46                    inner: MAcc,
47                    oneway: &'a Cell<Option<bool>>,
48                    more: &'a Cell<Option<bool>>,
49                    upgrade: &'a Cell<Option<bool>>,
50                }
51                impl<'de, 'a, MAcc> MapAccess<'de> for FilterMap<'a, MAcc>
52                where
53                    MAcc: MapAccess<'de>,
54                {
55                    type Error = MAcc::Error;
56
57                    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, MAcc::Error>
58                    where
59                        K: DeserializeSeed<'de>,
60                    {
61                        while let Some(key) = self.inner.next_key::<&str>()? {
62                            match key {
63                                "oneway" => {
64                                    let v = self.inner.next_value()?;
65                                    self.oneway.set(Some(v));
66                                    continue;
67                                }
68                                "more" => {
69                                    let v = self.inner.next_value()?;
70                                    self.more.set(Some(v));
71                                    continue;
72                                }
73                                "upgrade" => {
74                                    let v = self.inner.next_value()?;
75                                    self.upgrade.set(Some(v));
76                                    continue;
77                                }
78                                other => {
79                                    let de = other.into_deserializer();
80                                    return seed.deserialize(de).map(Some);
81                                }
82                            }
83                        }
84                        Ok(None)
85                    }
86
87                    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, MAcc::Error>
88                    where
89                        V: DeserializeSeed<'de>,
90                    {
91                        self.inner.next_value_seed(seed)
92                    }
93                }
94
95                // 3) Deserialize method: M using our FilterMap
96                let filter = FilterMap {
97                    inner: map,
98                    oneway: &oneway_cell,
99                    more: &more_cell,
100                    upgrade: &upgrade_cell,
101                };
102                let method = M::deserialize(MapAccessDeserializer::new(filter))
103                    .map_err(de::Error::custom)?;
104
105                // 4) Extract boolean fields from Cells
106                let oneway = oneway_cell.get().unwrap_or_default();
107                let more = more_cell.get().unwrap_or_default();
108                let upgrade = upgrade_cell.get().unwrap_or_default();
109
110                Ok(Call {
111                    method,
112                    oneway,
113                    more,
114                    upgrade,
115                })
116            }
117        }
118
119        deserializer.deserialize_map(CallVisitor(PhantomData))
120    }
121}