1use sonic_number::ParserNumber;
4
5use crate::{error::make_error, util::private::Sealed};
6
7#[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 NegInt(i64),
18 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
45impl 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 0.0f64.to_bits().hash(h);
59 } else {
60 f.to_bits().hash(h);
61 }
62 }
63 }
64 }
65}
66
67pub 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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}