Skip to content

Commit

Permalink
Add FromStr impl for NonZero types
Browse files Browse the repository at this point in the history
  • Loading branch information
hellow554 committed Feb 25, 2019
1 parent 082c861 commit 36bcbc3
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 0 deletions.
106 changes: 106 additions & 0 deletions src/libcore/num/mod.rs
Expand Up @@ -112,6 +112,112 @@ nonzero_integers! {
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
}

/// An error which can be returned when parsing a non-zero integer.
///
/// # Potential causes
///
/// Among other causes, `ParseNonZeroIntError` can be thrown because of leading or trailing
/// whitespace in the string e.g., when it is obtained from the standard input.
/// Using the [`str.trim()`] method ensures that no whitespace remains before parsing.
///
/// [`str.trim()`]: ../../std/primitive.str.html#method.trim
#[unstable(feature = "nonzero_parse", issue = "0")]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseNonZeroIntError {
kind: NonZeroIntErrorKind,
}

/// Enum to store the various types of errors that can cause parsing a non-zero integer to fail.
#[unstable(feature = "nonzero_parse", issue = "0")]
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum NonZeroIntErrorKind {
/// Value being parsed is empty.
///
/// Among other causes, this variant will be constructed when parsing an empty string.
Empty,
/// Contains an invalid digit.
///
/// Among other causes, this variant will be constructed when parsing a string that
/// contains a letter.
InvalidDigit,
/// Integer is too large to store in target integer type.
Overflow,
/// Integer is too small to store in target integer type.
Underflow,
/// Integer contains the value `0` which is forbidden for a non-zero integer
Zero,
}

#[unstable(feature = "nonzero_parse", issue = "0")]
impl From<ParseIntError> for ParseNonZeroIntError {
fn from(p: ParseIntError) -> Self {
use self::IntErrorKind as IK;
use self::NonZeroIntErrorKind as NK;
ParseNonZeroIntError {
kind: match p.kind {
IK::Empty => NK::Empty,
IK::InvalidDigit => NK::InvalidDigit,
IK::Overflow => NK::Overflow,
IK::Underflow => NK::Underflow,
},
}
}
}

impl ParseNonZeroIntError {
/// Outputs the detailed cause of parsing an integer failing.
#[unstable(feature = "int_error_matching",
reason = "it can be useful to match errors when making error messages \
for integer parsing",
issue = "22639")]
pub fn kind(&self) -> &NonZeroIntErrorKind {
&self.kind
}

#[unstable(feature = "int_error_internals",
reason = "available through Error trait and this method should \
not be exposed publicly",
issue = "0")]
#[doc(hidden)]
pub fn __description(&self) -> &str {
match self.kind {
NonZeroIntErrorKind::Empty => "cannot parse integer from empty string",
NonZeroIntErrorKind::InvalidDigit => "invalid digit found in string",
NonZeroIntErrorKind::Overflow => "number too large to fit in target type",
NonZeroIntErrorKind::Underflow => "number too small to fit in target type",
NonZeroIntErrorKind::Zero => "number is 0",
}
}

}

#[unstable(feature = "nonzero_parse", issue = "0")]
impl fmt::Display for ParseNonZeroIntError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.__description().fmt(f)
}
}


macro_rules! from_str_radix_nzint_impl {
($($t:ty)*) => {$(
#[unstable(feature = "nonzero_parse", issue = "0")]
impl FromStr for $t {
type Err = ParseNonZeroIntError;
fn from_str(src: &str) -> Result<Self, Self::Err> {
Self::new(from_str_radix(src, 10)?)
.ok_or(ParseNonZeroIntError {
kind: NonZeroIntErrorKind::Zero
})
}
}
)*}
}

from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }

/// Provides intentionally-wrapped arithmetic on `T`.
///
/// Operations like `+` on `u32` values is intended to never overflow,
Expand Down
17 changes: 17 additions & 0 deletions src/libcore/tests/nonzero.rs
Expand Up @@ -126,3 +126,20 @@ fn test_from_signed_nonzero() {
let num: i32 = nz.into();
assert_eq!(num, 1i32);
}

#[test]
fn test_from_str() {
assert_eq!(FromStr::from_str("123"), Ok(NonZeroU8::new(123).unwrap()));
assert_eq!(
FromStr::from_str("0"),
Err(ParseNonZeroIntError {
kind: NonZeroIntErrorKind::Zero
})
);
assert_eq!(
FromStr::from_str("-1",
Err(ParseNonZeroIntError {
kind: NonZeroIntErrorKind::Underflow
})
);
}

0 comments on commit 36bcbc3

Please sign in to comment.