Skip to content

Commit

Permalink
Rollup merge of rust-lang#58717 - hellow554:nonzero_parse, r=Amanieu
Browse files Browse the repository at this point in the history
Add FromStr impl for NonZero types

This is a WIP implementation because I do have some questions regarding the solution.

Somebody should ping the lang team on this I guess.
Please see the annotations on the code for more details.

Closes rust-lang#58604
  • Loading branch information
Centril committed Mar 27, 2019
2 parents 34f0297 + 7330525 commit 44a7b9c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
24 changes: 24 additions & 0 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ nonzero_integers! {
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
}

macro_rules! from_str_radix_nzint_impl {
($($t:ty)*) => {$(
#[stable(feature = "nonzero_parse", since = "1.35.0")]
impl FromStr for $t {
type Err = ParseIntError;
fn from_str(src: &str) -> Result<Self, Self::Err> {
Self::new(from_str_radix(src, 10)?)
.ok_or(ParseIntError {
kind: IntErrorKind::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 Expand Up @@ -4776,6 +4794,11 @@ pub enum IntErrorKind {
Overflow,
/// Integer is too small to store in target integer type.
Underflow,
/// Value was Zero
///
/// This variant will be emitted when the parsing string has a value of zero, which
/// would be illegal for non-zero types.
Zero,
}

impl ParseIntError {
Expand All @@ -4798,6 +4821,7 @@ impl ParseIntError {
IntErrorKind::InvalidDigit => "invalid digit found in string",
IntErrorKind::Overflow => "number too large to fit in target type",
IntErrorKind::Underflow => "number too small to fit in target type",
IntErrorKind::Zero => "number would be zero for non-zero type",
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/libcore/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
#![feature(copy_within)]
#![feature(int_error_matching)]

extern crate core;
extern crate test;
Expand Down
26 changes: 23 additions & 3 deletions src/libcore/tests/nonzero.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use core::num::{NonZeroU32, NonZeroI32};
use core::option::Option;
use core::option::Option::{Some, None};
use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8};
use core::option::Option::{self, None, Some};
use std::mem::size_of;

#[test]
Expand Down Expand Up @@ -126,3 +125,24 @@ fn test_from_signed_nonzero() {
let num: i32 = nz.into();
assert_eq!(num, 1i32);
}

#[test]
fn test_from_str() {
assert_eq!("123".parse::<NonZeroU8>(), Ok(NonZeroU8::new(123).unwrap()));
assert_eq!(
"0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::Zero)
);
assert_eq!(
"-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::InvalidDigit)
);
assert_eq!(
"-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::Underflow)
);
assert_eq!(
"257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
Some(IntErrorKind::Overflow)
);
}

0 comments on commit 44a7b9c

Please sign in to comment.