about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorLindsey Kuper <lindsey@composition.al>2013-08-31 23:51:07 -0400
committerLindsey Kuper <lindsey@composition.al>2013-09-05 06:25:23 -0400
commit8651011b6fffb7f95a354ce85eeb1d2aa4b476a5 (patch)
treee1c86fc3f9c287935250ac7ed9a598c227c51d8e /src/libstd
parentd285ea791058f7db8bef828740aae95e69becc99 (diff)
downloadrust-8651011b6fffb7f95a354ce85eeb1d2aa4b476a5.tar.gz
rust-8651011b6fffb7f95a354ce85eeb1d2aa4b476a5.zip
Factor shared code out into default GenericPath methods.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/path.rs367
1 files changed, 144 insertions, 223 deletions
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index d95c7b65101..16af8b1da3e 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -57,42 +57,97 @@ pub fn PosixPath(s: &str) -> PosixPath {
     GenericPath::from_str(s)
 }
 
-pub trait GenericPath {
+pub trait GenericPath : Clone + Eq + ToStr {
     /// Converts a string to a Path
     fn from_str(&str) -> Self;
 
     /// Returns the directory component of `self`, as a string
-    fn dirname(&self) -> ~str;
+    fn dirname(&self) -> ~str {
+        let s = self.dir_path().to_str();
+        match s.len() {
+            0 => ~".",
+            _ => s,
+        }
+    }
+
     /// Returns the file component of `self`, as a string option.
     /// Returns None if `self` names a directory.
-    fn filename<'a>(&'a self) -> Option<&'a str>;
+    fn filename<'a>(&'a self) -> Option<&'a str> {
+        match self.components().len() {
+            0 => None,
+            n => Some(self.components()[n - 1].as_slice()),
+        }
+    }
+
     /// Returns the stem of the file component of `self`, as a string option.
     /// The stem is the slice of a filename starting at 0 and ending just before
     /// the last '.' in the name.
     /// Returns None if `self` names a directory.
-    fn filestem<'a>(&'a self) -> Option<&'a str>;
+    fn filestem<'a>(&'a self) -> Option<&'a str> {
+        match self.filename() {
+            None => None,
+            Some(ref f) => {
+                match f.rfind('.') {
+                    Some(p) => Some(f.slice_to(p)),
+                    None => Some((*f)),
+                }
+            }
+        }
+    }
+
     /// Returns the type of the file component of `self`, as a string option.
     /// The file type is the slice of a filename starting just after the last
     /// '.' in the name and ending at the last index in the filename.
     /// Returns None if `self` names a directory.
-    fn filetype<'a>(&'a self) -> Option<&'a str>;
+    fn filetype<'a>(&'a self) -> Option<&'a str> {
+        match self.filename() {
+            None => None,
+            Some(ref f) => {
+                match f.rfind('.') {
+                    Some(p) if p < f.len() => Some(f.slice_from(p)),
+                    _ => None,
+                }
+            }
+        }
+    }
 
     /// Returns a new path consisting of `self` with the parent directory component replaced
     /// with the given string.
     fn with_dirname(&self, (&str)) -> Self;
+
     /// Returns a new path consisting of `self` with the file component replaced
     /// with the given string.
     fn with_filename(&self, (&str)) -> Self;
+
     /// Returns a new path consisting of `self` with the file stem replaced
     /// with the given string.
-    fn with_filestem(&self, (&str)) -> Self;
+    fn with_filestem(&self, s: &str) -> Self {
+        match self.filetype() {
+            None => self.with_filename(s),
+            Some(ref t) => self.with_filename(s.to_owned() + *t),
+        }
+    }
+
     /// Returns a new path consisting of `self` with the file type replaced
     /// with the given string.
-    fn with_filetype(&self, (&str)) -> Self;
+    fn with_filetype(&self, t: &str) -> Self {
+        match (t.len(), self.filestem()) {
+            (0, None)        => (*self).clone(),
+            (0, Some(ref s)) => self.with_filename(*s),
+            (_, None)        => self.with_filename(fmt!(".%s", t)),
+            (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
+        }
+    }
 
     /// Returns the directory component of `self`, as a new path.
     /// If `self` has no parent, returns `self`.
-    fn dir_path(&self) -> Self;
+    fn dir_path(&self) -> Self {
+        match self.components().len() {
+            0 => (*self).clone(),
+            _ => self.pop(),
+        }
+    }
+
     /// Returns the file component of `self`, as a new path.
     /// If `self` names a directory, returns the empty path.
     fn file_path(&self) -> Self;
@@ -100,11 +155,17 @@ pub trait GenericPath {
     /// Returns a new Path whose parent directory is `self` and whose
     /// file component is the given string.
     fn push(&self, (&str)) -> Self;
+
     /// Returns a new Path consisting of the given path, made relative to `self`.
-    fn push_rel(&self, (&Self)) -> Self;
+    fn push_rel(&self, other: &Self) -> Self {
+        assert!(!other.is_absolute());
+        self.push_many(other.components())
+    }
+
     /// Returns a new Path consisting of the path given by the given vector
     /// of strings, relative to `self`.
     fn push_many<S: Str>(&self, (&[S])) -> Self;
+
     /// Identical to `dir_path` except in the case where `self` has only one
     /// component. In this case, `pop` returns the empty path.
     fn pop(&self) -> Self;
@@ -112,6 +173,7 @@ pub trait GenericPath {
     /// The same as `push_rel`, except that the directory argument must not
     /// contain directory separators in any of its components.
     fn unsafe_join(&self, (&Self)) -> Self;
+
     /// On Unix, always returns false. On Windows, returns true iff `self`'s
     /// file stem is one of: `con` `aux` `com1` `com2` `com3` `com4`
     /// `lpt1` `lpt2` `lpt3` `prn` `nul`
@@ -126,7 +188,14 @@ pub trait GenericPath {
     fn is_absolute(&self) -> bool;
 
     /// True if `self` is an ancestor of `other`. See `test_is_ancestor_of` for examples
-    fn is_ancestor_of(&self, (&Self)) -> bool;
+    fn is_ancestor_of(&self, other: &Self) -> bool {
+        debug!("%s / %s %? %?", self.to_str(), other.to_str(), self.is_absolute(),
+               self.components().len());
+        self == other ||
+            (!other.components().is_empty() &&
+             !(self.components().is_empty() && !self.is_absolute()) &&
+             self.is_ancestor_of(&other.pop()))
+    }
 
     /// Find the relative path from one file to another
     fn get_relative_to(&self, abs2: (&Self)) -> Self {
@@ -578,8 +647,6 @@ impl ToCStr for PosixPath {
     }
 }
 
-// FIXME (#3227): when default methods in traits are working, de-duplicate
-// PosixPath and WindowsPath, most of their methods are common.
 impl GenericPath for PosixPath {
     fn from_str(s: &str) -> PosixPath {
         let components = s.split_iter('/')
@@ -592,45 +659,6 @@ impl GenericPath for PosixPath {
         }
     }
 
-    fn dirname(&self) -> ~str {
-        let s = self.dir_path().to_str();
-        match s.len() {
-            0 => ~".",
-            _ => s,
-        }
-    }
-
-    fn filename<'a>(&'a self) -> Option<&'a str> {
-        match self.components.len() {
-            0 => None,
-            n => Some(self.components[n - 1].as_slice()),
-        }
-    }
-
-    fn filestem<'a>(&'a self) -> Option<&'a str> {
-        match self.filename() {
-            None => None,
-            Some(ref f) => {
-                match f.rfind('.') {
-                    Some(p) => Some(f.slice_to(p)),
-                    None => Some((*f)),
-                }
-            }
-        }
-    }
-
-    fn filetype<'a>(&'a self) -> Option<&'a str> {
-        match self.filename() {
-            None => None,
-            Some(ref f) => {
-                match f.rfind('.') {
-                    Some(p) if p < f.len() => Some(f.slice_from(p)),
-                    _ => None,
-                }
-            }
-        }
-    }
-
     fn with_dirname(&self, d: &str) -> PosixPath {
         let dpath = PosixPath(d);
         match self.filename() {
@@ -644,29 +672,6 @@ impl GenericPath for PosixPath {
         self.dir_path().push(f)
     }
 
-    fn with_filestem(&self, s: &str) -> PosixPath {
-        match self.filetype() {
-            None => self.with_filename(s),
-            Some(ref t) => self.with_filename(s.to_owned() + *t),
-        }
-    }
-
-    fn with_filetype(&self, t: &str) -> PosixPath {
-        match (t.len(), self.filestem()) {
-            (0, None)        => (*self).clone(),
-            (0, Some(ref s)) => self.with_filename(*s),
-            (_, None)        => self.with_filename(fmt!(".%s", t)),
-            (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
-        }
-    }
-
-    fn dir_path(&self) -> PosixPath {
-        match self.components.len() {
-            0 => (*self).clone(),
-            _ => self.pop(),
-        }
-    }
-
     fn file_path(&self) -> PosixPath {
         let cs = match self.filename() {
           None => ~[],
@@ -678,24 +683,17 @@ impl GenericPath for PosixPath {
         }
     }
 
-    fn push_rel(&self, other: &PosixPath) -> PosixPath {
-        assert!(!other.is_absolute);
-        self.push_many(other.components)
-    }
-
-    fn unsafe_join(&self, other: &PosixPath) -> PosixPath {
-        if other.is_absolute {
-            PosixPath {
-                is_absolute: true,
-                components: other.components.clone(),
+    fn push(&self, s: &str) -> PosixPath {
+        let mut v = self.components.clone();
+        for s in s.split_iter(posix::is_sep) {
+            if !s.is_empty() {
+                v.push(s.to_owned())
             }
-        } else {
-            self.push_rel(other)
         }
-    }
-
-    fn is_restricted(&self) -> bool {
-        false
+        PosixPath {
+            components: v,
+            ..(*self).clone()
+        }
     }
 
     fn push_many<S: Str>(&self, cs: &[S]) -> PosixPath {
@@ -713,19 +711,6 @@ impl GenericPath for PosixPath {
         }
     }
 
-    fn push(&self, s: &str) -> PosixPath {
-        let mut v = self.components.clone();
-        for s in s.split_iter(posix::is_sep) {
-            if !s.is_empty() {
-                v.push(s.to_owned())
-            }
-        }
-        PosixPath {
-            components: v,
-            ..(*self).clone()
-        }
-    }
-
     fn pop(&self) -> PosixPath {
         let mut cs = self.components.clone();
         if cs.len() != 0 {
@@ -737,6 +722,21 @@ impl GenericPath for PosixPath {
         } //..self }
     }
 
+    fn unsafe_join(&self, other: &PosixPath) -> PosixPath {
+        if other.is_absolute {
+            PosixPath {
+                is_absolute: true,
+                components: other.components.clone(),
+            }
+        } else {
+            self.push_rel(other)
+        }
+    }
+
+    fn is_restricted(&self) -> bool {
+        false
+    }
+
     fn normalize(&self) -> PosixPath {
         PosixPath {
             is_absolute: self.is_absolute,
@@ -748,15 +748,8 @@ impl GenericPath for PosixPath {
         self.is_absolute
     }
 
-    fn is_ancestor_of(&self, other: &PosixPath) -> bool {
-        debug!("%s / %s %? %?", self.to_str(), other.to_str(), self.is_absolute,
-               self.components.len());
-        self == other ||
-            (!other.components.is_empty() && !(self.components.is_empty() && !self.is_absolute) &&
-             self.is_ancestor_of(&other.pop()))
-    }
+    fn components<'a>(&'a self) -> &'a [~str] { self.components.as_slice() }
 
-   fn components<'a>(&'a self) -> &'a [~str] { self.components.as_slice() }
 }
 
 
@@ -834,45 +827,6 @@ impl GenericPath for WindowsPath {
         }
     }
 
-    fn dirname(&self) -> ~str {
-        let s = self.dir_path().to_str();
-        match s.len() {
-            0 => ~".",
-            _ => s,
-        }
-    }
-
-    fn filename<'a>(&'a self) -> Option<&'a str> {
-        match self.components.len() {
-            0 => None,
-            n => Some(self.components[n - 1].as_slice()),
-        }
-    }
-
-    fn filestem<'a>(&'a self) -> Option<&'a str> {
-        match self.filename() {
-            None => None,
-            Some(ref f) => {
-                match f.rfind('.') {
-                    Some(p) => Some(f.slice_to(p)),
-                    None => Some((*f)),
-                }
-            }
-        }
-    }
-
-    fn filetype<'a>(&'a self) -> Option<&'a str> {
-        match self.filename() {
-          None => None,
-          Some(ref f) => {
-            match f.rfind('.') {
-                Some(p) if p < f.len() => Some(f.slice_from(p)),
-                _ => None,
-            }
-          }
-        }
-    }
-
     fn with_dirname(&self, d: &str) -> WindowsPath {
         let dpath = WindowsPath(d);
         match self.filename() {
@@ -886,29 +840,6 @@ impl GenericPath for WindowsPath {
         self.dir_path().push(f)
     }
 
-    fn with_filestem(&self, s: &str) -> WindowsPath {
-        match self.filetype() {
-            None => self.with_filename(s),
-            Some(ref t) => self.with_filename(s.to_owned() + *t),
-        }
-    }
-
-    fn with_filetype(&self, t: &str) -> WindowsPath {
-        match (t.len(), self.filestem()) {
-            (0, None)        => (*self).clone(),
-            (0, Some(ref s)) => self.with_filename(*s),
-            (_, None)        => self.with_filename(fmt!(".%s", t)),
-            (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
-        }
-    }
-
-    fn dir_path(&self) -> WindowsPath {
-        match self.components.len() {
-            0 => (*self).clone(),
-            _ => self.pop(),
-        }
-    }
-
     fn file_path(&self) -> WindowsPath {
         WindowsPath {
             host: None,
@@ -921,9 +852,45 @@ impl GenericPath for WindowsPath {
         }
     }
 
-    fn push_rel(&self, other: &WindowsPath) -> WindowsPath {
-        assert!(!other.is_absolute);
-        self.push_many(other.components)
+    fn push(&self, s: &str) -> WindowsPath {
+        let mut v = self.components.clone();
+        for s in s.split_iter(windows::is_sep) {
+            if !s.is_empty() {
+                v.push(s.to_owned())
+            }
+        }
+        WindowsPath { components: v, ..(*self).clone() }
+    }
+
+    fn push_many<S: Str>(&self, cs: &[S]) -> WindowsPath {
+        let mut v = self.components.clone();
+        for e in cs.iter() {
+            for s in e.as_slice().split_iter(windows::is_sep) {
+                if !s.is_empty() {
+                    v.push(s.to_owned())
+                }
+            }
+        }
+        // tedious, but as-is, we can't use ..self
+        WindowsPath {
+            host: self.host.clone(),
+            device: self.device.clone(),
+            is_absolute: self.is_absolute,
+            components: v
+        }
+    }
+
+    fn pop(&self) -> WindowsPath {
+        let mut cs = self.components.clone();
+        if cs.len() != 0 {
+            cs.pop();
+        }
+        WindowsPath {
+            host: self.host.clone(),
+            device: self.device.clone(),
+            is_absolute: self.is_absolute,
+            components: cs,
+        }
     }
 
     fn unsafe_join(&self, other: &WindowsPath) -> WindowsPath {
@@ -983,47 +950,6 @@ impl GenericPath for WindowsPath {
         }
     }
 
-    fn push_many<S: Str>(&self, cs: &[S]) -> WindowsPath {
-        let mut v = self.components.clone();
-        for e in cs.iter() {
-            for s in e.as_slice().split_iter(windows::is_sep) {
-                if !s.is_empty() {
-                    v.push(s.to_owned())
-                }
-            }
-        }
-        // tedious, but as-is, we can't use ..self
-        WindowsPath {
-            host: self.host.clone(),
-            device: self.device.clone(),
-            is_absolute: self.is_absolute,
-            components: v
-        }
-    }
-
-    fn push(&self, s: &str) -> WindowsPath {
-        let mut v = self.components.clone();
-        for s in s.split_iter(windows::is_sep) {
-            if !s.is_empty() {
-                v.push(s.to_owned())
-            }
-        }
-        WindowsPath { components: v, ..(*self).clone() }
-    }
-
-    fn pop(&self) -> WindowsPath {
-        let mut cs = self.components.clone();
-        if cs.len() != 0 {
-            cs.pop();
-        }
-        WindowsPath {
-            host: self.host.clone(),
-            device: self.device.clone(),
-            is_absolute: self.is_absolute,
-            components: cs,
-        }
-    }
-
     fn normalize(&self) -> WindowsPath {
         WindowsPath {
             host: self.host.clone(),
@@ -1043,13 +969,8 @@ impl GenericPath for WindowsPath {
         self.is_absolute
     }
 
-    fn is_ancestor_of(&self, other: &WindowsPath) -> bool {
-        self == other ||
-            (!other.components.is_empty() && !(self.components.is_empty() && !self.is_absolute) &&
-             self.is_ancestor_of(&other.pop()))
-    }
+    fn components<'a>(&'a self) -> &'a [~str] { self.components.as_slice() }
 
-   fn components<'a>(&'a self) -> &'a [~str] { self.components.as_slice() }
 }
 
 pub fn normalize(components: &[~str]) -> ~[~str] {