]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/io/mod.rs
Improve error messages for io::fs
[rust.git] / src / libstd / io / mod.rs
index a1e0fa889789f39b3b59a1f3a50c6cdd781d1641..a7f84899a622e1703858bab178a2fe3059a6bdbc 100644 (file)
@@ -232,7 +232,7 @@ fn file_product(p: &Path) -> IoResult<u32> {
 use result::{Ok, Err, Result};
 use rt::rtio;
 use slice::{Vector, MutableVector, ImmutableVector};
-use str::{StrSlice, StrAllocating};
+use str::{Str, StrSlice, StrAllocating};
 use str;
 use string::String;
 use uint;
@@ -309,6 +309,7 @@ impl IoError {
     /// struct is filled with an allocated string describing the error
     /// in more detail, retrieved from the operating system.
     pub fn from_errno(errno: uint, detail: bool) -> IoError {
+
         #[cfg(windows)]
         fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
             match errno {
@@ -388,8 +389,8 @@ fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
         IoError {
             kind: kind,
             desc: desc,
-            detail: if detail {
-                Some(os::error_string(errno))
+            detail: if detail && kind == OtherIoError {
+                Some(os::error_string(errno).as_slice().chars().map(|c| c.to_lowercase()).collect())
             } else {
                 None
             },
@@ -420,10 +421,13 @@ fn from_rtio_error(err: rtio::IoError) -> IoError {
 
 impl fmt::Show for IoError {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(fmt, "{}", self.desc));
-        match self.detail {
-            Some(ref s) => write!(fmt, " ({})", *s),
-            None => Ok(())
+        match *self {
+            IoError { kind: OtherIoError, desc: "unknown error", detail: Some(ref detail) } =>
+                write!(fmt, "{}", detail),
+            IoError { detail: None, desc, .. } =>
+                write!(fmt, "{}", desc),
+            IoError { detail: Some(ref detail), desc, .. } =>
+                write!(fmt, "{} ({})", desc, detail)
         }
     }
 }
@@ -484,6 +488,37 @@ pub enum IoErrorKind {
     NoProgress,
 }
 
+/// A trait that lets you add a `detail` to an IoError easily
+trait UpdateIoError<T> {
+    /// Returns an IoError with updated description and detail
+    fn update_err(self, desc: &'static str, detail: |&IoError| -> String) -> Self;
+
+    /// Returns an IoError with updated detail
+    fn update_detail(self, detail: |&IoError| -> String) -> Self;
+
+    /// Returns an IoError with update description
+    fn update_desc(self, desc: &'static str) -> Self;
+}
+
+impl<T> UpdateIoError<T> for IoResult<T> {
+    fn update_err(self, desc: &'static str, detail: |&IoError| -> String) -> IoResult<T> {
+        self.map_err(|mut e| {
+            let detail = detail(&e);
+            e.desc = desc;
+            e.detail = Some(detail);
+            e
+        })
+    }
+
+    fn update_detail(self, detail: |&IoError| -> String) -> IoResult<T> {
+        self.map_err(|mut e| { e.detail = Some(detail(&e)); e })
+    }
+
+    fn update_desc(self, desc: &'static str) -> IoResult<T> {
+        self.map_err(|mut e| { e.desc = desc; e })
+    }
+}
+
 static NO_PROGRESS_LIMIT: uint = 1000;
 
 /// A trait for objects which are byte-oriented streams. Readers are defined by
@@ -1577,7 +1612,7 @@ pub fn standard_error(kind: IoErrorKind) -> IoError {
         ConnectionAborted => "connection aborted",
         NotConnected => "not connected",
         BrokenPipe => "broken pipe",
-        PathAlreadyExists => "file exists",
+        PathAlreadyExists => "file already exists",
         PathDoesntExist => "no such file",
         MismatchedFileTypeForOperation => "mismatched file type",
         ResourceUnavailable => "resource unavailable",