serde_content/de/
number.rs

1use crate::Error;
2use crate::Expected;
3use crate::Number;
4use crate::Unexpected;
5use serde::de;
6use serde::Deserialize;
7
8#[cfg(feature = "std")]
9impl<'de> serde::de::IntoDeserializer<'de, Error> for Number {
10    type Deserializer = crate::Deserializer<'de>;
11
12    fn into_deserializer(self) -> Self::Deserializer {
13        use crate::Deserializer;
14        use crate::Value;
15
16        Deserializer::new(Value::Number(self))
17    }
18}
19
20impl<'de> Deserialize<'de> for Number {
21    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
22    where
23        D: serde::Deserializer<'de>,
24    {
25        deserializer.deserialize_any(Visitor)
26    }
27}
28
29struct Visitor;
30
31impl de::Visitor<'_> for Visitor {
32    type Value = Number;
33
34    fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
35        formatter.write_str("a number")
36    }
37
38    fn visit_i8<E>(self, v: i8) -> Result<Self::Value, E>
39    where
40        E: de::Error,
41    {
42        Ok(Number::I8(v))
43    }
44
45    fn visit_i16<E>(self, v: i16) -> Result<Self::Value, E>
46    where
47        E: de::Error,
48    {
49        Ok(Number::I16(v))
50    }
51
52    fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
53    where
54        E: de::Error,
55    {
56        Ok(Number::I32(v))
57    }
58
59    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
60    where
61        E: de::Error,
62    {
63        Ok(Number::I64(v))
64    }
65
66    fn visit_i128<E>(self, v: i128) -> Result<Self::Value, E>
67    where
68        E: de::Error,
69    {
70        Ok(Number::I128(v))
71    }
72
73    fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
74    where
75        E: de::Error,
76    {
77        Ok(Number::U8(v))
78    }
79
80    fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
81    where
82        E: de::Error,
83    {
84        Ok(Number::U16(v))
85    }
86
87    fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
88    where
89        E: de::Error,
90    {
91        Ok(Number::U32(v))
92    }
93
94    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
95    where
96        E: de::Error,
97    {
98        Ok(Number::U64(v))
99    }
100
101    fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
102    where
103        E: de::Error,
104    {
105        Ok(Number::U128(v))
106    }
107
108    fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
109    where
110        E: de::Error,
111    {
112        Ok(Number::F32(v))
113    }
114
115    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
116    where
117        E: de::Error,
118    {
119        Ok(Number::F64(v))
120    }
121}
122
123macro_rules! range {
124    ($min:ident, $max:ident as $dest:ty) => {
125        (($min::MIN as $dest)..=($max::MAX as $dest))
126    };
127    ($src:ident as $dest:ty) => {
128        (($src::MIN as $dest)..=($src::MAX as $dest))
129    };
130}
131
132macro_rules! coerce_int {
133    ($number:ident, $v:ident, $expected:ident, $visitor:ident) => {{
134        match $expected {
135            Expected::I8 => {
136                $visitor.visit_i8($v.try_into().map_err(|_| $number.unexpected($expected))?)
137            }
138            Expected::U8 => {
139                $visitor.visit_u8($v.try_into().map_err(|_| $number.unexpected($expected))?)
140            }
141            Expected::I16 => {
142                $visitor.visit_i16($v.try_into().map_err(|_| $number.unexpected($expected))?)
143            }
144            Expected::U16 => {
145                $visitor.visit_u16($v.try_into().map_err(|_| $number.unexpected($expected))?)
146            }
147            Expected::I32 => {
148                $visitor.visit_i32($v.try_into().map_err(|_| $number.unexpected($expected))?)
149            }
150            Expected::F32
151                if i32::try_from($v).is_ok()
152                    && range!(i16, u16 as i32).contains(&i32::try_from($v).unwrap()) =>
153            {
154                $visitor.visit_f32($v as f32)
155            }
156            Expected::U32 => {
157                $visitor.visit_u32($v.try_into().map_err(|_| $number.unexpected($expected))?)
158            }
159            Expected::I64 => {
160                $visitor.visit_i64($v.try_into().map_err(|_| $number.unexpected($expected))?)
161            }
162            Expected::F64
163                if i64::try_from($v).is_ok()
164                    && range!(i32, u32 as i64).contains(&i64::try_from($v).unwrap()) =>
165            {
166                $visitor.visit_f64($v as f64)
167            }
168            Expected::U64 => {
169                $visitor.visit_u64($v.try_into().map_err(|_| $number.unexpected($expected))?)
170            }
171            Expected::I128 => {
172                $visitor.visit_i128($v.try_into().map_err(|_| $number.unexpected($expected))?)
173            }
174            Expected::U128 => {
175                $visitor.visit_u128($v.try_into().map_err(|_| $number.unexpected($expected))?)
176            }
177            _ => Err($number.unexpected($expected)),
178        }
179    }};
180}
181
182enum NumberType {
183    Int,
184    F32,
185    F64,
186}
187
188impl Expected {
189    const fn number_type(&self) -> NumberType {
190        match self {
191            Expected::F32 => NumberType::F32,
192            Expected::F64 => NumberType::F64,
193            _ => NumberType::Int,
194        }
195    }
196}
197
198pub(super) fn visit<'de, V>(
199    number: Number,
200    expected: Expected,
201    coerce_numbers: bool,
202    visitor: V,
203) -> Result<V::Value, Error>
204where
205    V: de::Visitor<'de>,
206{
207    match (number, expected) {
208        (Number::I8(v), Expected::I8) => visitor.visit_i8(v),
209        (Number::U8(v), Expected::U8) => visitor.visit_u8(v),
210        (Number::I16(v), Expected::I16) => visitor.visit_i16(v),
211        (Number::U16(v), Expected::U16) => visitor.visit_u16(v),
212        (Number::I32(v), Expected::I32) => visitor.visit_i32(v),
213        (Number::U32(v), Expected::U32) => visitor.visit_u32(v),
214        (Number::F32(v), Expected::F32) => visitor.visit_f32(v),
215        (Number::I64(v), Expected::I64) => visitor.visit_i64(v),
216        (Number::U64(v), Expected::U64) => visitor.visit_u64(v),
217        (Number::F64(v), Expected::F64) => visitor.visit_f64(v),
218        (Number::I128(v), Expected::I128) => visitor.visit_i128(v),
219        (Number::U128(v), Expected::U128) => visitor.visit_u128(v),
220        (number, expected) => {
221            if !coerce_numbers {
222                return Err(number.unexpected(expected));
223            }
224
225            match (number, expected.number_type()) {
226                (Number::I8(v), _) => {
227                    coerce_int!(number, v, expected, visitor)
228                }
229                (Number::U8(v), _) => {
230                    coerce_int!(number, v, expected, visitor)
231                }
232                (Number::I16(v), _) => {
233                    coerce_int!(number, v, expected, visitor)
234                }
235                (Number::U16(v), _) => {
236                    coerce_int!(number, v, expected, visitor)
237                }
238                (Number::I32(v), _) => {
239                    coerce_int!(number, v, expected, visitor)
240                }
241                (Number::U32(v), _) => {
242                    coerce_int!(number, v, expected, visitor)
243                }
244                (Number::F32(v), NumberType::F64) => visitor.visit_f64(v as f64),
245                (Number::I64(v), _) => {
246                    coerce_int!(number, v, expected, visitor)
247                }
248                (Number::U64(v), _) => {
249                    coerce_int!(number, v, expected, visitor)
250                }
251                (Number::F64(v), NumberType::F32) if range!(f32 as f64).contains(&v) => {
252                    visitor.visit_f32(v as f32)
253                }
254                (Number::I128(v), _) => {
255                    coerce_int!(number, v, expected, visitor)
256                }
257                (Number::U128(v), _) => {
258                    coerce_int!(number, v, expected, visitor)
259                }
260                _ => Err(number.unexpected(expected)),
261            }
262        }
263    }
264}