about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-01-30 12:03:20 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-30 12:03:20 -0800
commitac1a03d7422ba52749e4e513a46c8d2129c2c817 (patch)
treecefa26a551d7703c5f8534cc6661432348c93e06 /src/libstd
parent0ba812fbf00e3026b29282e1a72d58ea7959833e (diff)
parent0cdde6e5e015ee6f6d9381ab624a312af7c9b069 (diff)
downloadrust-ac1a03d7422ba52749e4e513a46c8d2129c2c817.tar.gz
rust-ac1a03d7422ba52749e4e513a46c8d2129c2c817.zip
rollup merge of #21718: alexcrichton/stabilize-from-str
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
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/num/uint_macros.rs20
-rw-r--r--src/libstd/old_io/net/ip.rs108
-rw-r--r--src/libstd/path/posix.rs13
-rw-r--r--src/libstd/path/windows.rs13
-rw-r--r--src/libstd/rt/util.rs4
5 files changed, 93 insertions, 65 deletions
diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs
index 82c55d7b5b8..4cd6391318f 100644
--- a/src/libstd/num/uint_macros.rs
+++ b/src/libstd/num/uint_macros.rs
@@ -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("Z", 10), None::<$T>);
-        assert_eq!(FromStrRadix::from_str_radix("_", 2), None::<$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).ok(), None::<$T>);
+        assert_eq!(FromStrRadix::from_str_radix("_", 2).ok(), None::<$T>);
     }
 
     #[test]
diff --git a/src/libstd/old_io/net/ip.rs b/src/libstd/old_io/net/ip.rs
index f0b73bd37f2..3e2e69f75a6 100644
--- a/src/libstd/old_io/net/ip.rs
+++ b/src/libstd/old_io/net/ip.rs
@@ -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);
     }
 
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
index 588f724134e..72c41f2399e 100644
--- a/src/libstd/path/posix.rs
+++ b/src/libstd/path/posix.rs
@@ -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) {
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
index 98e0320cd14..e04f697b2a4 100644
--- a/src/libstd/path/windows.rs
+++ b/src/libstd/path/windows.rs
@@ -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]
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index 4023a0a4c10..f5727a38b69 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -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)