1use core::{
2 cmp::{Eq, Ordering},
3 hash::{Hash, Hasher},
4};
5
6use crate::error::{Error, Result};
7use serde::{de::Visitor, Serialize, Serializer};
8
9#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
37#[cfg_attr(doc, non_exhaustive)]
38pub enum Number {
39 I8(i8),
40 I16(i16),
41 I32(i32),
42 I64(i64),
43 #[cfg(feature = "integer128")]
44 I128(i128),
45 U8(u8),
46 U16(u16),
47 U32(u32),
48 U64(u64),
49 #[cfg(feature = "integer128")]
50 U128(u128),
51 F32(F32),
52 F64(F64),
53 #[cfg(not(doc))]
54 #[allow(private_interfaces)]
55 __NonExhaustive(private::Never),
56}
57
58mod private {
59 #[derive(Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
60 enum _Never {}
61
62 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
63 pub struct Never {
64 never: &'static _Never,
65 }
66
67 impl Never {
68 pub fn never(self) -> ! {
69 match *self.never {}
70 }
71 }
72
73 #[cfg(not(feature = "integer128"))]
74 fn _assert_non_exhaustive_check_fails_not_integer128() {}
92
93 #[cfg(feature = "integer128")]
94 fn _assert_non_exhaustive_check_fails_integer128() {}
114}
115
116impl Serialize for Number {
117 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
118 match self {
119 Self::I8(v) => serializer.serialize_i8(*v),
120 Self::I16(v) => serializer.serialize_i16(*v),
121 Self::I32(v) => serializer.serialize_i32(*v),
122 Self::I64(v) => serializer.serialize_i64(*v),
123 #[cfg(feature = "integer128")]
124 Self::I128(v) => serializer.serialize_i128(*v),
125 Self::U8(v) => serializer.serialize_u8(*v),
126 Self::U16(v) => serializer.serialize_u16(*v),
127 Self::U32(v) => serializer.serialize_u32(*v),
128 Self::U64(v) => serializer.serialize_u64(*v),
129 #[cfg(feature = "integer128")]
130 Self::U128(v) => serializer.serialize_u128(*v),
131 Self::F32(v) => serializer.serialize_f32(v.get()),
132 Self::F64(v) => serializer.serialize_f64(v.get()),
133 #[cfg(not(doc))]
134 Self::__NonExhaustive(never) => never.never(),
135 }
136 }
137}
138
139impl Number {
140 pub fn visit<'de, V: Visitor<'de>, E: serde::de::Error>(
141 &self,
142 visitor: V,
143 ) -> Result<V::Value, E> {
144 match self {
145 Self::I8(v) => visitor.visit_i8(*v),
146 Self::I16(v) => visitor.visit_i16(*v),
147 Self::I32(v) => visitor.visit_i32(*v),
148 Self::I64(v) => visitor.visit_i64(*v),
149 #[cfg(feature = "integer128")]
150 Self::I128(v) => visitor.visit_i128(*v),
151 Self::U8(v) => visitor.visit_u8(*v),
152 Self::U16(v) => visitor.visit_u16(*v),
153 Self::U32(v) => visitor.visit_u32(*v),
154 Self::U64(v) => visitor.visit_u64(*v),
155 #[cfg(feature = "integer128")]
156 Self::U128(v) => visitor.visit_u128(*v),
157 Self::F32(v) => visitor.visit_f32(v.get()),
158 Self::F64(v) => visitor.visit_f64(v.get()),
159 #[cfg(not(doc))]
160 Self::__NonExhaustive(never) => never.never(),
161 }
162 }
163}
164
165macro_rules! float_ty {
166 ($ty:ident($float:ty)) => {
167 #[doc = concat!(
168 "A wrapper for [`", stringify!($float), "`], which implements [`Eq`], ",
169 "[`Hash`] and [`Ord`] using [`", stringify!($float), "::total_cmp`] ",
170 "for a total order comparison",
171 )]
172 #[derive(Copy, Clone, Debug)] pub struct $ty(pub $float);
174
175 impl $ty {
176 #[doc = concat!("Construct a new [`", stringify!($ty), "`].")]
177 #[must_use]
178 pub fn new(v: $float) -> Self {
179 Self(v)
180 }
181
182 #[doc = concat!("Returns the wrapped [`", stringify!($float), "`].")]
183 #[must_use]
184 pub fn get(self) -> $float {
185 self.0
186 }
187 }
188
189 impl From<$float> for $ty {
190 fn from(v: $float) -> Self {
191 Self::new(v)
192 }
193 }
194
195 #[doc = concat!(
198 "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
199 "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
200 "order comparison.",
201 )]
202 impl PartialEq for $ty {
205 fn eq(&self, other: &Self) -> bool {
206 self.cmp(other).is_eq()
207 }
208 }
209
210 #[doc = concat!(
213 "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
214 "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
215 "order comparison.",
216 )]
217 impl Eq for $ty {}
220
221 impl Hash for $ty {
222 fn hash<H: Hasher>(&self, state: &mut H) {
223 self.0.to_bits().hash(state);
224 }
225 }
226
227 #[doc = concat!(
230 "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
231 "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
232 "order comparison.",
233 )]
234 impl PartialOrd for $ty {
237 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
238 Some(self.cmp(other))
239 }
240 }
241
242 #[doc = concat!(
245 "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
246 "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
247 "order comparison.",
248 )]
249 #[doc = concat!("use ron::value::", stringify!($ty), ";")]
252 #[doc = concat!(
253 "assert!(", stringify!($ty), "::new(", stringify!($float), "::NAN) > ",
254 stringify!($ty), "::new(", stringify!($float), "::INFINITY));",
255 )]
256 #[doc = concat!(
257 "assert!(", stringify!($ty), "::new(-", stringify!($float), "::NAN) < ",
258 stringify!($ty), "::new(", stringify!($float), "::NEG_INFINITY));",
259 )]
260 #[doc = concat!(
261 "assert!(", stringify!($ty), "::new(", stringify!($float), "::NAN) == ",
262 stringify!($ty), "::new(", stringify!($float), "::NAN));",
263 )]
264 impl Ord for $ty {
266 fn cmp(&self, other: &Self) -> Ordering {
267 self.0.total_cmp(&other.0)
268 }
269 }
270 };
271}
272
273float_ty! { F32(f32) }
274float_ty! { F64(f64) }
275
276impl Number {
277 pub fn new(v: impl Into<Number>) -> Self {
279 v.into()
280 }
281
282 #[must_use]
295 pub fn into_f64(self) -> f64 {
296 #[allow(clippy::cast_precision_loss)]
297 match self {
298 Self::I8(v) => f64::from(v),
299 Self::I16(v) => f64::from(v),
300 Self::I32(v) => f64::from(v),
301 Self::I64(v) => v as f64,
302 #[cfg(feature = "integer128")]
303 Self::I128(v) => v as f64,
304 Self::U8(v) => f64::from(v),
305 Self::U16(v) => f64::from(v),
306 Self::U32(v) => f64::from(v),
307 Self::U64(v) => v as f64,
308 #[cfg(feature = "integer128")]
309 Self::U128(v) => v as f64,
310 Self::F32(v) => f64::from(v.get()),
311 Self::F64(v) => v.get(),
312 #[cfg(not(doc))]
313 Self::__NonExhaustive(never) => never.never(),
314 }
315 }
316}
317
318macro_rules! number_from_impl {
319 (Number::$variant:ident($wrap:ident($ty:ty))) => {
320 impl From<$ty> for Number {
321 fn from(v: $ty) -> Number {
322 Number::$variant($wrap(v))
323 }
324 }
325 };
326 (Number::$variant:ident($ty:ty)) => {
327 impl From<$ty> for Number {
328 fn from(v: $ty) -> Number {
329 Number::$variant(v)
330 }
331 }
332 };
333}
334
335number_from_impl! { Number::I8(i8) }
336number_from_impl! { Number::I16(i16) }
337number_from_impl! { Number::I32(i32) }
338number_from_impl! { Number::I64(i64) }
339#[cfg(feature = "integer128")]
340number_from_impl! { Number::I128(i128) }
341number_from_impl! { Number::U8(u8) }
342number_from_impl! { Number::U16(u16) }
343number_from_impl! { Number::U32(u32) }
344number_from_impl! { Number::U64(u64) }
345#[cfg(feature = "integer128")]
346number_from_impl! { Number::U128(u128) }
347number_from_impl! { Number::F32(F32(f32)) }
348number_from_impl! { Number::F64(F64(f64)) }
349
350#[allow(clippy::module_name_repetitions)]
353pub struct NumberSerializer;
354
355impl serde::Serializer for NumberSerializer {
356 type Ok = Number;
357 type Error = Error;
358 type SerializeSeq = serde::ser::Impossible<Number, Error>;
359 type SerializeTuple = serde::ser::Impossible<Number, Error>;
360 type SerializeTupleStruct = serde::ser::Impossible<Number, Error>;
361 type SerializeTupleVariant = serde::ser::Impossible<Number, Error>;
362 type SerializeMap = serde::ser::Impossible<Number, Error>;
363 type SerializeStruct = serde::ser::Impossible<Number, Error>;
364 type SerializeStructVariant = serde::ser::Impossible<Number, Error>;
365
366 fn serialize_i8(self, v: i8) -> Result<Number> {
367 Ok(Number::new(v))
368 }
369 fn serialize_i16(self, v: i16) -> Result<Number> {
370 Ok(Number::new(v))
371 }
372 fn serialize_i32(self, v: i32) -> Result<Number> {
373 Ok(Number::new(v))
374 }
375 fn serialize_i64(self, v: i64) -> Result<Number> {
376 Ok(Number::new(v))
377 }
378 fn serialize_u8(self, v: u8) -> Result<Number> {
379 Ok(Number::new(v))
380 }
381 fn serialize_u16(self, v: u16) -> Result<Number> {
382 Ok(Number::new(v))
383 }
384 fn serialize_u32(self, v: u32) -> Result<Number> {
385 Ok(Number::new(v))
386 }
387 fn serialize_u64(self, v: u64) -> Result<Number> {
388 Ok(Number::new(v))
389 }
390 fn serialize_f32(self, v: f32) -> Result<Number> {
391 Ok(Number::new(v))
392 }
393 fn serialize_f64(self, v: f64) -> Result<Number> {
394 Ok(Number::new(v))
395 }
396 #[cfg(feature = "integer128")]
397 fn serialize_i128(self, v: i128) -> Result<Number> {
398 Ok(Number::new(v))
399 }
400 #[cfg(feature = "integer128")]
401 fn serialize_u128(self, v: u128) -> Result<Number> {
402 Ok(Number::new(v))
403 }
404
405 fn serialize_bool(self, _: bool) -> Result<Number> {
406 Err(Error::InvalidValueForType {
407 expected: alloc::string::String::from("number"),
408 found: alloc::string::String::from("bool"),
409 })
410 }
411 fn serialize_char(self, _: char) -> Result<Number> {
412 Err(Error::InvalidValueForType {
413 expected: alloc::string::String::from("number"),
414 found: alloc::string::String::from("char"),
415 })
416 }
417 fn serialize_str(self, _: &str) -> Result<Number> {
418 Err(Error::InvalidValueForType {
419 expected: alloc::string::String::from("number"),
420 found: alloc::string::String::from("string"),
421 })
422 }
423 fn serialize_bytes(self, _: &[u8]) -> Result<Number> {
424 Err(Error::InvalidValueForType {
425 expected: alloc::string::String::from("number"),
426 found: alloc::string::String::from("bytes"),
427 })
428 }
429 fn serialize_none(self) -> Result<Number> {
430 Err(Error::InvalidValueForType {
431 expected: alloc::string::String::from("number"),
432 found: alloc::string::String::from("None"),
433 })
434 }
435 fn serialize_some<T: ?Sized + Serialize>(self, _: &T) -> Result<Number> {
436 Err(Error::InvalidValueForType {
437 expected: alloc::string::String::from("number"),
438 found: alloc::string::String::from("Some"),
439 })
440 }
441 fn serialize_unit(self) -> Result<Number> {
442 Err(Error::InvalidValueForType {
443 expected: alloc::string::String::from("number"),
444 found: alloc::string::String::from("unit"),
445 })
446 }
447 fn serialize_unit_struct(self, _: &'static str) -> Result<Number> {
448 Err(Error::InvalidValueForType {
449 expected: alloc::string::String::from("number"),
450 found: alloc::string::String::from("unit struct"),
451 })
452 }
453 fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<Number> {
454 Err(Error::InvalidValueForType {
455 expected: alloc::string::String::from("number"),
456 found: alloc::string::String::from("unit variant"),
457 })
458 }
459 fn serialize_newtype_struct<T: ?Sized + Serialize>(
460 self,
461 _: &'static str,
462 _: &T,
463 ) -> Result<Number> {
464 Err(Error::InvalidValueForType {
465 expected: alloc::string::String::from("number"),
466 found: alloc::string::String::from("newtype struct"),
467 })
468 }
469 fn serialize_newtype_variant<T: ?Sized + Serialize>(
470 self,
471 _: &'static str,
472 _: u32,
473 _: &'static str,
474 _: &T,
475 ) -> Result<Number> {
476 Err(Error::InvalidValueForType {
477 expected: alloc::string::String::from("number"),
478 found: alloc::string::String::from("newtype variant"),
479 })
480 }
481 fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq> {
482 Err(Error::InvalidValueForType {
483 expected: alloc::string::String::from("number"),
484 found: alloc::string::String::from("seq"),
485 })
486 }
487 fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple> {
488 Err(Error::InvalidValueForType {
489 expected: alloc::string::String::from("number"),
490 found: alloc::string::String::from("tuple"),
491 })
492 }
493 fn serialize_tuple_struct(
494 self,
495 _: &'static str,
496 _: usize,
497 ) -> Result<Self::SerializeTupleStruct> {
498 Err(Error::InvalidValueForType {
499 expected: alloc::string::String::from("number"),
500 found: alloc::string::String::from("tuple struct"),
501 })
502 }
503 fn serialize_tuple_variant(
504 self,
505 _: &'static str,
506 _: u32,
507 _: &'static str,
508 _: usize,
509 ) -> Result<Self::SerializeTupleVariant> {
510 Err(Error::InvalidValueForType {
511 expected: alloc::string::String::from("number"),
512 found: alloc::string::String::from("tuple variant"),
513 })
514 }
515 fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap> {
516 Err(Error::InvalidValueForType {
517 expected: alloc::string::String::from("number"),
518 found: alloc::string::String::from("map"),
519 })
520 }
521 fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct> {
522 Err(Error::InvalidValueForType {
523 expected: alloc::string::String::from("number"),
524 found: alloc::string::String::from("struct"),
525 })
526 }
527 fn serialize_struct_variant(
528 self,
529 _: &'static str,
530 _: u32,
531 _: &'static str,
532 _: usize,
533 ) -> Result<Self::SerializeStructVariant> {
534 Err(Error::InvalidValueForType {
535 expected: alloc::string::String::from("number"),
536 found: alloc::string::String::from("struct variant"),
537 })
538 }
539}
540
541pub(crate) struct NumberDeserializer(pub(crate) Number);
542
543impl<'de> serde::de::Deserializer<'de> for NumberDeserializer {
544 type Error = crate::error::Error;
545
546 fn deserialize_any<V: serde::de::Visitor<'de>>(
547 self,
548 visitor: V,
549 ) -> crate::error::Result<V::Value> {
550 self.0.visit(visitor)
551 }
552
553 serde::forward_to_deserialize_any! {
554 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64
555 char str string bytes byte_buf option unit unit_struct
556 newtype_struct seq tuple tuple_struct map struct enum identifier ignored_any
557 }
558}
559
560#[cfg(test)]
561mod tests {
562 use super::*;
563
564 #[test]
565 fn test_nan() {
566 assert_eq!(F32(f32::NAN), F32(f32::NAN));
567 assert_eq!(F32(-f32::NAN), F32(-f32::NAN));
568 assert_ne!(F32(f32::NAN), F32(-f32::NAN));
569 }
570
571 #[cfg(feature = "std")]
572 #[test]
573 fn test_nan_hash() {
574 use std::collections::hash_map::DefaultHasher;
575 use std::hash::{Hash, Hasher};
576
577 fn hash<T: Hash>(v: &T) -> u64 {
578 let mut state = DefaultHasher::new();
579 v.hash(&mut state);
580 state.finish()
581 }
582
583 assert_eq!(hash(&F32(f32::NAN)), hash(&F32(f32::NAN)));
584 assert_eq!(hash(&F32(-f32::NAN)), hash(&F32(-f32::NAN)));
585 assert_ne!(hash(&F32(f32::NAN)), hash(&F32(-f32::NAN)));
586 }
587
588 #[test]
589 fn test_partial_ord() {
590 assert!(F32(f32::NAN) > F32(f32::INFINITY));
591 assert!(F32(-f32::NAN) < F32(f32::NEG_INFINITY));
592 assert!(F32(f32::NAN) == F32(f32::NAN));
593 }
594}