std: Stabilize FromStr and parse

This commits adds an associated type to the `FromStr` trait representing an
error payload for parses which do not succeed. The previous return value,
`Option<Self>` did not allow for this form of payload. After the associated type
was added, the following attributes were applied:

* `FromStr` is now stable
* `FromStr::Err` is now stable
* `FromStr::from_str` is now stable
* `StrExt::parse` is now stable
* `FromStr for bool` is now stable
* `FromStr for $float` is now stable
* `FromStr for $integral` is now stable
* Errors returned from stable `FromStr` implementations are stable
* Errors implement `Display` and `Error` (both impl blocks being `#[stable]`)

Closes #15138
This commit is contained in:
Alex Crichton 2015-01-27 22:52:32 -08:00
parent 1a51eb9cca
commit 0cdde6e5e0
39 changed files with 389 additions and 260 deletions

View File

@ -25,17 +25,18 @@ pub enum Mode {
}
impl FromStr for Mode {
fn from_str(s: &str) -> Option<Mode> {
type Err = ();
fn from_str(s: &str) -> Result<Mode, ()> {
match s {
"compile-fail" => Some(CompileFail),
"run-fail" => Some(RunFail),
"run-pass" => Some(RunPass),
"run-pass-valgrind" => Some(RunPassValgrind),
"pretty" => Some(Pretty),
"debuginfo-lldb" => Some(DebugInfoLldb),
"debuginfo-gdb" => Some(DebugInfoGdb),
"codegen" => Some(Codegen),
_ => None,
"compile-fail" => Ok(CompileFail),
"run-fail" => Ok(RunFail),
"run-pass" => Ok(RunPass),
"run-pass-valgrind" => Ok(RunPassValgrind),
"pretty" => Ok(Pretty),
"debuginfo-lldb" => Ok(DebugInfoLldb),
"debuginfo-gdb" => Ok(DebugInfoGdb),
"codegen" => Ok(Codegen),
_ => Err(()),
}
}
}

View File

@ -35,7 +35,6 @@ extern crate log;
use std::os;
use std::old_io;
use std::old_io::fs;
use std::str::FromStr;
use std::thunk::Thunk;
use getopts::{optopt, optflag, reqopt};
use common::Config;
@ -140,9 +139,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
build_base: opt_path(matches, "build-base"),
aux_base: opt_path(matches, "aux-base"),
stage_id: matches.opt_str("stage-id").unwrap(),
mode: FromStr::from_str(matches.opt_str("mode")
.unwrap()
.as_slice()).expect("invalid mode"),
mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"),
run_ignored: matches.opt_present("ignored"),
filter: filter,
logfile: matches.opt_str("logfile").map(|s| Path::new(s)),

View File

@ -352,8 +352,8 @@ pub fn gdb_version_to_int(version_string: &str) -> int {
panic!("{}", error_string);
}
let major: int = components[0].parse().expect(error_string);
let minor: int = components[1].parse().expect(error_string);
let major: int = components[0].parse().ok().expect(error_string);
let minor: int = components[1].parse().ok().expect(error_string);
return major * 1000 + minor;
}
@ -363,6 +363,6 @@ pub fn lldb_version_to_int(version_string: &str) -> int {
"Encountered LLDB version string with unexpected format: {}",
version_string);
let error_string = error_string.as_slice();
let major: int = version_string.parse().expect(error_string);
let major: int = version_string.parse().ok().expect(error_string);
return major;
}

View File

@ -2994,7 +2994,7 @@ Some examples of call expressions:
# fn add(x: i32, y: i32) -> i32 { 0 }
let x: i32 = add(1i32, 2i32);
let pi: Option<f32> = "3.14".parse();
let pi: Option<f32> = "3.14".parse().ok();
```
### Lambda expressions

View File

@ -400,7 +400,7 @@ a function for that:
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.parse();
let input_num: Option<u32> = input.parse().ok();
```
The `parse` function takes in a `&str` value and converts it into something.
@ -422,11 +422,13 @@ In this case, we say `x` is a `u32` explicitly, so Rust is able to properly
tell `random()` what to generate. In a similar fashion, both of these work:
```{rust,ignore}
let input_num = "5".parse::<u32>(); // input_num: Option<u32>
let input_num: Option<u32> = "5".parse(); // input_num: Option<u32>
let input_num = "5".parse::<u32>().ok(); // input_num: Option<u32>
let input_num: Option<u32> = "5".parse().ok(); // input_num: Option<u32>
```
Anyway, with us now converting our input to a number, our code looks like this:
Here we're converting the `Result` returned by `parse` to an `Option` by using
the `ok` method as well. Anyway, with us now converting our input to a number,
our code looks like this:
```{rust,ignore}
use std::old_io;
@ -445,7 +447,7 @@ fn main() {
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.parse();
let input_num: Option<u32> = input.parse().ok();
println!("You guessed: {}", input_num);
@ -495,7 +497,7 @@ fn main() {
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.parse();
let input_num: Option<u32> = input.parse().ok();
let num = match input_num {
Some(num) => num,
@ -562,7 +564,7 @@ fn main() {
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.trim().parse();
let input_num: Option<u32> = input.trim().parse().ok();
let num = match input_num {
Some(num) => num,
@ -638,7 +640,7 @@ fn main() {
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.trim().parse();
let input_num: Option<u32> = input.trim().parse().ok();
let num = match input_num {
Some(num) => num,
@ -714,7 +716,7 @@ fn main() {
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.trim().parse();
let input_num: Option<u32> = input.trim().parse().ok();
let num = match input_num {
Some(num) => num,
@ -770,7 +772,7 @@ fn main() {
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.trim().parse();
let input_num: Option<u32> = input.trim().parse().ok();
let num = match input_num {
Some(num) => num,
@ -847,7 +849,7 @@ fn main() {
let input = old_io::stdin().read_line()
.ok()
.expect("Failed to read line");
let input_num: Option<u32> = input.trim().parse();
let input_num: Option<u32> = input.trim().parse().ok();
let num = match input_num {
Some(num) => num,

View File

@ -68,6 +68,7 @@ use core::ops::FullRange;
#[cfg(not(stage0))]
use core::ops::RangeFull;
use core::option::Option::{self, Some, None};
use core::result::Result;
use core::slice::AsSlice;
use core::str as core_str;
use unicode::str::{UnicodeStr, Utf16Encoder};
@ -1231,13 +1232,12 @@ pub trait StrExt: Index<RangeFull, Output = str> {
/// # Example
///
/// ```
/// assert_eq!("4".parse::<u32>(), Some(4));
/// assert_eq!("j".parse::<u32>(), None);
/// assert_eq!("4".parse::<u32>(), Ok(4));
/// assert!("j".parse::<u32>().is_err());
/// ```
#[inline]
#[unstable(feature = "collections",
reason = "this method was just created")]
fn parse<F: FromStr>(&self) -> Option<F> {
#[stable(feature = "rust1", since = "1.0.0")]
fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
core_str::StrExt::parse(&self[])
}

View File

@ -940,10 +940,12 @@ pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
DerefString { x: as_vec(x.as_bytes()) }
}
#[unstable(feature = "collections", reason = "associated error type may change")]
impl FromStr for String {
type Err = ();
#[inline]
fn from_str(s: &str) -> Option<String> {
Some(String::from_str(s))
fn from_str(s: &str) -> Result<String, ()> {
Ok(String::from_str(s))
}
}
@ -1016,7 +1018,7 @@ mod tests {
#[test]
fn test_from_str() {
let owned: Option<::std::string::String> = "string".parse();
let owned: Option<::std::string::String> = "string".parse().ok();
assert_eq!(owned.as_ref().map(|s| s.as_slice()), Some("string"));
}

View File

@ -17,16 +17,17 @@
use char::CharExt;
use clone::Clone;
use cmp::{PartialEq, Eq};
use cmp::{PartialOrd, Ord};
use cmp::{PartialEq, Eq, PartialOrd, Ord};
use error::Error;
use fmt;
use intrinsics;
use iter::IteratorExt;
use marker::Copy;
use mem::size_of;
use ops::{Add, Sub, Mul, Div, Rem, Neg};
use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use option::Option;
use option::Option::{Some, None};
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use str::{FromStr, StrExt};
/// A built-in signed or unsigned integer.
@ -1428,22 +1429,25 @@ pub trait Float
}
/// A generic trait for converting a string with a radix (base) to a value
#[unstable(feature = "core", reason = "might need to return Result")]
#[unstable(feature = "core", reason = "needs reevaluation")]
pub trait FromStrRadix {
fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
type Err;
fn from_str_radix(str: &str, radix: uint) -> Result<Self, Self::Err>;
}
/// A utility function that just calls FromStrRadix::from_str_radix.
#[unstable(feature = "core", reason = "might need to return Result")]
pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
#[unstable(feature = "core", reason = "needs reevaluation")]
pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint)
-> Result<T, T::Err> {
FromStrRadix::from_str_radix(str, radix)
}
macro_rules! from_str_radix_float_impl {
($T:ty) => {
#[unstable(feature = "core",
reason = "might need to return Result")]
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for $T {
type Err = ParseFloatError;
/// Convert a string in base 10 to a float.
/// Accepts an optional decimal exponent.
///
@ -1470,14 +1474,15 @@ macro_rules! from_str_radix_float_impl {
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str(src: &str) -> Option<$T> {
fn from_str(src: &str) -> Result<$T, ParseFloatError> {
from_str_radix(src, 10)
}
}
#[unstable(feature = "core",
reason = "might need to return Result")]
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStrRadix for $T {
type Err = ParseFloatError;
/// Convert a string in a given base to a float.
///
/// Due to possible conflicts, this function does **not** accept
@ -1493,24 +1498,28 @@ macro_rules! from_str_radix_float_impl {
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
fn from_str_radix(src: &str, radix: uint) -> Option<$T> {
assert!(radix >= 2 && radix <= 36,
/// `None` if the string did not represent a valid number.
/// Otherwise, `Some(n)` where `n` is the floating-point number
/// represented by `src`.
fn from_str_radix(src: &str, radix: uint)
-> Result<$T, ParseFloatError> {
use self::FloatErrorKind::*;
use self::ParseFloatError as PFE;
assert!(radix >= 2 && radix <= 36,
"from_str_radix_float: must lie in the range `[2, 36]` - found {}",
radix);
// Special values
match src {
"inf" => return Some(Float::infinity()),
"-inf" => return Some(Float::neg_infinity()),
"NaN" => return Some(Float::nan()),
"inf" => return Ok(Float::infinity()),
"-inf" => return Ok(Float::neg_infinity()),
"NaN" => return Ok(Float::nan()),
_ => {},
}
let (is_positive, src) = match src.slice_shift_char() {
None => return None,
Some(('-', "")) => return None,
None => return Err(PFE { kind: Empty }),
Some(('-', "")) => return Err(PFE { kind: Empty }),
Some(('-', src)) => (false, src),
Some((_, _)) => (true, src),
};
@ -1541,15 +1550,15 @@ macro_rules! from_str_radix_float_impl {
// if we've not seen any non-zero digits.
if prev_sig != 0.0 {
if is_positive && sig <= prev_sig
{ return Some(Float::infinity()); }
{ return Ok(Float::infinity()); }
if !is_positive && sig >= prev_sig
{ return Some(Float::neg_infinity()); }
{ return Ok(Float::neg_infinity()); }
// Detect overflow by reversing the shift-and-add process
if is_positive && (prev_sig != (sig - digit as $T) / radix as $T)
{ return Some(Float::infinity()); }
{ return Ok(Float::infinity()); }
if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T)
{ return Some(Float::neg_infinity()); }
{ return Ok(Float::neg_infinity()); }
}
prev_sig = sig;
},
@ -1562,7 +1571,7 @@ macro_rules! from_str_radix_float_impl {
break; // start of fractional part
},
_ => {
return None;
return Err(PFE { kind: Invalid });
},
},
}
@ -1585,9 +1594,9 @@ macro_rules! from_str_radix_float_impl {
};
// Detect overflow by comparing to last value
if is_positive && sig < prev_sig
{ return Some(Float::infinity()); }
{ return Ok(Float::infinity()); }
if !is_positive && sig > prev_sig
{ return Some(Float::neg_infinity()); }
{ return Ok(Float::neg_infinity()); }
prev_sig = sig;
},
None => match c {
@ -1596,7 +1605,7 @@ macro_rules! from_str_radix_float_impl {
break; // start of exponent
},
_ => {
return None; // invalid number
return Err(PFE { kind: Invalid });
},
},
}
@ -1609,7 +1618,7 @@ macro_rules! from_str_radix_float_impl {
let base = match c {
'E' | 'e' if radix == 10 => 10.0,
'P' | 'p' if radix == 16 => 2.0,
_ => return None,
_ => return Err(PFE { kind: Invalid }),
};
// Parse the exponent as decimal integer
@ -1618,19 +1627,19 @@ macro_rules! from_str_radix_float_impl {
Some(('-', src)) => (false, src.parse::<uint>()),
Some(('+', src)) => (true, src.parse::<uint>()),
Some((_, _)) => (true, src.parse::<uint>()),
None => return None,
None => return Err(PFE { kind: Invalid }),
};
match (is_positive, exp) {
(true, Some(exp)) => base.powi(exp as i32),
(false, Some(exp)) => 1.0 / base.powi(exp as i32),
(_, None) => return None,
(true, Ok(exp)) => base.powi(exp as i32),
(false, Ok(exp)) => 1.0 / base.powi(exp as i32),
(_, Err(_)) => return Err(PFE { kind: Invalid }),
}
},
None => 1.0, // no exponent
};
Some(sig * exp)
Ok(sig * exp)
}
}
}
@ -1640,19 +1649,22 @@ from_str_radix_float_impl! { f64 }
macro_rules! from_str_radix_int_impl {
($T:ty) => {
#[unstable(feature = "core",
reason = "might need to return Result")]
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for $T {
type Err = ParseIntError;
#[inline]
fn from_str(src: &str) -> Option<$T> {
fn from_str(src: &str) -> Result<$T, ParseIntError> {
from_str_radix(src, 10)
}
}
#[unstable(feature = "core",
reason = "might need to return Result")]
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStrRadix for $T {
fn from_str_radix(src: &str, radix: uint) -> Option<$T> {
type Err = ParseIntError;
fn from_str_radix(src: &str, radix: uint)
-> Result<$T, ParseIntError> {
use self::IntErrorKind::*;
use self::ParseIntError as PIE;
assert!(radix >= 2 && radix <= 36,
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
radix);
@ -1666,18 +1678,18 @@ macro_rules! from_str_radix_int_impl {
for c in src.chars() {
let x = match c.to_digit(radix) {
Some(x) => x,
None => return None,
None => return Err(PIE { kind: InvalidDigit }),
};
result = match result.checked_mul(radix as $T) {
Some(result) => result,
None => return None,
None => return Err(PIE { kind: Underflow }),
};
result = match result.checked_sub(x as $T) {
Some(result) => result,
None => return None,
None => return Err(PIE { kind: Underflow }),
};
}
Some(result)
Ok(result)
},
Some((_, _)) => {
// The number is signed
@ -1685,20 +1697,20 @@ macro_rules! from_str_radix_int_impl {
for c in src.chars() {
let x = match c.to_digit(radix) {
Some(x) => x,
None => return None,
None => return Err(PIE { kind: InvalidDigit }),
};
result = match result.checked_mul(radix as $T) {
Some(result) => result,
None => return None,
None => return Err(PIE { kind: Overflow }),
};
result = match result.checked_add(x as $T) {
Some(result) => result,
None => return None,
None => return Err(PIE { kind: Overflow }),
};
}
Some(result)
Ok(result)
},
None => None,
None => Err(ParseIntError { kind: Empty }),
}
}
}
@ -1714,3 +1726,63 @@ from_str_radix_int_impl! { u8 }
from_str_radix_int_impl! { u16 }
from_str_radix_int_impl! { u32 }
from_str_radix_int_impl! { u64 }
/// An error which can be returned when parsing an integer.
#[derive(Show, Clone, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseIntError { kind: IntErrorKind }
#[derive(Show, Clone, PartialEq)]
enum IntErrorKind {
Empty,
InvalidDigit,
Overflow,
Underflow,
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseIntError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseIntError {
fn description(&self) -> &str {
match self.kind {
IntErrorKind::Empty => "cannot parse integer from empty string",
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",
}
}
}
/// An error which can be returned when parsing a float.
#[derive(Show, Clone, PartialEq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseFloatError { kind: FloatErrorKind }
#[derive(Show, Clone, PartialEq)]
enum FloatErrorKind {
Empty,
Invalid,
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseFloatError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.description().fmt(f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseFloatError {
fn description(&self) -> &str {
match self.kind {
FloatErrorKind::Empty => "cannot parse float from empty string",
FloatErrorKind::Invalid => "invalid float literal",
}
}
}

View File

@ -728,8 +728,8 @@ impl<T: Default> Option<T> {
/// ```
/// let good_year_from_input = "1909";
/// let bad_year_from_input = "190blarg";
/// let good_year = good_year_from_input.parse().unwrap_or_default();
/// let bad_year = bad_year_from_input.parse().unwrap_or_default();
/// let good_year = good_year_from_input.parse().ok().unwrap_or_default();
/// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default();
///
/// assert_eq!(1909, good_year);
/// assert_eq!(0, bad_year);

View File

@ -108,37 +108,62 @@ macro_rules! delegate_iter {
/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
// FIXME(#17307): there should be an `E` associated type for a `Result` return
#[unstable(feature = "core",
reason = "will return a Result once associated types are working")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait FromStr {
/// The associated error which can be returned from parsing.
#[stable(feature = "rust1", since = "1.0.0")]
type Err;
/// Parses a string `s` to return an optional value of this type. If the
/// string is ill-formatted, the None is returned.
fn from_str(s: &str) -> Option<Self>;
#[stable(feature = "rust1", since = "1.0.0")]
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for bool {
type Err = ParseBoolError;
/// Parse a `bool` from a string.
///
/// Yields an `Option<bool>`, because `s` may or may not actually be parseable.
/// Yields an `Option<bool>`, because `s` may or may not actually be
/// parseable.
///
/// # Examples
///
/// ```rust
/// assert_eq!("true".parse(), Some(true));
/// assert_eq!("false".parse(), Some(false));
/// assert_eq!("not even a boolean".parse::<bool>(), None);
/// assert_eq!("true".parse(), Ok(true));
/// assert_eq!("false".parse(), Ok(false));
/// assert!("not even a boolean".parse::<bool>().is_err());
/// ```
#[inline]
fn from_str(s: &str) -> Option<bool> {
fn from_str(s: &str) -> Result<bool, ParseBoolError> {
match s {
"true" => Some(true),
"false" => Some(false),
_ => None,
"true" => Ok(true),
"false" => Ok(false),
_ => Err(ParseBoolError { _priv: () }),
}
}
}
/// An error returned when parsing a `bool` from a string fails.
#[derive(Show, Clone, PartialEq)]
#[allow(missing_copy_implementations)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseBoolError { _priv: () }
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for ParseBoolError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"provided string was not `true` or `false`".fmt(f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseBoolError {
fn description(&self) -> &str { "failed to parse bool" }
}
/*
Section: Creating a string
*/
@ -1355,7 +1380,7 @@ pub trait StrExt {
fn as_ptr(&self) -> *const u8;
fn len(&self) -> uint;
fn is_empty(&self) -> bool;
fn parse<T: FromStr>(&self) -> Option<T>;
fn parse<T: FromStr>(&self) -> Result<T, T::Err>;
}
#[inline(never)]
@ -1670,7 +1695,7 @@ impl StrExt for str {
fn is_empty(&self) -> bool { self.len() == 0 }
#[inline]
fn parse<T: FromStr>(&self) -> Option<T> { FromStr::from_str(self) }
fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
}
/// Pluck a code point out of a UTF-8-like byte slice and return the

View File

@ -159,7 +159,7 @@ mod tests {
#[test]
fn test_from_str() {
fn from_str<T: ::std::str::FromStr>(t: &str) -> Option<T> {
::std::str::FromStr::from_str(t)
::std::str::FromStr::from_str(t).ok()
}
assert_eq!(from_str::<$T>("0"), Some(0 as $T));
assert_eq!(from_str::<$T>("3"), Some(3 as $T));
@ -180,26 +180,26 @@ mod tests {
#[test]
fn test_from_str_radix() {
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123 as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291 as i32));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Some(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 10), Ok(123 as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Ok(9 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Ok(83 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Ok(291 as i32));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Ok(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Ok(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Ok(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Ok(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Some(-123 as $T));
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Some(-9 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Some(-83 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Some(-291 as i32));
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Ok(-123 as $T));
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Ok(-9 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Ok(-83 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Ok(-291 as i32));
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Ok(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Ok(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Ok(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 35), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("Z", 35).ok(), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("-9", 2).ok(), None::<$T>);
}
}

View File

@ -62,64 +62,64 @@ mod test {
#[test]
fn from_str_issue7588() {
let u : Option<u8> = from_str_radix("1000", 10);
let u : Option<u8> = from_str_radix("1000", 10).ok();
assert_eq!(u, None);
let s : Option<i16> = from_str_radix("80000", 10);
let s : Option<i16> = from_str_radix("80000", 10).ok();
assert_eq!(s, None);
let f : Option<f32> = from_str_radix("10000000000000000000000000000000000000000", 10);
let f : Option<f32> = from_str_radix("10000000000000000000000000000000000000000", 10).ok();
assert_eq!(f, Some(Float::infinity()));
let fe : Option<f32> = from_str_radix("1e40", 10);
let fe : Option<f32> = from_str_radix("1e40", 10).ok();
assert_eq!(fe, Some(Float::infinity()));
}
#[test]
fn test_from_str_radix_float() {
let x1 : Option<f64> = from_str_radix("-123.456", 10);
let x1 : Option<f64> = from_str_radix("-123.456", 10).ok();
assert_eq!(x1, Some(-123.456));
let x2 : Option<f32> = from_str_radix("123.456", 10);
let x2 : Option<f32> = from_str_radix("123.456", 10).ok();
assert_eq!(x2, Some(123.456));
let x3 : Option<f32> = from_str_radix("-0.0", 10);
let x3 : Option<f32> = from_str_radix("-0.0", 10).ok();
assert_eq!(x3, Some(-0.0));
let x4 : Option<f32> = from_str_radix("0.0", 10);
let x4 : Option<f32> = from_str_radix("0.0", 10).ok();
assert_eq!(x4, Some(0.0));
let x4 : Option<f32> = from_str_radix("1.0", 10);
let x4 : Option<f32> = from_str_radix("1.0", 10).ok();
assert_eq!(x4, Some(1.0));
let x5 : Option<f32> = from_str_radix("-1.0", 10);
let x5 : Option<f32> = from_str_radix("-1.0", 10).ok();
assert_eq!(x5, Some(-1.0));
}
#[test]
fn test_int_from_str_overflow() {
let mut i8_val: i8 = 127_i8;
assert_eq!("127".parse::<i8>(), Some(i8_val));
assert_eq!("128".parse::<i8>(), None);
assert_eq!("127".parse::<i8>().ok(), Some(i8_val));
assert_eq!("128".parse::<i8>().ok(), None);
i8_val += 1 as i8;
assert_eq!("-128".parse::<i8>(), Some(i8_val));
assert_eq!("-129".parse::<i8>(), None);
assert_eq!("-128".parse::<i8>().ok(), Some(i8_val));
assert_eq!("-129".parse::<i8>().ok(), None);
let mut i16_val: i16 = 32_767_i16;
assert_eq!("32767".parse::<i16>(), Some(i16_val));
assert_eq!("32768".parse::<i16>(), None);
assert_eq!("32767".parse::<i16>().ok(), Some(i16_val));
assert_eq!("32768".parse::<i16>().ok(), None);
i16_val += 1 as i16;
assert_eq!("-32768".parse::<i16>(), Some(i16_val));
assert_eq!("-32769".parse::<i16>(), None);
assert_eq!("-32768".parse::<i16>().ok(), Some(i16_val));
assert_eq!("-32769".parse::<i16>().ok(), None);
let mut i32_val: i32 = 2_147_483_647_i32;
assert_eq!("2147483647".parse::<i32>(), Some(i32_val));
assert_eq!("2147483648".parse::<i32>(), None);
assert_eq!("2147483647".parse::<i32>().ok(), Some(i32_val));
assert_eq!("2147483648".parse::<i32>().ok(), None);
i32_val += 1 as i32;
assert_eq!("-2147483648".parse::<i32>(), Some(i32_val));
assert_eq!("-2147483649".parse::<i32>(), None);
assert_eq!("-2147483648".parse::<i32>().ok(), Some(i32_val));
assert_eq!("-2147483649".parse::<i32>().ok(), None);
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
assert_eq!("9223372036854775807".parse::<i64>(), Some(i64_val));
assert_eq!("9223372036854775808".parse::<i64>(), None);
assert_eq!("9223372036854775807".parse::<i64>().ok(), Some(i64_val));
assert_eq!("9223372036854775808".parse::<i64>().ok(), None);
i64_val += 1 as i64;
assert_eq!("-9223372036854775808".parse::<i64>(), Some(i64_val));
assert_eq!("-9223372036854775809".parse::<i64>(), None);
assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
}
}

View File

@ -10,9 +10,9 @@
#[test]
fn test_bool_from_str() {
assert_eq!("true".parse(), Some(true));
assert_eq!("false".parse(), Some(false));
assert_eq!("not even a boolean".parse::<bool>(), None);
assert_eq!("true".parse().ok(), Some(true));
assert_eq!("false".parse().ok(), Some(false));
assert_eq!("not even a boolean".parse::<bool>().ok(), None);
}
fn check_contains_all_substrings(s: &str) {

View File

@ -22,7 +22,7 @@ pub static LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO",
/// Parse an individual log level that is either a number or a symbolic log level
fn parse_log_level(level: &str) -> Option<u32> {
level.parse::<u32>().or_else(|| {
level.parse::<u32>().ok().or_else(|| {
let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
pos.map(|p| p as u32 + 1)
}).map(|p| cmp::min(p, ::MAX_LOG_LEVEL))

View File

@ -254,7 +254,7 @@ impl LintPass for TypeLimits {
let lit_val: f64 = match lit.node {
ast::LitFloat(ref v, _) |
ast::LitFloatUnsuffixed(ref v) => {
match v.parse() {
match v.parse().ok() {
Some(f) => f,
None => return
}

View File

@ -223,7 +223,7 @@ fn each_reexport<F>(d: rbml::Doc, f: F) -> bool where
fn variant_disr_val(d: rbml::Doc) -> Option<ty::Disr> {
reader::maybe_get_doc(d, tag_disr_val).and_then(|val_doc| {
reader::with_doc_data(val_doc, |data| {
str::from_utf8(data).ok().and_then(|s| s.parse())
str::from_utf8(data).ok().and_then(|s| s.parse().ok())
})
})
}

View File

@ -717,12 +717,16 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
let crate_part = &buf[0u..colon_idx];
let def_part = &buf[colon_idx + 1u..len];
let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| s.parse::<uint>()) {
let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
s.parse::<uint>().ok()
}) {
Some(cn) => cn as ast::CrateNum,
None => panic!("internal error: parse_def_id: crate number expected, found {:?}",
crate_part)
};
let def_num = match str::from_utf8(def_part).ok().and_then(|s| s.parse::<uint>()) {
let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
s.parse::<uint>().ok()
}) {
Some(dn) => dn as ast::NodeId,
None => panic!("internal error: parse_def_id: id expected, found {:?}",
def_part)

View File

@ -59,7 +59,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
}
let requested_node : Option<ast::NodeId> =
os::getenv("RUST_REGION_GRAPH_NODE").and_then(|s| s.parse());
os::getenv("RUST_REGION_GRAPH_NODE").and_then(|s| s.parse().ok());
if requested_node.is_some() && requested_node != Some(subject_node) {
return;

View File

@ -18,7 +18,6 @@
use session::Session;
use syntax::ast;
use syntax::attr::AttrMetaMethods;
use std::str::FromStr;
pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
for attr in krate.attrs.iter() {
@ -27,7 +26,7 @@ pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
}
if let Some(s) = attr.value_str() {
if let Some(n) = FromStr::from_str(s.get()) {
if let Some(n) = s.parse().ok() {
sess.recursion_limit.set(n);
return;
}

View File

@ -424,7 +424,7 @@ macro_rules! options {
}
fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool {
match v.and_then(|s| s.parse()) {
match v.and_then(|s| s.parse().ok()) {
Some(i) => { *slot = i; true },
None => false
}
@ -432,7 +432,7 @@ macro_rules! options {
fn parse_opt_uint(slot: &mut Option<uint>, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = s.parse(); slot.is_some() }
Some(s) => { *slot = s.parse().ok(); slot.is_some() }
None => { *slot = None; true }
}
}

View File

@ -99,7 +99,7 @@ pub fn parse_pretty(sess: &Session,
}
}
};
let opt_second = opt_second.and_then(|s| s.parse::<UserIdentifiedItem>());
let opt_second = opt_second.and_then(|s| s.parse::<UserIdentifiedItem>().ok());
(first, opt_second)
}
@ -345,13 +345,11 @@ pub enum UserIdentifiedItem {
}
impl FromStr for UserIdentifiedItem {
fn from_str(s: &str) -> Option<UserIdentifiedItem> {
s.parse().map(ItemViaNode).or_else(|| {
let v : Vec<_> = s.split_str("::")
.map(|x|x.to_string())
.collect();
Some(ItemViaPath(v))
})
type Err = ();
fn from_str(s: &str) -> Result<UserIdentifiedItem, ()> {
Ok(s.parse().map(ItemViaNode).unwrap_or_else(|_| {
ItemViaPath(s.split_str("::").map(|s| s.to_string()).collect())
}))
}
}

View File

@ -2127,7 +2127,7 @@ macro_rules! read_primitive {
Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))),
// re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
// is going to have a string here, as per JSON spec.
Json::String(s) => match s.parse() {
Json::String(s) => match s.parse().ok() {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), s)),
},
@ -2165,7 +2165,7 @@ impl ::Decoder for Decoder {
Json::String(s) => {
// re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
// is going to have a string here, as per JSON spec.
match s.parse() {
match s.parse().ok() {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), s)),
}
@ -2597,8 +2597,9 @@ impl<'a, T: Encodable> fmt::Display for AsPrettyJson<'a, T> {
}
impl FromStr for Json {
fn from_str(s: &str) -> Option<Json> {
from_str(s).ok()
type Err = BuilderError;
fn from_str(s: &str) -> Result<Json, BuilderError> {
from_str(s)
}
}

View File

@ -20,7 +20,7 @@ mod tests {
use num::FromStrRadix;
fn from_str<T: ::str::FromStr>(t: &str) -> Option<T> {
::str::FromStr::from_str(t)
::str::FromStr::from_str(t).ok()
}
#[test]
@ -38,15 +38,15 @@ mod tests {
#[test]
pub fn test_parse_bytes() {
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123u as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291u as u16));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535u as u16));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 10), Ok(123u as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Ok(9u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Ok(83u as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Ok(291u as u16));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Ok(65535u as u16));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Ok(35u as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 10), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("_", 2), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("Z", 10).ok(), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("_", 2).ok(), None::<$T>);
}
#[test]

View File

@ -25,7 +25,7 @@ use iter::{Iterator, IteratorExt};
use ops::{FnOnce, FnMut};
use option::Option;
use option::Option::{None, Some};
use result::Result::{Ok, Err};
use result::Result::{self, Ok, Err};
use slice::SliceExt;
use str::{FromStr, StrExt};
use vec::Vec;
@ -350,17 +350,28 @@ impl<'a> Parser<'a> {
}
impl FromStr for IpAddr {
fn from_str(s: &str) -> Option<IpAddr> {
Parser::new(s).read_till_eof(|p| p.read_ip_addr())
type Err = ParseError;
fn from_str(s: &str) -> Result<IpAddr, ParseError> {
match Parser::new(s).read_till_eof(|p| p.read_ip_addr()) {
Some(s) => Ok(s),
None => Err(ParseError),
}
}
}
impl FromStr for SocketAddr {
fn from_str(s: &str) -> Option<SocketAddr> {
Parser::new(s).read_till_eof(|p| p.read_socket_addr())
type Err = ParseError;
fn from_str(s: &str) -> Result<SocketAddr, ParseError> {
match Parser::new(s).read_till_eof(|p| p.read_socket_addr()) {
Some(s) => Ok(s),
None => Err(ParseError),
}
}
}
#[derive(Show, Clone, PartialEq, Copy)]
pub struct ParseError;
/// A trait for objects which can be converted or resolved to one or more `SocketAddr` values.
///
/// Implementing types minimally have to implement either `to_socket_addr` or `to_socket_addr_all`
@ -493,7 +504,7 @@ fn parse_and_resolve_socket_addr(s: &str) -> IoResult<Vec<SocketAddr>> {
let mut parts_iter = s.rsplitn(2, ':');
let port_str = try_opt!(parts_iter.next(), "invalid socket address");
let host = try_opt!(parts_iter.next(), "invalid socket address");
let port: u16 = try_opt!(FromStr::from_str(port_str), "invalid port value");
let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
resolve_socket_addr(host, port)
}
@ -502,7 +513,7 @@ impl<'a> ToSocketAddr for (&'a str, u16) {
let (host, port) = *self;
// try to parse the host as a regular IpAddr first
match FromStr::from_str(host) {
match host.parse().ok() {
Some(addr) => return Ok(vec![SocketAddr {
ip: addr,
port: port
@ -518,7 +529,7 @@ impl<'a> ToSocketAddr for (&'a str, u16) {
impl<'a> ToSocketAddr for &'a str {
fn to_socket_addr(&self) -> IoResult<SocketAddr> {
// try to parse as a regular SocketAddr first
match FromStr::from_str(*self) {
match self.parse().ok() {
Some(addr) => return Ok(addr),
None => {}
}
@ -535,7 +546,7 @@ impl<'a> ToSocketAddr for &'a str {
fn to_socket_addr_all(&self) -> IoResult<Vec<SocketAddr>> {
// try to parse as a regular SocketAddr first
match FromStr::from_str(*self) {
match self.parse().ok() {
Some(addr) => return Ok(vec![addr]),
None => {}
}
@ -553,95 +564,94 @@ mod test {
#[test]
fn test_from_str_ipv4() {
assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
assert_eq!(Ok(Ipv4Addr(127, 0, 0, 1)), "127.0.0.1".parse());
assert_eq!(Ok(Ipv4Addr(255, 255, 255, 255)), "255.255.255.255".parse());
assert_eq!(Ok(Ipv4Addr(0, 0, 0, 0)), "0.0.0.0".parse());
// out of range
let none: Option<IpAddr> = FromStr::from_str("256.0.0.1");
let none: Option<IpAddr> = "256.0.0.1".parse().ok();
assert_eq!(None, none);
// too short
let none: Option<IpAddr> = FromStr::from_str("255.0.0");
let none: Option<IpAddr> = "255.0.0".parse().ok();
assert_eq!(None, none);
// too long
let none: Option<IpAddr> = FromStr::from_str("255.0.0.1.2");
let none: Option<IpAddr> = "255.0.0.1.2".parse().ok();
assert_eq!(None, none);
// no number between dots
let none: Option<IpAddr> = FromStr::from_str("255.0..1");
let none: Option<IpAddr> = "255.0..1".parse().ok();
assert_eq!(None, none);
}
#[test]
fn test_from_str_ipv6() {
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
assert_eq!(Ok(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
assert_eq!(Ok(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
assert_eq!(Ok(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
assert_eq!(Ok(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
FromStr::from_str("2a02:6b8::11:11"));
assert_eq!(Ok(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
"2a02:6b8::11:11".parse());
// too long group
let none: Option<IpAddr> = FromStr::from_str("::00000");
let none: Option<IpAddr> = "::00000".parse().ok();
assert_eq!(None, none);
// too short
let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7");
let none: Option<IpAddr> = "1:2:3:4:5:6:7".parse().ok();
assert_eq!(None, none);
// too long
let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7:8:9");
let none: Option<IpAddr> = "1:2:3:4:5:6:7:8:9".parse().ok();
assert_eq!(None, none);
// triple colon
let none: Option<IpAddr> = FromStr::from_str("1:2:::6:7:8");
let none: Option<IpAddr> = "1:2:::6:7:8".parse().ok();
assert_eq!(None, none);
// two double colons
let none: Option<IpAddr> = FromStr::from_str("1:2::6::8");
let none: Option<IpAddr> = "1:2::6::8".parse().ok();
assert_eq!(None, none);
}
#[test]
fn test_from_str_ipv4_in_ipv6() {
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
FromStr::from_str("::192.0.2.33"));
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
FromStr::from_str("::FFFF:192.0.2.33"));
assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
FromStr::from_str("64:ff9b::192.0.2.33"));
assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
assert_eq!(Ok(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
"::192.0.2.33".parse());
assert_eq!(Ok(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
"::FFFF:192.0.2.33".parse());
assert_eq!(Ok(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
"64:ff9b::192.0.2.33".parse());
assert_eq!(Ok(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
"2001:db8:122:c000:2:2100:192.0.2.33".parse());
// colon after v4
let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
let none: Option<IpAddr> = "::127.0.0.1:".parse().ok();
assert_eq!(None, none);
// not enough groups
let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
let none: Option<IpAddr> = "1.2.3.4.5:127.0.0.1".parse().ok();
assert_eq!(None, none);
// too many groups
let none: Option<IpAddr> =
FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1");
let none: Option<IpAddr> = "1.2.3.4.5:6:7:127.0.0.1".parse().ok();
assert_eq!(None, none);
}
#[test]
fn test_from_str_socket_addr() {
assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
FromStr::from_str("77.88.21.11:80"));
assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
FromStr::from_str("[2a02:6b8:0:1::1]:53"));
assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
FromStr::from_str("[::127.0.0.1]:22"));
assert_eq!(Ok(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
"77.88.21.11:80".parse());
assert_eq!(Ok(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
"[2a02:6b8:0:1::1]:53".parse());
assert_eq!(Ok(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
"[::127.0.0.1]:22".parse());
// without port
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1");
let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
assert_eq!(None, none);
// without port
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:");
let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
assert_eq!(None, none);
// wrong brackets around v4
let none: Option<SocketAddr> = FromStr::from_str("[127.0.0.1]:22");
let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
assert_eq!(None, none);
// port out of range
let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:123456");
let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
assert_eq!(None, none);
}

View File

@ -19,6 +19,7 @@ use iter::{AdditiveIterator, Extend};
use iter::{Iterator, IteratorExt, Map};
use marker::Sized;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice::{AsSlice, Split, SliceExt, SliceConcatExt};
use str::{self, FromStr, StrExt};
use vec::Vec;
@ -86,11 +87,19 @@ impl Ord for Path {
}
impl FromStr for Path {
fn from_str(s: &str) -> Option<Path> {
Path::new_opt(s)
type Err = ParsePathError;
fn from_str(s: &str) -> Result<Path, ParsePathError> {
match Path::new_opt(s) {
Some(p) => Ok(p),
None => Err(ParsePathError),
}
}
}
/// Valuelue indicating that a path could not be parsed from a string.
#[derive(Show, Clone, PartialEq, Copy)]
pub struct ParsePathError;
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
#[inline]
fn hash(&self, state: &mut S) {

View File

@ -27,6 +27,7 @@ use mem;
use option::Option::{self, Some, None};
#[cfg(stage0)]
use ops::FullRange;
use result::Result::{self, Ok, Err};
use slice::{SliceExt, SliceConcatExt};
use str::{SplitTerminator, FromStr, StrExt};
use string::{String, ToString};
@ -115,11 +116,19 @@ impl Ord for Path {
}
impl FromStr for Path {
fn from_str(s: &str) -> Option<Path> {
Path::new_opt(s)
type Err = ParsePathError;
fn from_str(s: &str) -> Result<Path, ParsePathError> {
match Path::new_opt(s) {
Some(p) => Ok(p),
None => Err(ParsePathError),
}
}
}
/// Value indicating that a path could not be parsed from a string.
#[derive(Show, Clone, PartialEq, Copy)]
pub struct ParsePathError;
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
#[cfg(not(test))]
#[inline]

View File

@ -51,7 +51,7 @@ pub fn min_stack() -> uint {
0 => {}
n => return n - 1,
}
let amt = os::getenv("RUST_MIN_STACK").and_then(|s| s.parse());
let amt = os::getenv("RUST_MIN_STACK").and_then(|s| s.parse().ok());
let amt = amt.unwrap_or(2 * 1024 * 1024);
// 0 is our sentinel value, so ensure that we'll never see 0 after
// initialization has run
@ -64,7 +64,7 @@ pub fn min_stack() -> uint {
pub fn default_sched_threads() -> uint {
match os::getenv("RUST_THREADS") {
Some(nstr) => {
let opt_n: Option<uint> = nstr.parse();
let opt_n: Option<uint> = nstr.parse().ok();
match opt_n {
Some(n) if n > 0 => n,
_ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)

View File

@ -613,7 +613,7 @@ impl<'a> StringReader<'a> {
// find the integer representing the name
self.scan_digits(base);
let encoded_name : u32 = self.with_str_from(start_bpos, |s| {
num::from_str_radix(s, 10).unwrap_or_else(|| {
num::from_str_radix(s, 10).ok().unwrap_or_else(|| {
panic!("expected digits representing a name, got {:?}, {}, range [{:?},{:?}]",
s, whence, start_bpos, self.last_pos);
})
@ -631,7 +631,7 @@ impl<'a> StringReader<'a> {
let start_bpos = self.last_pos;
self.scan_digits(base);
let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| {
num::from_str_radix(s, 10).unwrap_or_else(|| {
num::from_str_radix(s, 10).ok().unwrap_or_else(|| {
panic!("expected digits representing a ctxt, got {:?}, {}", s, whence);
})
});

View File

@ -401,7 +401,7 @@ pub fn char_lit(lit: &str) -> (char, isize) {
let msg2 = &msg[];
fn esc(len: usize, lit: &str) -> Option<(char, isize)> {
num::from_str_radix(&lit[2..len], 16)
num::from_str_radix(&lit[2..len], 16).ok()
.and_then(char::from_u32)
.map(|x| (x, len as isize))
}
@ -410,7 +410,7 @@ pub fn char_lit(lit: &str) -> (char, isize) {
if lit.as_bytes()[2] == b'{' {
let idx = lit.find('}').expect(msg2);
let subslice = &lit[3..idx];
num::from_str_radix(subslice, 16)
num::from_str_radix(subslice, 16).ok()
.and_then(char::from_u32)
.map(|x| (x, subslice.chars().count() as isize + 4))
} else {
@ -583,7 +583,7 @@ pub fn byte_lit(lit: &str) -> (u8, usize) {
b'\'' => b'\'',
b'0' => b'\0',
_ => {
match ::std::num::from_str_radix::<u64>(&lit[2..4], 16) {
match ::std::num::from_str_radix::<u64>(&lit[2..4], 16).ok() {
Some(c) =>
if c > 0xFF {
panic!(err(2))
@ -732,7 +732,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) ->
debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \
string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix);
let res: u64 = match ::std::num::from_str_radix(s, base) {
let res: u64 = match ::std::num::from_str_radix(s, base).ok() {
Some(r) => r,
None => { sd.span_err(sp, "int literal is too large"); 0 }
};

View File

@ -2459,7 +2459,7 @@ impl<'a> Parser<'a> {
hi = self.span.hi;
self.bump();
let index = n.as_str().parse::<usize>();
let index = n.as_str().parse::<usize>().ok();
match index {
Some(n) => {
let id = spanned(dot, hi, n);
@ -2479,7 +2479,7 @@ impl<'a> Parser<'a> {
self.span_err(last_span,
&format!("unexpected token: `{}`", n.as_str())[]);
if fstr.chars().all(|x| "0123456789.".contains_char(x)) {
let float = match fstr.parse::<f64>() {
let float = match fstr.parse::<f64>().ok() {
Some(f) => f,
None => continue,
};

View File

@ -27,14 +27,15 @@ enum Mode {
}
impl FromStr for Mode {
fn from_str(s: &str) -> Option<Mode> {
type Err = ();
fn from_str(s: &str) -> Result<Mode, ()> {
let mode = match s {
"expr" => Mode::Expression,
"pat" => Mode::Pattern,
"ty" => Mode::Type,
_ => return None
_ => return Err(())
};
Some(mode)
Ok(mode)
}
}
@ -73,7 +74,7 @@ impl<'a, 'v> Visitor<'v> for ShowSpanVisitor<'a> {
pub fn run(span_diagnostic: &diagnostic::SpanHandler,
mode: &str,
krate: &ast::Crate) {
let mode = match mode.parse() {
let mode = match mode.parse().ok() {
Some(mode) => mode,
None => return
};

View File

@ -74,7 +74,6 @@ use std::old_io;
use std::iter::repeat;
use std::num::{Float, Int};
use std::os;
use std::str::FromStr;
use std::sync::mpsc::{channel, Sender};
use std::thread::{self, Thread};
use std::thunk::{Thunk, Invoke};
@ -818,7 +817,7 @@ fn get_concurrency() -> uint {
use std::rt;
match os::getenv("RUST_TEST_TASKS") {
Some(s) => {
let opt_n: Option<uint> = FromStr::from_str(s.as_slice());
let opt_n: Option<uint> = s.parse().ok();
match opt_n {
Some(n) if n > 0 => n,
_ => panic!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s)

View File

@ -19,7 +19,7 @@ pub trait read {
impl read for int {
fn readMaybe(s: String) -> Option<int> {
s.parse()
s.parse().ok()
}
}

View File

@ -232,7 +232,7 @@ fn main() {
} else {
std::os::args().as_slice()
.get(1)
.and_then(|arg| arg.parse())
.and_then(|arg| arg.parse().ok())
.unwrap_or(600u)
};

View File

@ -182,7 +182,7 @@ fn fannkuch(n: i32) -> (i32, i32) {
fn main() {
let n = std::os::args().as_slice()
.get(1)
.and_then(|arg| arg.parse())
.and_then(|arg| arg.parse().ok())
.unwrap_or(2i32);
let (checksum, maxflips) = fannkuch(n);

View File

@ -174,7 +174,7 @@ fn main() {
5000000
} else {
std::os::args().get(1)
.and_then(|arg| arg.parse())
.and_then(|arg| arg.parse().ok())
.unwrap_or(1000)
};
let mut bodies = BODIES;

View File

@ -68,10 +68,10 @@ fn main() {
let token = if std::os::getenv("RUST_BENCH").is_some() {
2000000
} else {
args.get(1).and_then(|arg| arg.parse()).unwrap_or(1000)
args.get(1).and_then(|arg| arg.parse().ok()).unwrap_or(1000)
};
let n_tasks = args.get(2)
.and_then(|arg| arg.parse())
.and_then(|arg| arg.parse().ok())
.unwrap_or(503);
start(n_tasks, token);

View File

@ -14,7 +14,7 @@ pub fn main() {
// sometimes we have had trouble finding
// the right type for f, as we unified
// bot and u32 here
let f = match "1234".parse::<uint>() {
let f = match "1234".parse::<uint>().ok() {
None => return (),
Some(num) => num as u32
};

View File

@ -41,7 +41,7 @@ fn find_zombies() {
if 0 < line_no && 0 < line.len() &&
my_pid == line.split(' ').filter(|w| 0 < w.len()).nth(1)
.expect("1st column should be PPID")
.parse()
.parse().ok()
.expect("PPID string into integer") &&
line.contains("defunct") {
panic!("Zombie child {}", line);