1
use core::{
2
    cmp::{Eq, Ordering},
3
    hash::{Hash, Hasher},
4
};
5

            
6
use crate::error::{Error, Result};
7
use serde::{de::Visitor, Serialize, Serializer};
8

            
9
/// A wrapper for any numeric primitive type in Rust.
10
///
11
/// Some varints of the `Number` enum are enabled by features:
12
/// - `Number::I128` and `Number::U128` by the `integer128` feature
13
///
14
/// To ensure that feature unification does not break `match`ing over `Number`,
15
/// the `Number` enum is non-exhaustive.
16
///
17
/// <details>
18
/// <summary>Exhaustively matching on <code>Number</code> in tests</summary>
19
///
20
/// If you want to ensure that you exhaustively handle every variant, you can
21
/// match on the hidden `Number::__NonExhaustive(x)` variant by using the
22
/// `x.never() -> !` method.
23
///
24
/// <div class="warning">
25
/// Matching on this variant means that your code may break when RON is
26
/// upgraded or when feature unification enables further variants in the
27
/// <code>Number</code> enum than your code expects.
28
/// </div>
29
///
30
/// It is your responsibility to only *ever* match on `Number::__NonExhaustive`
31
/// inside tests, e.g. by using `#[cfg(test)]` on the particular match arm, to
32
/// ensure that only your tests break (e.g. in CI) when your code is not
33
/// exhaustively matching on every variant, e.g. after a version upgrade or
34
/// feature unification.
35
/// </details>
36
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
37
#[cfg_attr(doc, non_exhaustive)]
38
pub 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

            
58
mod 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
    /// ```compile_fail
75
    /// # use ron::Number;
76
    /// fn match_number(x: Number) {
77
    ///     match x {
78
    ///         Number::I8(v) => println!("i8: {}", v),
79
    ///         Number::I16(v) => println!("i16: {}", v),
80
    ///         Number::I32(v) => println!("i32: {}", v),
81
    ///         Number::I64(v) => println!("i64: {}", v),
82
    ///         Number::U8(v) => println!("u8: {}", v),
83
    ///         Number::U16(v) => println!("u16: {}", v),
84
    ///         Number::U32(v) => println!("u32: {}", v),
85
    ///         Number::U64(v) => println!("u64: {}", v),
86
    ///         Number::F32(v) => println!("f32: {}", v.0),
87
    ///         Number::F64(v) => println!("f64: {}", v.0),
88
    ///     }
89
    /// }
90
    /// ```
91
    fn _assert_non_exhaustive_check_fails_not_integer128() {}
92

            
93
    #[cfg(feature = "integer128")]
94
    /// ```compile_fail
95
    /// # use ron::Number;
96
    /// fn match_number(x: Number) {
97
    ///     match x {
98
    ///         Number::I8(v) => println!("i8: {}", v),
99
    ///         Number::I16(v) => println!("i16: {}", v),
100
    ///         Number::I32(v) => println!("i32: {}", v),
101
    ///         Number::I64(v) => println!("i64: {}", v),
102
    ///         Number::I128(v) => println!("i128: {}", v),
103
    ///         Number::U8(v) => println!("u8: {}", v),
104
    ///         Number::U16(v) => println!("u16: {}", v),
105
    ///         Number::U32(v) => println!("u32: {}", v),
106
    ///         Number::U64(v) => println!("u64: {}", v),
107
    ///         Number::U128(v) => println!("u128: {}", v),
108
    ///         Number::F32(v) => println!("f32: {}", v.0),
109
    ///         Number::F64(v) => println!("f64: {}", v.0),
110
    ///     }
111
    /// }
112
    /// ```
113
    fn _assert_non_exhaustive_check_fails_integer128() {}
114
}
115

            
116
impl Serialize for Number {
117
728
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
118
728
        match self {
119
56
            Self::I8(v) => serializer.serialize_i8(*v),
120
40
            Self::I16(v) => serializer.serialize_i16(*v),
121
68
            Self::I32(v) => serializer.serialize_i32(*v),
122
40
            Self::I64(v) => serializer.serialize_i64(*v),
123
            #[cfg(feature = "integer128")]
124
20
            Self::I128(v) => serializer.serialize_i128(*v),
125
88
            Self::U8(v) => serializer.serialize_u8(*v),
126
40
            Self::U16(v) => serializer.serialize_u16(*v),
127
40
            Self::U32(v) => serializer.serialize_u32(*v),
128
40
            Self::U64(v) => serializer.serialize_u64(*v),
129
            #[cfg(feature = "integer128")]
130
20
            Self::U128(v) => serializer.serialize_u128(*v),
131
196
            Self::F32(v) => serializer.serialize_f32(v.get()),
132
80
            Self::F64(v) => serializer.serialize_f64(v.get()),
133
            #[cfg(not(doc))]
134
            Self::__NonExhaustive(never) => never.never(),
135
        }
136
728
    }
137
}
138

            
139
impl Number {
140
9399806
    pub fn visit<'de, V: Visitor<'de>, E: serde::de::Error>(
141
9399806
        &self,
142
9399806
        visitor: V,
143
9399806
    ) -> Result<V::Value, E> {
144
9399806
        match self {
145
604
            Self::I8(v) => visitor.visit_i8(*v),
146
588
            Self::I16(v) => visitor.visit_i16(*v),
147
600
            Self::I32(v) => visitor.visit_i32(*v),
148
588
            Self::I64(v) => visitor.visit_i64(*v),
149
            #[cfg(feature = "integer128")]
150
298
            Self::I128(v) => visitor.visit_i128(*v),
151
264130
            Self::U8(v) => visitor.visit_u8(*v),
152
604
            Self::U16(v) => visitor.visit_u16(*v),
153
588
            Self::U32(v) => visitor.visit_u32(*v),
154
588
            Self::U64(v) => visitor.visit_u64(*v),
155
            #[cfg(feature = "integer128")]
156
447
            Self::U128(v) => visitor.visit_u128(*v),
157
7025
            Self::F32(v) => visitor.visit_f32(v.get()),
158
9123746
            Self::F64(v) => visitor.visit_f64(v.get()),
159
            #[cfg(not(doc))]
160
            Self::__NonExhaustive(never) => never.never(),
161
        }
162
9399806
    }
163
}
164

            
165
macro_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)] // GRCOV_EXCL_LINE
173
        pub struct $ty(pub $float);
174

            
175
        impl $ty {
176
            #[doc = concat!("Construct a new [`", stringify!($ty), "`].")]
177
            #[must_use]
178
9128272
            pub fn new(v: $float) -> Self {
179
9128272
                Self(v)
180
9128272
            }
181

            
182
            #[doc = concat!("Returns the wrapped [`", stringify!($float), "`].")]
183
            #[must_use]
184
9144145
            pub fn get(self) -> $float {
185
9144145
                self.0
186
9144145
            }
187
        }
188

            
189
        impl From<$float> for $ty {
190
9128272
            fn from(v: $float) -> Self {
191
9128272
                Self::new(v)
192
9128272
            }
193
        }
194

            
195
        /// Partial equality comparison
196
        ///
197
        #[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
        ///
203
        /// See the [`Ord`] implementation.
204
        impl PartialEq for $ty {
205
18575
            fn eq(&self, other: &Self) -> bool {
206
18575
                self.cmp(other).is_eq()
207
18575
            }
208
        }
209

            
210
        /// Equality comparison
211
        ///
212
        #[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
        ///
218
        /// See the [`Ord`] implementation.
219
        impl Eq for $ty {}
220

            
221
        impl Hash for $ty {
222
24
            fn hash<H: Hasher>(&self, state: &mut H) {
223
24
                self.0.to_bits().hash(state);
224
24
            }
225
        }
226

            
227
        /// Partial ordering comparison
228
        ///
229
        #[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
        ///
235
        /// See the [`Ord`] implementation.
236
        impl PartialOrd for $ty {
237
8
            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
238
8
                Some(self.cmp(other))
239
8
            }
240
        }
241

            
242
        /// Ordering comparison
243
        ///
244
        #[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
        ///
250
        /// ```
251
        #[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
        /// ```
265
        impl Ord for $ty {
266
18885
            fn cmp(&self, other: &Self) -> Ordering {
267
18885
                self.0.total_cmp(&other.0)
268
18885
            }
269
        }
270
    };
271
}
272

            
273
float_ty! { F32(f32) }
274
float_ty! { F64(f64) }
275

            
276
impl Number {
277
    /// Construct a new number.
278
9372326
    pub fn new(v: impl Into<Number>) -> Self {
279
9372326
        v.into()
280
9372326
    }
281

            
282
    /// Returns the [`f64`] representation of the [`Number`] regardless of
283
    /// whether the number is stored as a float or integer.
284
    ///
285
    /// # Example
286
    ///
287
    /// ```
288
    /// # use ron::value::Number;
289
    /// let i = Number::new(5);
290
    /// let f = Number::new(2.0);
291
    /// assert_eq!(i.into_f64(), 5.0);
292
    /// assert_eq!(f.into_f64(), 2.0);
293
    /// ```
294
    #[must_use]
295
8820
    pub fn into_f64(self) -> f64 {
296
        #[allow(clippy::cast_precision_loss)]
297
8820
        match self {
298
588
            Self::I8(v) => f64::from(v),
299
588
            Self::I16(v) => f64::from(v),
300
588
            Self::I32(v) => f64::from(v),
301
588
            Self::I64(v) => v as f64,
302
            #[cfg(feature = "integer128")]
303
294
            Self::I128(v) => v as f64,
304
588
            Self::U8(v) => f64::from(v),
305
588
            Self::U16(v) => f64::from(v),
306
588
            Self::U32(v) => f64::from(v),
307
588
            Self::U64(v) => v as f64,
308
            #[cfg(feature = "integer128")]
309
294
            Self::U128(v) => v as f64,
310
1764
            Self::F32(v) => f64::from(v.get()),
311
1764
            Self::F64(v) => v.get(),
312
            #[cfg(not(doc))]
313
            Self::__NonExhaustive(never) => never.never(),
314
        }
315
8820
    }
316
}
317

            
318
macro_rules! number_from_impl {
319
    (Number::$variant:ident($wrap:ident($ty:ty))) => {
320
        impl From<$ty> for Number {
321
9155043
            fn from(v: $ty) -> Number {
322
9155043
                Number::$variant($wrap(v))
323
9155043
            }
324
        }
325
    };
326
    (Number::$variant:ident($ty:ty)) => {
327
        impl From<$ty> for Number {
328
253487
            fn from(v: $ty) -> Number {
329
253487
                Number::$variant(v)
330
253487
            }
331
        }
332
    };
333
}
334

            
335
number_from_impl! { Number::I8(i8) }
336
number_from_impl! { Number::I16(i16) }
337
number_from_impl! { Number::I32(i32) }
338
number_from_impl! { Number::I64(i64) }
339
#[cfg(feature = "integer128")]
340
number_from_impl! { Number::I128(i128) }
341
number_from_impl! { Number::U8(u8) }
342
number_from_impl! { Number::U16(u16) }
343
number_from_impl! { Number::U32(u32) }
344
number_from_impl! { Number::U64(u64) }
345
#[cfg(feature = "integer128")]
346
number_from_impl! { Number::U128(u128) }
347
number_from_impl! { Number::F32(F32(f32)) }
348
number_from_impl! { Number::F64(F64(f64)) }
349

            
350
/// A serializer that only accepts numeric values, returning a [`Number`].
351
/// Used by [`crate::ser::RangeCompound`] to detect whether range bounds are numeric.
352
#[allow(clippy::module_name_repetitions)]
353
pub struct NumberSerializer;
354

            
355
impl 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
2058
    fn serialize_i32(self, v: i32) -> Result<Number> {
373
2058
        Ok(Number::new(v))
374
2058
    }
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
2058
    fn serialize_f32(self, v: f32) -> Result<Number> {
391
2058
        Ok(Number::new(v))
392
2058
    }
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
294
    fn serialize_str(self, _: &str) -> Result<Number> {
418
294
        Err(Error::InvalidValueForType {
419
294
            expected: alloc::string::String::from("number"),
420
294
            found: alloc::string::String::from("string"),
421
294
        })
422
294
    }
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

            
541
pub(crate) struct NumberDeserializer(pub(crate) Number);
542

            
543
impl<'de> serde::de::Deserializer<'de> for NumberDeserializer {
544
    type Error = crate::error::Error;
545

            
546
80
    fn deserialize_any<V: serde::de::Visitor<'de>>(
547
80
        self,
548
80
        visitor: V,
549
80
    ) -> crate::error::Result<V::Value> {
550
80
        self.0.visit(visitor)
551
80
    }
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)]
561
mod tests {
562
    use super::*;
563

            
564
    #[test]
565
4
    fn test_nan() {
566
4
        assert_eq!(F32(f32::NAN), F32(f32::NAN));
567
4
        assert_eq!(F32(-f32::NAN), F32(-f32::NAN));
568
4
        assert_ne!(F32(f32::NAN), F32(-f32::NAN));
569
4
    }
570

            
571
    #[cfg(feature = "std")]
572
    #[test]
573
4
    fn test_nan_hash() {
574
        use std::collections::hash_map::DefaultHasher;
575
        use std::hash::{Hash, Hasher};
576

            
577
24
        fn hash<T: Hash>(v: &T) -> u64 {
578
24
            let mut state = DefaultHasher::new();
579
24
            v.hash(&mut state);
580
24
            state.finish()
581
24
        }
582

            
583
4
        assert_eq!(hash(&F32(f32::NAN)), hash(&F32(f32::NAN)));
584
4
        assert_eq!(hash(&F32(-f32::NAN)), hash(&F32(-f32::NAN)));
585
4
        assert_ne!(hash(&F32(f32::NAN)), hash(&F32(-f32::NAN)));
586
4
    }
587

            
588
    #[test]
589
4
    fn test_partial_ord() {
590
4
        assert!(F32(f32::NAN) > F32(f32::INFINITY));
591
4
        assert!(F32(-f32::NAN) < F32(f32::NEG_INFINITY));
592
4
        assert!(F32(f32::NAN) == F32(f32::NAN));
593
4
    }
594
}