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 let oneway_cell = Cell::new(None);
41 let more_cell = Cell::new(None);
42 let upgrade_cell = Cell::new(None);
43
44 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 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 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}