sonic_rs/serde/
number.rs

1// The code is cloned from [serde_json](https://github.com/serde-rs/json) and modified necessary parts.
2
3use sonic_number::ParserNumber;
4
5use crate::{error::make_error, util::private::Sealed};
6
7/// Represents a JSON number, whether integer or floating point.
8#[derive(Clone, PartialEq, Eq, Hash)]
9pub struct Number {
10    pub(crate) n: N,
11}
12
13#[derive(Debug, Copy, Clone)]
14pub(crate) enum N {
15    PosInt(u64),
16    /// Always less than zero.
17    NegInt(i64),
18    /// Always finite.
19    Float(f64),
20}
21
22use core::{
23    fmt::{self, Debug, Display},
24    hash::{Hash, Hasher},
25};
26
27use serde::{
28    de::{self, Visitor},
29    forward_to_deserialize_any, Deserialize, Deserializer, Serialize, Serializer,
30};
31
32use crate::error::Error;
33
34impl PartialEq for N {
35    fn eq(&self, other: &Self) -> bool {
36        match (self, other) {
37            (N::PosInt(a), N::PosInt(b)) => a == b,
38            (N::NegInt(a), N::NegInt(b)) => a == b,
39            (N::Float(a), N::Float(b)) => a == b,
40            _ => false,
41        }
42    }
43}
44
45// Implementing Eq is fine since any float values are always finite.
46impl Eq for N {}
47
48impl Hash for N {
49    fn hash<H: Hasher>(&self, h: &mut H) {
50        match *self {
51            N::PosInt(i) => i.hash(h),
52            N::NegInt(i) => i.hash(h),
53            N::Float(f) => {
54                if f == 0.0f64 {
55                    // There are 2 zero representations, +0 and -0, which
56                    // compare equal but have different bits. We use the +0 hash
57                    // for both so that hash(+0) == hash(-0).
58                    0.0f64.to_bits().hash(h);
59                } else {
60                    f.to_bits().hash(h);
61                }
62            }
63        }
64    }
65}
66
67/// Number trait for both `Number` and `RawNumber`.
68pub trait JsonNumberTrait: Sealed {
69    fn is_i64(&self) -> bool;
70    fn is_u64(&self) -> bool;
71    fn is_f64(&self) -> bool;
72    fn as_i64(&self) -> Option<i64>;
73    fn as_u64(&self) -> Option<u64>;
74    fn as_f64(&self) -> Option<f64>;
75}
76
77impl Sealed for Number {}
78
79impl JsonNumberTrait for Number {
80    /// Returns true if the `Number` is an integer between `i64::MIN` and
81    /// `i64::MAX`.
82    ///
83    /// For any Number on which `is_i64` returns true, `as_i64` is guaranteed to
84    /// return the integer value.
85    #[inline]
86    fn is_i64(&self) -> bool {
87        match self.n {
88            N::PosInt(v) => v <= i64::MAX as u64,
89            N::NegInt(_) => true,
90            N::Float(_) => false,
91        }
92    }
93
94    /// Returns true if the `Number` is an integer between zero and `u64::MAX`.
95    ///
96    /// For any Number on which `is_u64` returns true, `as_u64` is guaranteed to
97    /// return the integer value.
98    #[inline]
99    fn is_u64(&self) -> bool {
100        match self.n {
101            N::PosInt(_) => true,
102            N::NegInt(_) | N::Float(_) => false,
103        }
104    }
105
106    /// Returns true if the `Number` can be represented by f64.
107    ///
108    /// For any Number on which `is_f64` returns true, `as_f64` is guaranteed to
109    /// return the floating point value.
110    ///
111    /// Currently this function returns true if and only if both `is_i64` and
112    /// `is_u64` return false but this is not a guarantee in the future.
113    #[inline]
114    fn is_f64(&self) -> bool {
115        match self.n {
116            N::Float(_) => true,
117            N::PosInt(_) | N::NegInt(_) => false,
118        }
119    }
120
121    /// If the `Number` is an integer, represent it as i64 if possible. Returns
122    /// None otherwise.
123    #[inline]
124    fn as_i64(&self) -> Option<i64> {
125        match self.n {
126            N::PosInt(n) => {
127                if n <= i64::MAX as u64 {
128                    Some(n as i64)
129                } else {
130                    None
131                }
132            }
133            N::NegInt(n) => Some(n),
134            N::Float(_) => None,
135        }
136    }
137
138    /// If the `Number` is an integer, represent it as u64 if possible. Returns
139    /// None otherwise.
140    #[inline]
141    fn as_u64(&self) -> Option<u64> {
142        match self.n {
143            N::PosInt(n) => Some(n),
144            N::NegInt(_) | N::Float(_) => None,
145        }
146    }
147
148    /// Represents the number as finite f64 if possible. Returns None otherwise.
149    #[inline]
150    fn as_f64(&self) -> Option<f64> {
151        match self.n {
152            N::PosInt(n) => Some(n as f64),
153            N::NegInt(n) => Some(n as f64),
154            N::Float(n) => Some(n),
155        }
156    }
157}
158
159impl Number {
160    /// Converts a finite `f64` to a `Number`. Infinite or NaN values are not JSON
161    /// numbers.
162    #[inline]
163    pub fn from_f64(f: f64) -> Option<Number> {
164        if f.is_finite() {
165            let n = { N::Float(f) };
166            Some(Number { n })
167        } else {
168            None
169        }
170    }
171}
172
173impl Display for Number {
174    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
175        match self.n {
176            N::PosInt(u) => formatter.write_str(itoa::Buffer::new().format(u)),
177            N::NegInt(i) => formatter.write_str(itoa::Buffer::new().format(i)),
178            N::Float(f) => formatter.write_str(ryu::Buffer::new().format_finite(f)),
179        }
180    }
181}
182
183impl Debug for Number {
184    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
185        write!(formatter, "Number({self})")
186    }
187}
188
189impl Serialize for Number {
190    #[inline]
191    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
192    where
193        S: Serializer,
194    {
195        match self.n {
196            N::PosInt(u) => serializer.serialize_u64(u),
197            N::NegInt(i) => serializer.serialize_i64(i),
198            N::Float(f) => serializer.serialize_f64(f),
199        }
200    }
201}
202
203impl<'de> Deserialize<'de> for Number {
204    #[inline]
205    fn deserialize<D>(deserializer: D) -> Result<Number, D::Error>
206    where
207        D: Deserializer<'de>,
208    {
209        struct NumberVisitor;
210
211        impl<'de> Visitor<'de> for NumberVisitor {
212            type Value = Number;
213
214            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
215                formatter.write_str("a JSON number")
216            }
217
218            #[inline]
219            fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
220                Ok(value.into())
221            }
222
223            #[inline]
224            fn visit_u64<E>(self, value: u64) -> Result<Number, E> {
225                Ok(value.into())
226            }
227
228            #[inline]
229            fn visit_f64<E>(self, value: f64) -> Result<Number, E>
230            where
231                E: de::Error,
232            {
233                Number::from_f64(value).ok_or_else(|| de::Error::custom("not a JSON number"))
234            }
235        }
236
237        deserializer.deserialize_any(NumberVisitor)
238    }
239}
240
241macro_rules! deserialize_any {
242    (@expand [$($num_string:tt)*]) => {
243        #[inline]
244        fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
245        where
246            V: Visitor<'de>,
247        {
248            match self.n {
249                N::PosInt(u) => visitor.visit_u64(u),
250                N::NegInt(i) => visitor.visit_i64(i),
251                N::Float(f) => visitor.visit_f64(f),
252            }
253        }
254    };
255
256    (owned) => {
257        deserialize_any!(@expand [n]);
258    };
259
260    (ref) => {
261        deserialize_any!(@expand [n.clone()]);
262    };
263}
264
265macro_rules! deserialize_number {
266    ($deserialize:ident) => {
267        fn $deserialize<V>(self, visitor: V) -> Result<V::Value, Error>
268        where
269            V: Visitor<'de>,
270        {
271            self.deserialize_any(visitor)
272        }
273    };
274}
275
276impl<'de> Deserializer<'de> for Number {
277    type Error = Error;
278
279    deserialize_any!(owned);
280
281    deserialize_number!(deserialize_i8);
282    deserialize_number!(deserialize_i16);
283    deserialize_number!(deserialize_i32);
284    deserialize_number!(deserialize_i64);
285    deserialize_number!(deserialize_i128);
286    deserialize_number!(deserialize_u8);
287    deserialize_number!(deserialize_u16);
288    deserialize_number!(deserialize_u32);
289    deserialize_number!(deserialize_u64);
290    deserialize_number!(deserialize_u128);
291    deserialize_number!(deserialize_f32);
292    deserialize_number!(deserialize_f64);
293
294    forward_to_deserialize_any! {
295        bool char str string bytes byte_buf option unit unit_struct
296        newtype_struct seq tuple tuple_struct map struct enum identifier
297        ignored_any
298    }
299}
300
301impl<'de, 'a> Deserializer<'de> for &'a Number {
302    type Error = Error;
303
304    deserialize_any!(ref);
305
306    deserialize_number!(deserialize_i8);
307    deserialize_number!(deserialize_i16);
308    deserialize_number!(deserialize_i32);
309    deserialize_number!(deserialize_i64);
310    deserialize_number!(deserialize_i128);
311    deserialize_number!(deserialize_u8);
312    deserialize_number!(deserialize_u16);
313    deserialize_number!(deserialize_u32);
314    deserialize_number!(deserialize_u64);
315    deserialize_number!(deserialize_u128);
316    deserialize_number!(deserialize_f32);
317    deserialize_number!(deserialize_f64);
318
319    forward_to_deserialize_any! {
320        bool char str string bytes byte_buf option unit unit_struct
321        newtype_struct seq tuple tuple_struct map struct enum identifier
322        ignored_any
323    }
324}
325
326impl From<ParserNumber> for Number {
327    fn from(value: ParserNumber) -> Self {
328        let n = match value {
329            ParserNumber::Float(f) => N::Float(f),
330            ParserNumber::Unsigned(u) => N::PosInt(u),
331            ParserNumber::Signed(i) => N::NegInt(i),
332        };
333        Number { n }
334    }
335}
336
337macro_rules! impl_from_unsigned {
338    (
339        $($ty:ty),*
340    ) => {
341        $(
342            impl From<$ty> for Number {
343                #[inline]
344                fn from(u: $ty) -> Self {
345                    let n = {
346                        { N::PosInt(u as u64) }
347                    };
348                    Number { n }
349                }
350            }
351        )*
352    };
353}
354
355macro_rules! impl_from_signed {
356    (
357        $($ty:ty),*
358    ) => {
359        $(
360            impl From<$ty> for Number {
361                #[inline]
362                fn from(i: $ty) -> Self {
363                    let n = {
364                            if i < 0 {
365                                N::NegInt(i as i64)
366                            } else {
367                                N::PosInt(i as u64)
368                            }
369                    };
370                    Number { n }
371                }
372            }
373        )*
374    };
375}
376
377impl_from_unsigned!(u8, u16, u32, u64, usize);
378impl_from_signed!(i8, i16, i32, i64, isize);
379
380impl TryFrom<f32> for Number {
381    type Error = crate::Error;
382    #[inline]
383    fn try_from(f: f32) -> Result<Self, Self::Error> {
384        Number::try_from(f as f64)
385    }
386}
387
388impl TryFrom<f64> for Number {
389    type Error = crate::Error;
390    fn try_from(value: f64) -> Result<Self, Self::Error> {
391        Number::from_f64(value)
392            .ok_or_else(|| make_error("NaN or Infinity is not a valid JSON value".to_string()))
393    }
394}