Skip to content

Commit 298e8da

Browse files
f-frmbrubeck
authored andcommitted
Implement Num for NotNaN
1 parent 8333afb commit 298e8da

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/lib.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::fmt;
1515
use std::io;
1616
use std::mem;
1717
use unreachable::unreachable;
18-
use num_traits::{Bounded, Float, FromPrimitive, One, ToPrimitive, Zero};
18+
use num_traits::{Bounded, Float, FromPrimitive, Num, One, ToPrimitive, Zero};
1919

2020
/// A wrapper around Floats providing an implementation of Ord and Hash.
2121
///
@@ -621,6 +621,37 @@ impl<T: Float + ToPrimitive> ToPrimitive for NotNaN<T> {
621621
fn to_f64(&self) -> Option<f64> { self.0.to_f64() }
622622
}
623623

624+
/// An error indicating a parse error from a string for `NotNaN`.
625+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
626+
pub enum ParseNotNaNError<E> {
627+
/// A plain parse error from the underlying float type.
628+
ParseFloatError(E),
629+
/// The parsed float value resulted in a NaN.
630+
IsNaN,
631+
}
632+
633+
impl<E: fmt::Debug> Error for ParseNotNaNError<E> {
634+
fn description(&self) -> &str {
635+
return "Error parsing a not-NaN floating point value";
636+
}
637+
}
638+
639+
impl<E: fmt::Debug> fmt::Display for ParseNotNaNError<E> {
640+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
641+
<Self as fmt::Debug>::fmt(self, f)
642+
}
643+
}
644+
645+
impl<T: Float + Num> Num for NotNaN<T> {
646+
type FromStrRadixErr = ParseNotNaNError<T::FromStrRadixErr>;
647+
648+
fn from_str_radix(src: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
649+
T::from_str_radix(src, radix)
650+
.map_err(|err| ParseNotNaNError::ParseFloatError(err))
651+
.and_then(|n| NotNaN::new(n).map_err(|_| ParseNotNaNError::IsNaN))
652+
}
653+
}
654+
624655
#[cfg(feature = "serde")]
625656
mod impl_serde {
626657
extern crate serde;

tests/test.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ extern crate ordered_float;
55
extern crate num_traits;
66

77
pub use ordered_float::*;
8-
pub use num_traits::{Bounded, Float, FromPrimitive, One, ToPrimitive, Zero};
8+
pub use num_traits::{Bounded, Float, FromPrimitive, Num, One, ToPrimitive, Zero};
99
pub use std::cmp::Ordering::*;
1010
pub use std::{f32, f64, panic};
1111

@@ -155,6 +155,11 @@ describe! not_nan32 {
155155
assert_eq!(x.to_f64(), Some(42f64));
156156
assert_eq!(x.to_f64(), Some(42f64));
157157
}
158+
159+
it "should implement Num" {
160+
assert_eq!(NotNaN::<f32>::from_str_radix("42.0", 10).unwrap(), NotNaN::from(42.0f32));
161+
assert!(NotNaN::<f32>::from_str_radix("NaN", 10).is_err());
162+
}
158163
}
159164

160165
describe! not_nan64 {
@@ -269,6 +274,11 @@ describe! not_nan64 {
269274
assert_eq!(x.to_f64(), Some(42f64));
270275
assert_eq!(x.to_f64(), Some(42f64));
271276
}
277+
278+
it "should implement Num" {
279+
assert_eq!(NotNaN::<f64>::from_str_radix("42.0", 10).unwrap(), NotNaN::from(42.0f64));
280+
assert!(NotNaN::<f64>::from_str_radix("NaN", 10).is_err());
281+
}
272282
}
273283

274284
describe! hashing {

0 commit comments

Comments
 (0)