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

            
6
use crate::{
7
    error::{Error, Result},
8
    extensions::Extensions,
9
};
10
use serde::{de::Visitor, Serialize, Serializer};
11

            
12
/// A wrapper for any numeric primitive type in Rust.
13
///
14
/// Some varints of the `Number` enum are enabled by features:
15
/// - `Number::I128` and `Number::U128` by the `integer128` feature
16
///
17
/// To ensure that feature unification does not break `match`ing over `Number`,
18
/// the `Number` enum is non-exhaustive.
19
///
20
/// <details>
21
/// <summary>Exhaustively matching on <code>Number</code> in tests</summary>
22
///
23
/// If you want to ensure that you exhaustively handle every variant, you can
24
/// match on the hidden `Number::__NonExhaustive(x)` variant by using the
25
/// `x.never() -> !` method.
26
///
27
/// <div class="warning">
28
/// Matching on this variant means that your code may break when RON is
29
/// upgraded or when feature unification enables further variants in the
30
/// <code>Number</code> enum than your code expects.
31
/// </div>
32
///
33
/// It is your responsibility to only *ever* match on `Number::__NonExhaustive`
34
/// inside tests, e.g. by using `#[cfg(test)]` on the particular match arm, to
35
/// ensure that only your tests break (e.g. in CI) when your code is not
36
/// exhaustively matching on every variant, e.g. after a version upgrade or
37
/// feature unification.
38
/// </details>
39
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
40
#[cfg_attr(doc, non_exhaustive)]
41
pub enum Number {
42
    I8(i8),
43
    I16(i16),
44
    I32(i32),
45
    I64(i64),
46
    #[cfg(feature = "integer128")]
47
    I128(i128),
48
    U8(u8),
49
    U16(u16),
50
    U32(u32),
51
    U64(u64),
52
    #[cfg(feature = "integer128")]
53
    U128(u128),
54
    F32(F32),
55
    F64(F64),
56
    #[cfg(not(doc))]
57
    #[allow(private_interfaces)]
58
    __NonExhaustive(private::Never),
59
}
60

            
61
mod private {
62
    #[derive(Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
63
    enum _Never {}
64

            
65
    #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Hash, Ord)]
66
    pub struct Never {
67
        never: &'static _Never,
68
    }
69

            
70
    impl Never {
71
        pub fn never(self) -> ! {
72
            match *self.never {}
73
        }
74
    }
75

            
76
    #[cfg(not(feature = "integer128"))]
77
    /// ```compile_fail
78
    /// # use ron::Number;
79
    /// fn match_number(x: Number) {
80
    ///     match x {
81
    ///         Number::I8(v) => println!("i8: {}", v),
82
    ///         Number::I16(v) => println!("i16: {}", v),
83
    ///         Number::I32(v) => println!("i32: {}", v),
84
    ///         Number::I64(v) => println!("i64: {}", v),
85
    ///         Number::U8(v) => println!("u8: {}", v),
86
    ///         Number::U16(v) => println!("u16: {}", v),
87
    ///         Number::U32(v) => println!("u32: {}", v),
88
    ///         Number::U64(v) => println!("u64: {}", v),
89
    ///         Number::F32(v) => println!("f32: {}", v.0),
90
    ///         Number::F64(v) => println!("f64: {}", v.0),
91
    ///     }
92
    /// }
93
    /// ```
94
    fn _assert_non_exhaustive_check_fails_not_integer128() {}
95

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

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

            
142
impl Number {
143
9933722
    pub fn visit<'de, V: Visitor<'de>, E: serde::de::Error>(
144
9933722
        &self,
145
9933722
        visitor: V,
146
9933722
    ) -> Result<V::Value, E> {
147
9933722
        match self {
148
644
            Self::I8(v) => visitor.visit_i8(*v),
149
620
            Self::I16(v) => visitor.visit_i16(*v),
150
632
            Self::I32(v) => visitor.visit_i32(*v),
151
620
            Self::I64(v) => visitor.visit_i64(*v),
152
            #[cfg(feature = "integer128")]
153
314
            Self::I128(v) => visitor.visit_i128(*v),
154
291192
            Self::U8(v) => visitor.visit_u8(*v),
155
636
            Self::U16(v) => visitor.visit_u16(*v),
156
620
            Self::U32(v) => visitor.visit_u32(*v),
157
620
            Self::U64(v) => visitor.visit_u64(*v),
158
            #[cfg(feature = "integer128")]
159
471
            Self::U128(v) => visitor.visit_u128(*v),
160
15219
            Self::F32(v) => visitor.visit_f32(v.get()),
161
9622134
            Self::F64(v) => visitor.visit_f64(v.get()),
162
            #[cfg(not(doc))]
163
            Self::__NonExhaustive(never) => never.never(),
164
        }
165
9933722
    }
166
}
167

            
168
macro_rules! float_ty {
169
    ($ty:ident($float:ty)) => {
170
        #[doc = concat!(
171
                    "A wrapper for [`", stringify!($float), "`], which implements [`Eq`], ",
172
                    "[`Hash`] and [`Ord`] using [`", stringify!($float), "::total_cmp`] ",
173
                    "for a total order comparison",
174
                )]
175
        #[derive(Copy, Clone, Debug)] // GRCOV_EXCL_LINE
176
        pub struct $ty(pub $float);
177

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

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

            
192
        impl From<$float> for $ty {
193
9633100
            fn from(v: $float) -> Self {
194
9633100
                Self::new(v)
195
9633100
            }
196
        }
197

            
198
        /// Partial equality comparison
199
        ///
200
        #[doc = concat!(
201
                    "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
202
                    "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
203
                    "order comparison.",
204
                )]
205
        ///
206
        /// See the [`Ord`] implementation.
207
        impl PartialEq for $ty {
208
21745
            fn eq(&self, other: &Self) -> bool {
209
21745
                self.cmp(other).is_eq()
210
21745
            }
211
        }
212

            
213
        /// Equality comparison
214
        ///
215
        #[doc = concat!(
216
                    "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
217
                    "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
218
                    "order comparison.",
219
                )]
220
        ///
221
        /// See the [`Ord`] implementation.
222
        impl Eq for $ty {}
223

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

            
230
        /// Partial ordering comparison
231
        ///
232
        #[doc = concat!(
233
                    "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
234
                    "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
235
                    "order comparison.",
236
                )]
237
        ///
238
        /// See the [`Ord`] implementation.
239
        impl PartialOrd for $ty {
240
8
            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
241
8
                Some(self.cmp(other))
242
8
            }
243
        }
244

            
245
        /// Ordering comparison
246
        ///
247
        #[doc = concat!(
248
                    "In order to be able to use [`", stringify!($ty), "`] as a mapping key, ",
249
                    "floating values use [`", stringify!($float), "::total_cmp`] for a total ",
250
                    "order comparison.",
251
                )]
252
        ///
253
        /// ```
254
        #[doc = concat!("use ron::value::", stringify!($ty), ";")]
255
        #[doc = concat!(
256
                    "assert!(", stringify!($ty), "::new(", stringify!($float), "::NAN) > ",
257
                    stringify!($ty), "::new(", stringify!($float), "::INFINITY));",
258
                )]
259
        #[doc = concat!(
260
                    "assert!(", stringify!($ty), "::new(-", stringify!($float), "::NAN) < ",
261
                    stringify!($ty), "::new(", stringify!($float), "::NEG_INFINITY));",
262
                )]
263
        #[doc = concat!(
264
                    "assert!(", stringify!($ty), "::new(", stringify!($float), "::NAN) == ",
265
                    stringify!($ty), "::new(", stringify!($float), "::NAN));",
266
                )]
267
        /// ```
268
        impl Ord for $ty {
269
26411
            fn cmp(&self, other: &Self) -> Ordering {
270
26411
                self.0.total_cmp(&other.0)
271
26411
            }
272
        }
273
    };
274
}
275

            
276
float_ty! { F32(f32) }
277
float_ty! { F64(f64) }
278

            
279
impl Number {
280
    /// Construct a new number.
281
9901268
    pub fn new(v: impl Into<Number>) -> Self {
282
9901268
        v.into()
283
9901268
    }
284

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

            
321
macro_rules! number_from_impl {
322
    (Number::$variant:ident($wrap:ident($ty:ty))) => {
323
        impl From<$ty> for Number {
324
9668139
            fn from(v: $ty) -> Number {
325
9668139
                Number::$variant($wrap(v))
326
9668139
            }
327
        }
328
    };
329
    (Number::$variant:ident($ty:ty)) => {
330
        impl From<$ty> for Number {
331
271285
            fn from(v: $ty) -> Number {
332
271285
                Number::$variant(v)
333
271285
            }
334
        }
335
    };
336
}
337

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

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

            
358
impl serde::Serializer for NumberSerializer {
359
    type Ok = Number;
360
    type Error = Error;
361
    type SerializeSeq = serde::ser::Impossible<Number, Error>;
362
    type SerializeTuple = serde::ser::Impossible<Number, Error>;
363
    type SerializeTupleStruct = serde::ser::Impossible<Number, Error>;
364
    type SerializeTupleVariant = serde::ser::Impossible<Number, Error>;
365
    type SerializeMap = serde::ser::Impossible<Number, Error>;
366
    type SerializeStruct = serde::ser::Impossible<Number, Error>;
367
    type SerializeStructVariant = serde::ser::Impossible<Number, Error>;
368

            
369
    fn serialize_i8(self, v: i8) -> Result<Number> {
370
        Ok(Number::new(v))
371
    }
372
    fn serialize_i16(self, v: i16) -> Result<Number> {
373
        Ok(Number::new(v))
374
    }
375
2790
    fn serialize_i32(self, v: i32) -> Result<Number> {
376
2790
        Ok(Number::new(v))
377
2790
    }
378
    fn serialize_i64(self, v: i64) -> Result<Number> {
379
        Ok(Number::new(v))
380
    }
381
    fn serialize_u8(self, v: u8) -> Result<Number> {
382
        Ok(Number::new(v))
383
    }
384
    fn serialize_u16(self, v: u16) -> Result<Number> {
385
        Ok(Number::new(v))
386
    }
387
    fn serialize_u32(self, v: u32) -> Result<Number> {
388
        Ok(Number::new(v))
389
    }
390
    fn serialize_u64(self, v: u64) -> Result<Number> {
391
        Ok(Number::new(v))
392
    }
393
2170
    fn serialize_f32(self, v: f32) -> Result<Number> {
394
2170
        Ok(Number::new(v))
395
2170
    }
396
3410
    fn serialize_f64(self, v: f64) -> Result<Number> {
397
3410
        Ok(Number::new(v))
398
3410
    }
399
    #[cfg(feature = "integer128")]
400
    fn serialize_i128(self, v: i128) -> Result<Number> {
401
        Ok(Number::new(v))
402
    }
403
    #[cfg(feature = "integer128")]
404
    fn serialize_u128(self, v: u128) -> Result<Number> {
405
        Ok(Number::new(v))
406
    }
407

            
408
    fn serialize_bool(self, _: bool) -> Result<Number> {
409
        Err(Error::InvalidValueForType {
410
            expected: alloc::string::String::from("number"),
411
            found: alloc::string::String::from("bool"),
412
        })
413
    }
414
    fn serialize_char(self, _: char) -> Result<Number> {
415
        Err(Error::InvalidValueForType {
416
            expected: alloc::string::String::from("number"),
417
            found: alloc::string::String::from("char"),
418
        })
419
    }
420
1240
    fn serialize_str(self, _: &str) -> Result<Number> {
421
1240
        Err(Error::InvalidValueForType {
422
1240
            expected: alloc::string::String::from("number"),
423
1240
            found: alloc::string::String::from("string"),
424
1240
        })
425
1240
    }
426
    fn serialize_bytes(self, _: &[u8]) -> Result<Number> {
427
        Err(Error::InvalidValueForType {
428
            expected: alloc::string::String::from("number"),
429
            found: alloc::string::String::from("bytes"),
430
        })
431
    }
432
    fn serialize_none(self) -> Result<Number> {
433
        Err(Error::InvalidValueForType {
434
            expected: alloc::string::String::from("number"),
435
            found: alloc::string::String::from("None"),
436
        })
437
    }
438
    fn serialize_some<T: ?Sized + Serialize>(self, _: &T) -> Result<Number> {
439
        Err(Error::InvalidValueForType {
440
            expected: alloc::string::String::from("number"),
441
            found: alloc::string::String::from("Some"),
442
        })
443
    }
444
    fn serialize_unit(self) -> Result<Number> {
445
        Err(Error::InvalidValueForType {
446
            expected: alloc::string::String::from("number"),
447
            found: alloc::string::String::from("unit"),
448
        })
449
    }
450
    fn serialize_unit_struct(self, _: &'static str) -> Result<Number> {
451
        Err(Error::InvalidValueForType {
452
            expected: alloc::string::String::from("number"),
453
            found: alloc::string::String::from("unit struct"),
454
        })
455
    }
456
    fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result<Number> {
457
        Err(Error::InvalidValueForType {
458
            expected: alloc::string::String::from("number"),
459
            found: alloc::string::String::from("unit variant"),
460
        })
461
    }
462
    fn serialize_newtype_struct<T: ?Sized + Serialize>(
463
        self,
464
        _: &'static str,
465
        _: &T,
466
    ) -> Result<Number> {
467
        Err(Error::InvalidValueForType {
468
            expected: alloc::string::String::from("number"),
469
            found: alloc::string::String::from("newtype struct"),
470
        })
471
    }
472
    fn serialize_newtype_variant<T: ?Sized + Serialize>(
473
        self,
474
        _: &'static str,
475
        _: u32,
476
        _: &'static str,
477
        _: &T,
478
    ) -> Result<Number> {
479
        Err(Error::InvalidValueForType {
480
            expected: alloc::string::String::from("number"),
481
            found: alloc::string::String::from("newtype variant"),
482
        })
483
    }
484
    fn serialize_seq(self, _: Option<usize>) -> Result<Self::SerializeSeq> {
485
        Err(Error::InvalidValueForType {
486
            expected: alloc::string::String::from("number"),
487
            found: alloc::string::String::from("seq"),
488
        })
489
    }
490
    fn serialize_tuple(self, _: usize) -> Result<Self::SerializeTuple> {
491
        Err(Error::InvalidValueForType {
492
            expected: alloc::string::String::from("number"),
493
            found: alloc::string::String::from("tuple"),
494
        })
495
    }
496
    fn serialize_tuple_struct(
497
        self,
498
        _: &'static str,
499
        _: usize,
500
    ) -> Result<Self::SerializeTupleStruct> {
501
        Err(Error::InvalidValueForType {
502
            expected: alloc::string::String::from("number"),
503
            found: alloc::string::String::from("tuple struct"),
504
        })
505
    }
506
    fn serialize_tuple_variant(
507
        self,
508
        _: &'static str,
509
        _: u32,
510
        _: &'static str,
511
        _: usize,
512
    ) -> Result<Self::SerializeTupleVariant> {
513
        Err(Error::InvalidValueForType {
514
            expected: alloc::string::String::from("number"),
515
            found: alloc::string::String::from("tuple variant"),
516
        })
517
    }
518
    fn serialize_map(self, _: Option<usize>) -> Result<Self::SerializeMap> {
519
        Err(Error::InvalidValueForType {
520
            expected: alloc::string::String::from("number"),
521
            found: alloc::string::String::from("map"),
522
        })
523
    }
524
    fn serialize_struct(self, _: &'static str, _: usize) -> Result<Self::SerializeStruct> {
525
        Err(Error::InvalidValueForType {
526
            expected: alloc::string::String::from("number"),
527
            found: alloc::string::String::from("struct"),
528
        })
529
    }
530
    fn serialize_struct_variant(
531
        self,
532
        _: &'static str,
533
        _: u32,
534
        _: &'static str,
535
        _: usize,
536
    ) -> Result<Self::SerializeStructVariant> {
537
        Err(Error::InvalidValueForType {
538
            expected: alloc::string::String::from("number"),
539
            found: alloc::string::String::from("struct variant"),
540
        })
541
    }
542
}
543

            
544
pub(crate) struct NumberDeserializer {
545
    pub(crate) number: Number,
546
    pub(crate) extensions: Extensions,
547
}
548

            
549
impl<'de> serde::de::Deserializer<'de> for NumberDeserializer {
550
    type Error = crate::error::Error;
551

            
552
5160
    fn deserialize_any<V: serde::de::Visitor<'de>>(
553
5160
        self,
554
5160
        visitor: V,
555
5160
    ) -> crate::error::Result<V::Value> {
556
5160
        self.number.visit(visitor)
557
5160
    }
558

            
559
60
    fn deserialize_newtype_struct<V: serde::de::Visitor<'de>>(
560
60
        self,
561
60
        _: &'static str,
562
60
        visitor: V,
563
60
    ) -> crate::error::Result<V::Value> {
564
60
        if self.extensions.contains(Extensions::UNWRAP_NEWTYPES) {
565
40
            visitor.visit_newtype_struct(self)
566
        } else {
567
20
            self.deserialize_any(visitor)
568
        }
569
60
    }
570

            
571
    serde::forward_to_deserialize_any! {
572
        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64
573
        char str string bytes byte_buf option unit unit_struct
574
        seq tuple tuple_struct map struct enum identifier ignored_any
575
    }
576
}
577

            
578
#[cfg(test)]
579
mod tests {
580
    use super::*;
581

            
582
    #[test]
583
4
    fn test_nan() {
584
4
        assert_eq!(F32(f32::NAN), F32(f32::NAN));
585
4
        assert_eq!(F32(-f32::NAN), F32(-f32::NAN));
586
4
        assert_ne!(F32(f32::NAN), F32(-f32::NAN));
587
4
    }
588

            
589
    #[cfg(feature = "std")]
590
    #[test]
591
4
    fn test_nan_hash() {
592
        use std::collections::hash_map::DefaultHasher;
593
        use std::hash::{Hash, Hasher};
594

            
595
24
        fn hash<T: Hash>(v: &T) -> u64 {
596
24
            let mut state = DefaultHasher::new();
597
24
            v.hash(&mut state);
598
24
            state.finish()
599
24
        }
600

            
601
4
        assert_eq!(hash(&F32(f32::NAN)), hash(&F32(f32::NAN)));
602
4
        assert_eq!(hash(&F32(-f32::NAN)), hash(&F32(-f32::NAN)));
603
4
        assert_ne!(hash(&F32(f32::NAN)), hash(&F32(-f32::NAN)));
604
4
    }
605

            
606
    #[test]
607
4
    fn test_partial_ord() {
608
4
        assert!(F32(f32::NAN) > F32(f32::INFINITY));
609
4
        assert!(F32(-f32::NAN) < F32(f32::NEG_INFINITY));
610
4
        assert!(F32(f32::NAN) == F32(f32::NAN));
611
4
    }
612
}