Skip to content

Commit 44a7b9c

Browse files
authored
Rollup merge of rust-lang#58717 - hellow554:nonzero_parse, r=Amanieu
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
2 parents 34f0297 + 7330525 commit 44a7b9c

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

src/libcore/num/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,24 @@ nonzero_integers! {
112112
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
113113
}
114114

115+
macro_rules! from_str_radix_nzint_impl {
116+
($($t:ty)*) => {$(
117+
#[stable(feature = "nonzero_parse", since = "1.35.0")]
118+
impl FromStr for $t {
119+
type Err = ParseIntError;
120+
fn from_str(src: &str) -> Result<Self, Self::Err> {
121+
Self::new(from_str_radix(src, 10)?)
122+
.ok_or(ParseIntError {
123+
kind: IntErrorKind::Zero
124+
})
125+
}
126+
}
127+
)*}
128+
}
129+
130+
from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
131+
NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
132+
115133
/// Provides intentionally-wrapped arithmetic on `T`.
116134
///
117135
/// Operations like `+` on `u32` values is intended to never overflow,
@@ -4776,6 +4794,11 @@ pub enum IntErrorKind {
47764794
Overflow,
47774795
/// Integer is too small to store in target integer type.
47784796
Underflow,
4797+
/// Value was Zero
4798+
///
4799+
/// This variant will be emitted when the parsing string has a value of zero, which
4800+
/// would be illegal for non-zero types.
4801+
Zero,
47794802
}
47804803

47814804
impl ParseIntError {
@@ -4798,6 +4821,7 @@ impl ParseIntError {
47984821
IntErrorKind::InvalidDigit => "invalid digit found in string",
47994822
IntErrorKind::Overflow => "number too large to fit in target type",
48004823
IntErrorKind::Underflow => "number too small to fit in target type",
4824+
IntErrorKind::Zero => "number would be zero for non-zero type",
48014825
}
48024826
}
48034827
}

src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#![feature(slice_internals)]
3232
#![feature(slice_partition_dedup)]
3333
#![feature(copy_within)]
34+
#![feature(int_error_matching)]
3435

3536
extern crate core;
3637
extern crate test;

src/libcore/tests/nonzero.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use core::num::{NonZeroU32, NonZeroI32};
2-
use core::option::Option;
3-
use core::option::Option::{Some, None};
1+
use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8};
2+
use core::option::Option::{self, None, Some};
43
use std::mem::size_of;
54

65
#[test]
@@ -126,3 +125,24 @@ fn test_from_signed_nonzero() {
126125
let num: i32 = nz.into();
127126
assert_eq!(num, 1i32);
128127
}
128+
129+
#[test]
130+
fn test_from_str() {
131+
assert_eq!("123".parse::<NonZeroU8>(), Ok(NonZeroU8::new(123).unwrap()));
132+
assert_eq!(
133+
"0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
134+
Some(IntErrorKind::Zero)
135+
);
136+
assert_eq!(
137+
"-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
138+
Some(IntErrorKind::InvalidDigit)
139+
);
140+
assert_eq!(
141+
"-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
142+
Some(IntErrorKind::Underflow)
143+
);
144+
assert_eq!(
145+
"257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
146+
Some(IntErrorKind::Overflow)
147+
);
148+
}

0 commit comments

Comments
 (0)