Skip to main content

perde_core/decode/
union.rs

1use crate::{decode, schema::*, types::Object};
2use serde::de::{
3    self, DeserializeSeed, Deserializer, IntoDeserializer, MapAccess, SeqAccess, Unexpected,
4    Visitor,
5};
6use std::fmt;
7
8struct UnionVisitor<'a>(&'a Union);
9
10macro_rules! find {
11    ($s:expr, $unx:expr, $($kind:tt),*) => {
12        $s.0.variants.iter().find(|s| match s {
13            $(Schema::$kind(_) => true,)*
14                _ => false,
15        })
16        .ok_or_else(|| de::Error::invalid_type($unx, &$s))
17    }
18}
19
20impl<'a, 'de> Visitor<'de> for UnionVisitor<'a> {
21    type Value = Object;
22
23    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
24        let names: Vec<_> = self.0.variants.iter().map(|v| v.name()).collect();
25        write!(f, "any of {:?}", names)
26    }
27
28    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
29    where
30        E: de::Error,
31    {
32        let schema = find!(self, Unexpected::Bool(v), Primitive)?;
33        schema.deserialize(v.into_deserializer())
34    }
35
36    fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
37    where
38        E: de::Error,
39    {
40        self.visit_i64(v as i64)
41    }
42
43    fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
44    where
45        E: de::Error,
46    {
47        self.visit_i64(v as i64)
48    }
49
50    fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
51    where
52        E: de::Error,
53    {
54        self.visit_i64(v as i64)
55    }
56
57    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
58    where
59        E: de::Error,
60    {
61        let schema = find!(self, Unexpected::Signed(v), Primitive)?;
62        schema.deserialize(v.into_deserializer())
63    }
64
65    fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
66    where
67        E: de::Error,
68    {
69        self.visit_u64(v as u64)
70    }
71
72    fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
73    where
74        E: de::Error,
75    {
76        self.visit_u64(v as u64)
77    }
78
79    fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
80    where
81        E: de::Error,
82    {
83        self.visit_u64(v as u64)
84    }
85
86    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
87    where
88        E: de::Error,
89    {
90        let schema = find!(self, Unexpected::Unsigned(v), Primitive)?;
91        schema.deserialize(v.into_deserializer())
92    }
93
94    fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
95    where
96        E: de::Error,
97    {
98        self.visit_f64(v as f64)
99    }
100
101    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
102    where
103        E: de::Error,
104    {
105        let schema = find!(self, Unexpected::Float(v), Primitive)?;
106        schema.deserialize(v.into_deserializer())
107    }
108
109    fn visit_char<E>(self, v: char) -> Result<Self::Value, E>
110    where
111        E: de::Error,
112    {
113        self.visit_borrowed_str(&v.to_string())
114    }
115
116    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
117    where
118        E: de::Error,
119    {
120        self.visit_borrowed_str(v)
121    }
122
123    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
124    where
125        E: de::Error,
126    {
127        let schema = find!(self, Unexpected::Str(v), Primitive)?;
128        schema.deserialize(v.into_deserializer())
129    }
130
131    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
132    where
133        E: de::Error,
134    {
135        self.visit_borrowed_str(&v)
136    }
137
138    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
139    where
140        E: de::Error,
141    {
142        self.visit_borrowed_bytes(v)
143    }
144
145    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
146    where
147        E: de::Error,
148    {
149        let schema = find!(self, Unexpected::Bytes(v), Primitive)?;
150
151        match schema {
152            Schema::Primitive(Primitive::Bytes) => {
153                decode::primitive::BytesVisitor(false).visit_borrowed_bytes(v)
154            }
155            Schema::Primitive(Primitive::ByteArray) => {
156                decode::primitive::BytesVisitor(true).visit_borrowed_bytes(v)
157            }
158            _ => Err(de::Error::invalid_type(Unexpected::Bytes(v), &self)),
159        }
160    }
161
162    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
163    where
164        E: de::Error,
165    {
166        self.visit_borrowed_bytes(&v)
167    }
168
169    fn visit_none<E>(self) -> Result<Self::Value, E>
170    where
171        E: de::Error,
172    {
173        let schema = find!(self, Unexpected::Option, Optional)?;
174
175        match schema {
176            Schema::Optional(option) => decode::option::OptionVisitor(option).visit_none(),
177            _ => Err(de::Error::invalid_type(Unexpected::Option, &self)),
178        }
179    }
180
181    fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
182    where
183        D: Deserializer<'de>,
184    {
185        let schema = find!(self, Unexpected::Option, Optional)?;
186        schema.deserialize(deserializer)
187    }
188
189    fn visit_seq<A>(self, seq: A) -> Result<Self::Value, A::Error>
190    where
191        A: SeqAccess<'de>,
192    {
193        let schema = find!(self, Unexpected::Seq, List, Tuple, Set)?;
194
195        match schema {
196            Schema::List(l) => decode::list::ListVisitor(l).visit_seq(seq),
197            Schema::Tuple(t) => decode::tuple::TupleVisitor(t).visit_seq(seq),
198            Schema::Set(s) => decode::set::SetVisitor(s).visit_seq(seq),
199            _ => unreachable!(),
200        }
201    }
202
203    fn visit_map<A>(self, map: A) -> Result<Self::Value, A::Error>
204    where
205        A: MapAccess<'de>,
206    {
207        let schema = find!(self, Unexpected::Map, Dict, Class)?;
208
209        match schema {
210            Schema::Dict(d) => decode::dict::DictVisitor(d).visit_map(map),
211            Schema::Class(c) => decode::class::ClassVisitor(c).visit_map(map),
212            _ => unreachable!(),
213        }
214    }
215}
216
217impl<'a, 'de> DeserializeSeed<'de> for &'a Union {
218    type Value = Object;
219
220    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
221    where
222        D: Deserializer<'de>,
223    {
224        deserializer.deserialize_any(UnionVisitor(self))
225    }
226}