]> git.lizzy.rs Git - rust.git/commitdiff
Rename std::path to std::old_path
authorAaron Turon <aturon@mozilla.com>
Thu, 29 Jan 2015 22:03:36 +0000 (14:03 -0800)
committerAaron Turon <aturon@mozilla.com>
Tue, 3 Feb 2015 22:34:42 +0000 (14:34 -0800)
As part of [RFC 474](https://github.com/rust-lang/rfcs/pull/474), this
commit renames `std::path` to `std::old_path`, leaving the existing path
API in place to ease migration to the new one. Updating should be as
simple as adjusting imports, and the prelude still maps to the old path
APIs for now.

[breaking-change]

29 files changed:
src/libcore/error.rs
src/libgraphviz/maybe_owned_vec.rs
src/librustc_back/target/mod.rs
src/librustc_trans/trans/debuginfo.rs
src/librustdoc/clean/mod.rs
src/libserialize/serialize.rs
src/libstd/env.rs
src/libstd/lib.rs
src/libstd/old_io/fs.rs
src/libstd/old_io/net/pipe.rs
src/libstd/old_io/process.rs
src/libstd/old_io/tempfile.rs
src/libstd/old_path/mod.rs [new file with mode: 0644]
src/libstd/old_path/posix.rs [new file with mode: 0644]
src/libstd/old_path/windows.rs [new file with mode: 0644]
src/libstd/os.rs
src/libstd/path/mod.rs [deleted file]
src/libstd/path/posix.rs [deleted file]
src/libstd/path/windows.rs [deleted file]
src/libstd/prelude/v1.rs
src/libstd/rand/os.rs
src/libstd/sys/common/mod.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/process.rs
src/libsyntax/parse/token.rs
src/test/compile-fail/range-3.rs
src/test/compile-fail/range-4.rs
src/test/debuginfo/associated-types.rs

index 71d5e88cccff70e9cd647e3bacf66ff9476eab09..161f6c78921630e68c952fdeb90de7fe4627620c 100644 (file)
@@ -51,7 +51,7 @@
 //! use std::error::FromError;
 //! use std::old_io::{File, IoError};
 //! use std::os::{MemoryMap, MapError};
-//! use std::path::Path;
+//! use std::old_path::Path;
 //!
 //! enum MyError {
 //!     Io(IoError),
index 71f117835935d63c8aa4fadab9005537f191b11e..1c931856fa17c5a9e9c9d82be30304d8e41fe715 100644 (file)
@@ -17,7 +17,7 @@
 use std::default::Default;
 use std::fmt;
 use std::iter::FromIterator;
-use std::path::BytesContainer;
+use std::old_path::BytesContainer;
 use std::slice;
 
 // Note 1: It is not clear whether the flexibility of providing both
index 4b3833b687c5b53e176fe511c949a67382357409..bffee9d49334da43c3bedcb1d7743a7e66523f1b 100644 (file)
@@ -306,7 +306,7 @@ pub fn search(target: &str) -> Result<Target, String> {
         use std::env;
         use std::ffi::OsString;
         use std::old_io::File;
-        use std::path::Path;
+        use std::old_path::Path;
         use serialize::json;
 
         fn load_file(path: &Path) -> Result<Target, String> {
index 66bb299273d9f86aa7aa4861f7468f3eddf783b0..0ced4066f625b7150238385cdc832b92b5ea159f 100644 (file)
@@ -1590,7 +1590,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
                     Some(ref p) if p.is_relative() => {
                         // prepend "./" if necessary
                         let dotdot = b"..";
-                        let prefix: &[u8] = &[dotdot[0], ::std::path::SEP_BYTE];
+                        let prefix: &[u8] = &[dotdot[0], ::std::old_path::SEP_BYTE];
                         let mut path_bytes = p.as_vec().to_vec();
 
                         if &path_bytes[..2] != prefix &&
index 07679480bfb39ef6f6f2702070d99df4c98cdf09..57eaf042aa02edc676697cb3173d92d881dd0209 100644 (file)
@@ -49,7 +49,7 @@
 use std::rc::Rc;
 use std::u32;
 use std::str::Str as StrTrait; // Conflicts with Str variant
-use std::path::Path as FsPath; // Conflicts with Path struct
+use std::old_path::Path as FsPath; // Conflicts with Path struct
 
 use core::DocContext;
 use doctree;
index 3d7c91ad1885925e82bd9500a41ebdca3714f6d1..517907bcf58e347c3e94b7f876e66026a7aef97d 100644 (file)
@@ -14,7 +14,7 @@
 Core encoding and decoding interfaces.
 */
 
-use std::path;
+use std::old_path;
 use std::rc::Rc;
 use std::cell::{Cell, RefCell};
 use std::sync::Arc;
@@ -538,29 +538,29 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
-impl Encodable for path::posix::Path {
+impl Encodable for old_path::posix::Path {
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         self.as_vec().encode(e)
     }
 }
 
-impl Decodable for path::posix::Path {
-    fn decode<D: Decoder>(d: &mut D) -> Result<path::posix::Path, D::Error> {
+impl Decodable for old_path::posix::Path {
+    fn decode<D: Decoder>(d: &mut D) -> Result<old_path::posix::Path, D::Error> {
         let bytes: Vec<u8> = try!(Decodable::decode(d));
-        Ok(path::posix::Path::new(bytes))
+        Ok(old_path::posix::Path::new(bytes))
     }
 }
 
-impl Encodable for path::windows::Path {
+impl Encodable for old_path::windows::Path {
     fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
         self.as_vec().encode(e)
     }
 }
 
-impl Decodable for path::windows::Path {
-    fn decode<D: Decoder>(d: &mut D) -> Result<path::windows::Path, D::Error> {
+impl Decodable for old_path::windows::Path {
+    fn decode<D: Decoder>(d: &mut D) -> Result<old_path::windows::Path, D::Error> {
         let bytes: Vec<u8> = try!(Decodable::decode(d));
-        Ok(path::windows::Path::new(bytes))
+        Ok(old_path::windows::Path::new(bytes))
     }
 }
 
index 5070f8c547ab0663501b84ce25d29b291c84c561..559a68542efc890492144a2ec5289b739e059b68 100644 (file)
@@ -57,7 +57,7 @@ pub fn current_dir() -> IoResult<Path> {
 ///
 /// ```rust
 /// use std::env;
-/// use std::path::Path;
+/// use std::old_path::Path;
 ///
 /// let root = Path::new("/");
 /// assert!(env::set_current_dir(&root).is_ok());
index 839983d336d765e819cde518e8432b1c60731b4b..bd4763d7bd475eb6e99f417604ce27664c5cfcd5 100644 (file)
 pub mod os;
 pub mod env;
 pub mod path;
+pub mod old_path;
 pub mod rand;
 pub mod time;
 
index abf215988bb4b859982967ee3dda5ceeb3294d65..88ca6667d55deba1e56b8446824b6a9f73c48ddc 100644 (file)
@@ -61,8 +61,8 @@
 use iter::{Iterator, Extend};
 use option::Option;
 use option::Option::{Some, None};
-use path::{Path, GenericPath};
-use path;
+use old_path::{Path, GenericPath};
+use old_path;
 use result::Result::{Err, Ok};
 use slice::SliceExt;
 use string::String;
@@ -782,7 +782,7 @@ pub trait PathExtensions {
     fn is_dir(&self) -> bool;
 }
 
-impl PathExtensions for path::Path {
+impl PathExtensions for old_path::Path {
     fn stat(&self) -> IoResult<FileStat> { stat(self) }
     fn lstat(&self) -> IoResult<FileStat> { lstat(self) }
     fn exists(&self) -> bool {
index 0da7670c5b49cf2a2eda037c8557a45824a27f0f..8c4a10a55d489d86865f8ca661754fefc97d56b5 100644 (file)
@@ -23,7 +23,7 @@
 use prelude::v1::*;
 
 use ffi::CString;
-use path::BytesContainer;
+use old_path::BytesContainer;
 use old_io::{Listener, Acceptor, IoResult, TimedOut, standard_error};
 use sys::pipe::UnixAcceptor as UnixAcceptorImp;
 use sys::pipe::UnixListener as UnixListenerImp;
index 61a07bc8208eda35ffc5b3a96b6e329943e621d9..27af957e18e18614c591e47fd2911a9672cdd8f2 100644 (file)
@@ -25,7 +25,7 @@
 use old_io;
 use libc;
 use os;
-use path::BytesContainer;
+use old_path::BytesContainer;
 use sync::mpsc::{channel, Receiver};
 use sys::fs::FileDesc;
 use sys::process::Process as ProcessImp;
index 83a42549424d698dabee5242ff2075df1c04ceb0..a227116dfae997b4c3818f888fba4abf3a30e8bb 100644 (file)
@@ -17,7 +17,7 @@
 use ops::Drop;
 use option::Option::{None, Some};
 use option::Option;
-use path::{Path, GenericPath};
+use old_path::{Path, GenericPath};
 use rand::{Rng, thread_rng};
 use result::Result::{Ok, Err};
 use str::StrExt;
diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs
new file mode 100644 (file)
index 0000000..0d80258
--- /dev/null
@@ -0,0 +1,923 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Cross-platform path support
+//!
+//! This module implements support for two flavors of paths. `PosixPath` represents a path on any
+//! unix-like system, whereas `WindowsPath` represents a path on Windows. This module also exposes
+//! a typedef `Path` which is equal to the appropriate platform-specific path variant.
+//!
+//! Both `PosixPath` and `WindowsPath` implement a trait `GenericPath`, which contains the set of
+//! methods that behave the same for both paths. They each also implement some methods that could
+//! not be expressed in `GenericPath`, yet behave identically for both path flavors, such as
+//! `.components()`.
+//!
+//! The three main design goals of this module are 1) to avoid unnecessary allocation, 2) to behave
+//! the same regardless of which flavor of path is being used, and 3) to support paths that cannot
+//! be represented in UTF-8 (as Linux has no restriction on paths beyond disallowing NUL).
+//!
+//! ## Usage
+//!
+//! Usage of this module is fairly straightforward. Unless writing platform-specific code, `Path`
+//! should be used to refer to the platform-native path.
+//!
+//! Creation of a path is typically done with either `Path::new(some_str)` or
+//! `Path::new(some_vec)`. This path can be modified with `.push()` and `.pop()` (and other
+//! setters). The resulting Path can either be passed to another API that expects a path, or can be
+//! turned into a `&[u8]` with `.as_vec()` or a `Option<&str>` with `.as_str()`. Similarly,
+//! attributes of the path can be queried with methods such as `.filename()`. There are also
+//! methods that return a new path instead of modifying the receiver, such as `.join()` or
+//! `.dir_path()`.
+//!
+//! Paths are always kept in normalized form. This means that creating the path
+//! `Path::new("a/b/../c")` will return the path `a/c`. Similarly any attempt to mutate the path
+//! will always leave it in normalized form.
+//!
+//! When rendering a path to some form of output, there is a method `.display()` which is
+//! compatible with the `format!()` parameter `{}`. This will render the path as a string,
+//! replacing all non-utf8 sequences with the Replacement Character (U+FFFD). As such it is not
+//! suitable for passing to any API that actually operates on the path; it is only intended for
+//! display.
+//!
+//! ## Example
+//!
+//! ```rust
+//! use std::old_io::fs::PathExtensions;
+//!
+//! let mut path = Path::new("/tmp/path");
+//! println!("path: {}", path.display());
+//! path.set_filename("foo");
+//! path.push("bar");
+//! println!("new path: {}", path.display());
+//! println!("path exists: {}", path.exists());
+//! ```
+
+#![unstable(feature = "path")]
+
+use core::marker::Sized;
+use ffi::CString;
+use clone::Clone;
+use fmt;
+use iter::IteratorExt;
+use option::Option;
+use option::Option::{None, Some};
+use str;
+use str::StrExt;
+use string::{String, CowString};
+use slice::SliceExt;
+use vec::Vec;
+
+/// Typedef for POSIX file paths.
+/// See `posix::Path` for more info.
+pub use self::posix::Path as PosixPath;
+
+/// Typedef for Windows file paths.
+/// See `windows::Path` for more info.
+pub use self::windows::Path as WindowsPath;
+
+/// Typedef for the platform-native path type
+#[cfg(unix)]
+pub use self::posix::Path as Path;
+/// Typedef for the platform-native path type
+#[cfg(windows)]
+pub use self::windows::Path as Path;
+
+/// Typedef for the platform-native component iterator
+#[cfg(unix)]
+pub use self::posix::Components as Components;
+/// Typedef for the platform-native component iterator
+#[cfg(windows)]
+pub use self::windows::Components as Components;
+
+/// Typedef for the platform-native str component iterator
+#[cfg(unix)]
+pub use self::posix::StrComponents as StrComponents;
+/// Typedef for the platform-native str component iterator
+#[cfg(windows)]
+pub use self::windows::StrComponents as StrComponents;
+
+/// Alias for the platform-native separator character.
+#[cfg(unix)]
+pub use self::posix::SEP as SEP;
+/// Alias for the platform-native separator character.
+#[cfg(windows)]
+pub use self::windows::SEP as SEP;
+
+/// Alias for the platform-native separator byte.
+#[cfg(unix)]
+pub use self::posix::SEP_BYTE as SEP_BYTE;
+/// Alias for the platform-native separator byte.
+#[cfg(windows)]
+pub use self::windows::SEP_BYTE as SEP_BYTE;
+
+/// Typedef for the platform-native separator char func
+#[cfg(unix)]
+pub use self::posix::is_sep as is_sep;
+/// Typedef for the platform-native separator char func
+#[cfg(windows)]
+pub use self::windows::is_sep as is_sep;
+/// Typedef for the platform-native separator byte func
+#[cfg(unix)]
+pub use self::posix::is_sep_byte as is_sep_byte;
+/// Typedef for the platform-native separator byte func
+#[cfg(windows)]
+pub use self::windows::is_sep_byte as is_sep_byte;
+
+pub mod posix;
+pub mod windows;
+
+/// A trait that represents the generic operations available on paths
+pub trait GenericPath: Clone + GenericPathUnsafe {
+    /// Creates a new Path from a byte vector or string.
+    /// The resulting Path will always be normalized.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let path = Path::new("foo/bar");
+    /// # }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the path contains a NUL.
+    ///
+    /// See individual Path impls for additional restrictions.
+    #[inline]
+    fn new<T: BytesContainer>(path: T) -> Self {
+        assert!(!contains_nul(&path));
+        unsafe { GenericPathUnsafe::new_unchecked(path) }
+    }
+
+    /// Creates a new Path from a byte vector or string, if possible.
+    /// The resulting Path will always be normalized.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let x: &[u8] = b"foo\0";
+    /// assert!(Path::new_opt(x).is_none());
+    /// # }
+    /// ```
+    #[inline]
+    fn new_opt<T: BytesContainer>(path: T) -> Option<Self> {
+        if contains_nul(&path) {
+            None
+        } else {
+            Some(unsafe { GenericPathUnsafe::new_unchecked(path) })
+        }
+    }
+
+    /// Returns the path as a string, if possible.
+    /// If the path is not representable in utf-8, this returns None.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("/abc/def");
+    /// assert_eq!(p.as_str(), Some("/abc/def"));
+    /// # }
+    /// ```
+    #[inline]
+    fn as_str<'a>(&'a self) -> Option<&'a str> {
+        str::from_utf8(self.as_vec()).ok()
+    }
+
+    /// Returns the path as a byte vector
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def");
+    /// assert_eq!(p.as_vec(), b"abc/def");
+    /// # }
+    /// ```
+    fn as_vec<'a>(&'a self) -> &'a [u8];
+
+    /// Converts the Path into an owned byte vector
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def");
+    /// assert_eq!(p.into_vec(), b"abc/def".to_vec());
+    /// // attempting to use p now results in "error: use of moved value"
+    /// # }
+    /// ```
+    fn into_vec(self) -> Vec<u8>;
+
+    /// Returns an object that implements `Show` for printing paths
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def");
+    /// println!("{}", p.display()); // prints "abc/def"
+    /// # }
+    /// ```
+    fn display<'a>(&'a self) -> Display<'a, Self> {
+        Display{ path: self, filename: false }
+    }
+
+    /// Returns an object that implements `Show` for printing filenames
+    ///
+    /// If there is no filename, nothing will be printed.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def");
+    /// println!("{}", p.filename_display()); // prints "def"
+    /// # }
+    /// ```
+    fn filename_display<'a>(&'a self) -> Display<'a, Self> {
+        Display{ path: self, filename: true }
+    }
+
+    /// Returns the directory component of `self`, as a byte vector (with no trailing separator).
+    /// If `self` has no directory component, returns ['.'].
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def/ghi");
+    /// assert_eq!(p.dirname(), b"abc/def");
+    /// # }
+    /// ```
+    fn dirname<'a>(&'a self) -> &'a [u8];
+
+    /// Returns the directory component of `self`, as a string, if possible.
+    /// See `dirname` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def/ghi");
+    /// assert_eq!(p.dirname_str(), Some("abc/def"));
+    /// # }
+    /// ```
+    #[inline]
+    fn dirname_str<'a>(&'a self) -> Option<&'a str> {
+        str::from_utf8(self.dirname()).ok()
+    }
+
+    /// Returns the file component of `self`, as a byte vector.
+    /// If `self` represents the root of the file hierarchy, returns None.
+    /// If `self` is "." or "..", returns None.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def/ghi");
+    /// assert_eq!(p.filename(), Some(b"ghi"));
+    /// # }
+    /// ```
+    fn filename<'a>(&'a self) -> Option<&'a [u8]>;
+
+    /// Returns the file component of `self`, as a string, if possible.
+    /// See `filename` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def/ghi");
+    /// assert_eq!(p.filename_str(), Some("ghi"));
+    /// # }
+    /// ```
+    #[inline]
+    fn filename_str<'a>(&'a self) -> Option<&'a str> {
+        self.filename().and_then(|s| str::from_utf8(s).ok())
+    }
+
+    /// Returns the stem of the filename of `self`, as a byte vector.
+    /// The stem is the portion of the filename just before the last '.'.
+    /// If there is no '.', the entire filename is returned.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("/abc/def.txt");
+    /// assert_eq!(p.filestem(), Some(b"def"));
+    /// # }
+    /// ```
+    fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
+        match self.filename() {
+            None => None,
+            Some(name) => Some({
+                let dot = b'.';
+                match name.rposition_elem(&dot) {
+                    None | Some(0) => name,
+                    Some(1) if name == b".." => name,
+                    Some(pos) => &name[..pos]
+                }
+            })
+        }
+    }
+
+    /// Returns the stem of the filename of `self`, as a string, if possible.
+    /// See `filestem` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("/abc/def.txt");
+    /// assert_eq!(p.filestem_str(), Some("def"));
+    /// # }
+    /// ```
+    #[inline]
+    fn filestem_str<'a>(&'a self) -> Option<&'a str> {
+        self.filestem().and_then(|s| str::from_utf8(s).ok())
+    }
+
+    /// Returns the extension of the filename of `self`, as an optional byte vector.
+    /// The extension is the portion of the filename just after the last '.'.
+    /// If there is no extension, None is returned.
+    /// If the filename ends in '.', the empty vector is returned.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def.txt");
+    /// assert_eq!(p.extension(), Some(b"txt"));
+    /// # }
+    /// ```
+    fn extension<'a>(&'a self) -> Option<&'a [u8]> {
+        match self.filename() {
+            None => None,
+            Some(name) => {
+                let dot = b'.';
+                match name.rposition_elem(&dot) {
+                    None | Some(0) => None,
+                    Some(1) if name == b".." => None,
+                    Some(pos) => Some(&name[pos+1..])
+                }
+            }
+        }
+    }
+
+    /// Returns the extension of the filename of `self`, as a string, if possible.
+    /// See `extension` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def.txt");
+    /// assert_eq!(p.extension_str(), Some("txt"));
+    /// # }
+    /// ```
+    #[inline]
+    fn extension_str<'a>(&'a self) -> Option<&'a str> {
+        self.extension().and_then(|s| str::from_utf8(s).ok())
+    }
+
+    /// Replaces the filename portion of the path with the given byte vector or string.
+    /// If the replacement name is [], this is equivalent to popping the path.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let mut p = Path::new("abc/def.txt");
+    /// p.set_filename("foo.dat");
+    /// assert!(p == Path::new("abc/foo.dat"));
+    /// # }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the filename contains a NUL.
+    #[inline]
+    fn set_filename<T: BytesContainer>(&mut self, filename: T) {
+        assert!(!contains_nul(&filename));
+        unsafe { self.set_filename_unchecked(filename) }
+    }
+
+    /// Replaces the extension with the given byte vector or string.
+    /// If there is no extension in `self`, this adds one.
+    /// If the argument is [] or "", this removes the extension.
+    /// If `self` has no filename, this is a no-op.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let mut p = Path::new("abc/def.txt");
+    /// p.set_extension("csv");
+    /// assert_eq!(p, Path::new("abc/def.csv"));
+    /// # }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the extension contains a NUL.
+    fn set_extension<T: BytesContainer>(&mut self, extension: T) {
+        assert!(!contains_nul(&extension));
+
+        let val = self.filename().and_then(|name| {
+            let dot = b'.';
+            let extlen = extension.container_as_bytes().len();
+            match (name.rposition_elem(&dot), extlen) {
+                (None, 0) | (Some(0), 0) => None,
+                (Some(idx), 0) => Some(name[..idx].to_vec()),
+                (idx, extlen) => {
+                    let idx = match idx {
+                        None | Some(0) => name.len(),
+                        Some(val) => val
+                    };
+
+                    let mut v;
+                    v = Vec::with_capacity(idx + extlen + 1);
+                    v.push_all(&name[..idx]);
+                    v.push(dot);
+                    v.push_all(extension.container_as_bytes());
+                    Some(v)
+                }
+            }
+        });
+
+        match val {
+            None => (),
+            Some(v) => unsafe { self.set_filename_unchecked(v) }
+        }
+    }
+
+    /// Returns a new Path constructed by replacing the filename with the given
+    /// byte vector or string.
+    /// See `set_filename` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let mut p = Path::new("abc/def.txt");
+    /// assert_eq!(p.with_filename("foo.dat"), Path::new("abc/foo.dat"));
+    /// # }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the filename contains a NUL.
+    #[inline]
+    fn with_filename<T: BytesContainer>(&self, filename: T) -> Self {
+        let mut p = self.clone();
+        p.set_filename(filename);
+        p
+    }
+
+    /// Returns a new Path constructed by setting the extension to the given
+    /// byte vector or string.
+    /// See `set_extension` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let mut p = Path::new("abc/def.txt");
+    /// assert_eq!(p.with_extension("csv"), Path::new("abc/def.csv"));
+    /// # }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the extension contains a NUL.
+    #[inline]
+    fn with_extension<T: BytesContainer>(&self, extension: T) -> Self {
+        let mut p = self.clone();
+        p.set_extension(extension);
+        p
+    }
+
+    /// Returns the directory component of `self`, as a Path.
+    /// If `self` represents the root of the filesystem hierarchy, returns `self`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def/ghi");
+    /// assert_eq!(p.dir_path(), Path::new("abc/def"));
+    /// # }
+    /// ```
+    fn dir_path(&self) -> Self {
+        // self.dirname() returns a NUL-free vector
+        unsafe { GenericPathUnsafe::new_unchecked(self.dirname()) }
+    }
+
+    /// Returns a Path that represents the filesystem root that `self` is rooted in.
+    ///
+    /// If `self` is not absolute, or vol/cwd-relative in the case of Windows, this returns None.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// assert_eq!(Path::new("abc/def").root_path(), None);
+    /// assert_eq!(Path::new("/abc/def").root_path(), Some(Path::new("/")));
+    /// # }
+    /// ```
+    fn root_path(&self) -> Option<Self>;
+
+    /// Pushes a path (as a byte vector or string) onto `self`.
+    /// If the argument represents an absolute path, it replaces `self`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let mut p = Path::new("foo/bar");
+    /// p.push("baz.txt");
+    /// assert_eq!(p, Path::new("foo/bar/baz.txt"));
+    /// # }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the path contains a NUL.
+    #[inline]
+    fn push<T: BytesContainer>(&mut self, path: T) {
+        assert!(!contains_nul(&path));
+        unsafe { self.push_unchecked(path) }
+    }
+
+    /// Pushes multiple paths (as byte vectors or strings) onto `self`.
+    /// See `push` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let mut p = Path::new("foo");
+    /// p.push_many(&["bar", "baz.txt"]);
+    /// assert_eq!(p, Path::new("foo/bar/baz.txt"));
+    /// # }
+    /// ```
+    #[inline]
+    fn push_many<T: BytesContainer>(&mut self, paths: &[T]) {
+        let t: Option<&T> = None;
+        if BytesContainer::is_str(t) {
+            for p in paths {
+                self.push(p.container_as_str().unwrap())
+            }
+        } else {
+            for p in paths {
+                self.push(p.container_as_bytes())
+            }
+        }
+    }
+
+    /// Removes the last path component from the receiver.
+    /// Returns `true` if the receiver was modified, or `false` if it already
+    /// represented the root of the file hierarchy.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let mut p = Path::new("foo/bar/baz.txt");
+    /// p.pop();
+    /// assert_eq!(p, Path::new("foo/bar"));
+    /// # }
+    /// ```
+    fn pop(&mut self) -> bool;
+
+    /// Returns a new Path constructed by joining `self` with the given path
+    /// (as a byte vector or string).
+    /// If the given path is absolute, the new Path will represent just that.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("/foo");
+    /// assert_eq!(p.join("bar.txt"), Path::new("/foo/bar.txt"));
+    /// # }
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the path contains a NUL.
+    #[inline]
+    fn join<T: BytesContainer>(&self, path: T) -> Self {
+        let mut p = self.clone();
+        p.push(path);
+        p
+    }
+
+    /// Returns a new Path constructed by joining `self` with the given paths
+    /// (as byte vectors or strings).
+    /// See `join` for details.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("foo");
+    /// let fbbq = Path::new("foo/bar/baz/quux.txt");
+    /// assert_eq!(p.join_many(&["bar", "baz", "quux.txt"]), fbbq);
+    /// # }
+    /// ```
+    #[inline]
+    fn join_many<T: BytesContainer>(&self, paths: &[T]) -> Self {
+        let mut p = self.clone();
+        p.push_many(paths);
+        p
+    }
+
+    /// Returns whether `self` represents an absolute path.
+    /// An absolute path is defined as one that, when joined to another path, will
+    /// yield back the same absolute path.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("/abc/def");
+    /// assert!(p.is_absolute());
+    /// # }
+    /// ```
+    fn is_absolute(&self) -> bool;
+
+    /// Returns whether `self` represents a relative path.
+    /// Typically this is the inverse of `is_absolute`.
+    /// But for Windows paths, it also means the path is not volume-relative or
+    /// relative to the current working directory.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("abc/def");
+    /// assert!(p.is_relative());
+    /// # }
+    /// ```
+    fn is_relative(&self) -> bool {
+        !self.is_absolute()
+    }
+
+    /// Returns whether `self` is equal to, or is an ancestor of, the given path.
+    /// If both paths are relative, they are compared as though they are relative
+    /// to the same parent path.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("foo/bar/baz/quux.txt");
+    /// let fb = Path::new("foo/bar");
+    /// let bq = Path::new("baz/quux.txt");
+    /// assert!(fb.is_ancestor_of(&p));
+    /// # }
+    /// ```
+    fn is_ancestor_of(&self, other: &Self) -> bool;
+
+    /// Returns the Path that, were it joined to `base`, would yield `self`.
+    /// If no such path exists, None is returned.
+    /// If `self` is absolute and `base` is relative, or on Windows if both
+    /// paths refer to separate drives, an absolute path is returned.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("foo/bar/baz/quux.txt");
+    /// let fb = Path::new("foo/bar");
+    /// let bq = Path::new("baz/quux.txt");
+    /// assert_eq!(p.path_relative_from(&fb), Some(bq));
+    /// # }
+    /// ```
+    fn path_relative_from(&self, base: &Self) -> Option<Self>;
+
+    /// Returns whether the relative path `child` is a suffix of `self`.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # foo();
+    /// # #[cfg(windows)] fn foo() {}
+    /// # #[cfg(unix)] fn foo() {
+    /// let p = Path::new("foo/bar/baz/quux.txt");
+    /// let bq = Path::new("baz/quux.txt");
+    /// assert!(p.ends_with_path(&bq));
+    /// # }
+    /// ```
+    fn ends_with_path(&self, child: &Self) -> bool;
+}
+
+/// A trait that represents something bytes-like (e.g. a &[u8] or a &str)
+pub trait BytesContainer {
+    /// Returns a &[u8] representing the receiver
+    fn container_as_bytes<'a>(&'a self) -> &'a [u8];
+    /// Returns the receiver interpreted as a utf-8 string, if possible
+    #[inline]
+    fn container_as_str<'a>(&'a self) -> Option<&'a str> {
+        str::from_utf8(self.container_as_bytes()).ok()
+    }
+    /// Returns whether .container_as_str() is guaranteed to not fail
+    // FIXME (#8888): Remove unused arg once ::<for T> works
+    #[inline]
+    fn is_str(_: Option<&Self>) -> bool { false }
+}
+
+/// A trait that represents the unsafe operations on GenericPaths
+pub trait GenericPathUnsafe {
+    /// Creates a new Path without checking for null bytes.
+    /// The resulting Path will always be normalized.
+    unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Self;
+
+    /// Replaces the filename portion of the path without checking for null
+    /// bytes.
+    /// See `set_filename` for details.
+    unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T);
+
+    /// Pushes a path onto `self` without checking for null bytes.
+    /// See `push` for details.
+    unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T);
+}
+
+/// Helper struct for printing paths with format!()
+pub struct Display<'a, P:'a> {
+    path: &'a P,
+    filename: bool
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, P: GenericPath> fmt::Debug for Display<'a, P> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.as_cow(), f)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, P: GenericPath> fmt::Display for Display<'a, P> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.as_cow().fmt(f)
+    }
+}
+
+impl<'a, P: GenericPath> Display<'a, P> {
+    /// Returns the path as a possibly-owned string.
+    ///
+    /// If the path is not UTF-8, invalid sequences will be replaced with the
+    /// Unicode replacement char. This involves allocation.
+    #[inline]
+    pub fn as_cow(&self) -> CowString<'a> {
+        String::from_utf8_lossy(if self.filename {
+            match self.path.filename() {
+                None => {
+                    let result: &[u8] = &[];
+                    result
+                }
+                Some(v) => v
+            }
+        } else {
+            self.path.as_vec()
+        })
+    }
+}
+
+impl BytesContainer for str {
+    #[inline]
+    fn container_as_bytes(&self) -> &[u8] {
+        self.as_bytes()
+    }
+    #[inline]
+    fn container_as_str(&self) -> Option<&str> {
+        Some(self)
+    }
+    #[inline]
+    fn is_str(_: Option<&str>) -> bool { true }
+}
+
+impl BytesContainer for String {
+    #[inline]
+    fn container_as_bytes(&self) -> &[u8] {
+        self.as_bytes()
+    }
+    #[inline]
+    fn container_as_str(&self) -> Option<&str> {
+        Some(&self[])
+    }
+    #[inline]
+    fn is_str(_: Option<&String>) -> bool { true }
+}
+
+impl BytesContainer for [u8] {
+    #[inline]
+    fn container_as_bytes(&self) -> &[u8] {
+        self
+    }
+}
+
+impl BytesContainer for Vec<u8> {
+    #[inline]
+    fn container_as_bytes(&self) -> &[u8] {
+        &self[]
+    }
+}
+
+impl BytesContainer for CString {
+    #[inline]
+    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
+        self.as_bytes()
+    }
+}
+
+impl<'a, T: ?Sized + BytesContainer> BytesContainer for &'a T {
+    #[inline]
+    fn container_as_bytes(&self) -> &[u8] {
+        (**self).container_as_bytes()
+    }
+    #[inline]
+    fn container_as_str(&self) -> Option<&str> {
+        (**self).container_as_str()
+    }
+    #[inline]
+    fn is_str(_: Option<& &'a T>) -> bool { BytesContainer::is_str(None::<&T>) }
+}
+
+#[inline(always)]
+fn contains_nul<T: BytesContainer>(v: &T) -> bool {
+    v.container_as_bytes().iter().any(|&x| x == 0)
+}
diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs
new file mode 100644 (file)
index 0000000..8bcdd89
--- /dev/null
@@ -0,0 +1,1348 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! POSIX file path handling
+
+use clone::Clone;
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
+use fmt;
+use hash;
+use old_io::Writer;
+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;
+
+use super::{BytesContainer, GenericPath, GenericPathUnsafe};
+
+/// Iterator that yields successive components of a Path as &[u8]
+pub type Components<'a> = Split<'a, u8, fn(&u8) -> bool>;
+
+/// Iterator that yields successive components of a Path as Option<&str>
+pub type StrComponents<'a> =
+    Map<Components<'a>, fn(&[u8]) -> Option<&str>>;
+
+/// Represents a POSIX file path
+#[derive(Clone)]
+pub struct Path {
+    repr: Vec<u8>, // assumed to never be empty or contain NULs
+    sepidx: Option<uint> // index of the final separator in repr
+}
+
+/// The standard path separator character
+pub const SEP: char = '/';
+
+/// The standard path separator byte
+pub const SEP_BYTE: u8 = SEP as u8;
+
+/// Returns whether the given byte is a path separator
+#[inline]
+pub fn is_sep_byte(u: &u8) -> bool {
+    *u as char == SEP
+}
+
+/// Returns whether the given char is a path separator
+#[inline]
+pub fn is_sep(c: char) -> bool {
+    c == SEP
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.display(), f)
+    }
+}
+
+impl PartialEq for Path {
+    #[inline]
+    fn eq(&self, other: &Path) -> bool {
+        self.repr == other.repr
+    }
+}
+
+impl Eq for Path {}
+
+impl PartialOrd for Path {
+    fn partial_cmp(&self, other: &Path) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Path {
+    fn cmp(&self, other: &Path) -> Ordering {
+        self.repr.cmp(&other.repr)
+    }
+}
+
+impl FromStr for Path {
+    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(Debug, Clone, PartialEq, Copy)]
+pub struct ParsePathError;
+
+impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        self.repr.hash(state)
+    }
+}
+
+impl BytesContainer for Path {
+    #[inline]
+    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
+        self.as_vec()
+    }
+}
+
+impl GenericPathUnsafe for Path {
+    unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Path {
+        let path = Path::normalize(path.container_as_bytes());
+        assert!(!path.is_empty());
+        let idx = path.rposition_elem(&SEP_BYTE);
+        Path{ repr: path, sepidx: idx }
+    }
+
+    unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
+        let filename = filename.container_as_bytes();
+        match self.sepidx {
+            None if b".." == self.repr => {
+                let mut v = Vec::with_capacity(3 + filename.len());
+                v.push_all(dot_dot_static);
+                v.push(SEP_BYTE);
+                v.push_all(filename);
+                // FIXME: this is slow
+                self.repr = Path::normalize(v.as_slice());
+            }
+            None => {
+                self.repr = Path::normalize(filename);
+            }
+            Some(idx) if &self.repr[idx+1..] == b".." => {
+                let mut v = Vec::with_capacity(self.repr.len() + 1 + filename.len());
+                v.push_all(self.repr.as_slice());
+                v.push(SEP_BYTE);
+                v.push_all(filename);
+                // FIXME: this is slow
+                self.repr = Path::normalize(v.as_slice());
+            }
+            Some(idx) => {
+                let mut v = Vec::with_capacity(idx + 1 + filename.len());
+                v.push_all(&self.repr[..idx+1]);
+                v.push_all(filename);
+                // FIXME: this is slow
+                self.repr = Path::normalize(v.as_slice());
+            }
+        }
+        self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
+    }
+
+    unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
+        let path = path.container_as_bytes();
+        if !path.is_empty() {
+            if path[0] == SEP_BYTE {
+                self.repr = Path::normalize(path);
+            }  else {
+                let mut v = Vec::with_capacity(self.repr.len() + path.len() + 1);
+                v.push_all(self.repr.as_slice());
+                v.push(SEP_BYTE);
+                v.push_all(path);
+                // FIXME: this is slow
+                self.repr = Path::normalize(v.as_slice());
+            }
+            self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
+        }
+    }
+}
+
+impl GenericPath for Path {
+    #[inline]
+    fn as_vec<'a>(&'a self) -> &'a [u8] {
+        self.repr.as_slice()
+    }
+
+    fn into_vec(self) -> Vec<u8> {
+        self.repr
+    }
+
+    fn dirname<'a>(&'a self) -> &'a [u8] {
+        match self.sepidx {
+            None if b".." == self.repr => self.repr.as_slice(),
+            None => dot_static,
+            Some(0) => &self.repr[..1],
+            Some(idx) if &self.repr[idx+1..] == b".." => self.repr.as_slice(),
+            Some(idx) => &self.repr[..idx]
+        }
+    }
+
+    fn filename<'a>(&'a self) -> Option<&'a [u8]> {
+        match self.sepidx {
+            None if b"." == self.repr ||
+                b".." == self.repr => None,
+            None => Some(self.repr.as_slice()),
+            Some(idx) if &self.repr[idx+1..] == b".." => None,
+            Some(0) if self.repr[1..].is_empty() => None,
+            Some(idx) => Some(&self.repr[idx+1..])
+        }
+    }
+
+    fn pop(&mut self) -> bool {
+        match self.sepidx {
+            None if b"." == self.repr => false,
+            None => {
+                self.repr = vec![b'.'];
+                self.sepidx = None;
+                true
+            }
+            Some(0) if b"/" == self.repr => false,
+            Some(idx) => {
+                if idx == 0 {
+                    self.repr.truncate(idx+1);
+                } else {
+                    self.repr.truncate(idx);
+                }
+                self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
+                true
+            }
+        }
+    }
+
+    fn root_path(&self) -> Option<Path> {
+        if self.is_absolute() {
+            Some(Path::new("/"))
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn is_absolute(&self) -> bool {
+        self.repr[0] == SEP_BYTE
+    }
+
+    fn is_ancestor_of(&self, other: &Path) -> bool {
+        if self.is_absolute() != other.is_absolute() {
+            false
+        } else {
+            let mut ita = self.components();
+            let mut itb = other.components();
+            if b"." == self.repr {
+                return match itb.next() {
+                    None => true,
+                    Some(b) => b != b".."
+                };
+            }
+            loop {
+                match (ita.next(), itb.next()) {
+                    (None, _) => break,
+                    (Some(a), Some(b)) if a == b => { continue },
+                    (Some(a), _) if a == b".." => {
+                        // if ita contains only .. components, it's an ancestor
+                        return ita.all(|x| x == b"..");
+                    }
+                    _ => return false
+                }
+            }
+            true
+        }
+    }
+
+    fn path_relative_from(&self, base: &Path) -> Option<Path> {
+        if self.is_absolute() != base.is_absolute() {
+            if self.is_absolute() {
+                Some(self.clone())
+            } else {
+                None
+            }
+        } else {
+            let mut ita = self.components();
+            let mut itb = base.components();
+            let mut comps = vec![];
+            loop {
+                match (ita.next(), itb.next()) {
+                    (None, None) => break,
+                    (Some(a), None) => {
+                        comps.push(a);
+                        comps.extend(ita.by_ref());
+                        break;
+                    }
+                    (None, _) => comps.push(dot_dot_static),
+                    (Some(a), Some(b)) if comps.is_empty() && a == b => (),
+                    (Some(a), Some(b)) if b == b"." => comps.push(a),
+                    (Some(_), Some(b)) if b == b".." => return None,
+                    (Some(a), Some(_)) => {
+                        comps.push(dot_dot_static);
+                        for _ in itb {
+                            comps.push(dot_dot_static);
+                        }
+                        comps.push(a);
+                        comps.extend(ita.by_ref());
+                        break;
+                    }
+                }
+            }
+            Some(Path::new(comps.connect(&SEP_BYTE)))
+        }
+    }
+
+    fn ends_with_path(&self, child: &Path) -> bool {
+        if !child.is_relative() { return false; }
+        let mut selfit = self.components().rev();
+        let mut childit = child.components().rev();
+        loop {
+            match (selfit.next(), childit.next()) {
+                (Some(a), Some(b)) => if a != b { return false; },
+                (Some(_), None) => break,
+                (None, Some(_)) => return false,
+                (None, None) => break
+            }
+        }
+        true
+    }
+}
+
+impl Path {
+    /// Returns a new Path from a byte vector or string
+    ///
+    /// # Panics
+    ///
+    /// Panics the task if the vector contains a NUL.
+    #[inline]
+    pub fn new<T: BytesContainer>(path: T) -> Path {
+        GenericPath::new(path)
+    }
+
+    /// Returns a new Path from a byte vector or string, if possible
+    #[inline]
+    pub fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
+        GenericPath::new_opt(path)
+    }
+
+    /// Returns a normalized byte vector representation of a path, by removing all empty
+    /// components, and unnecessary . and .. components.
+    fn normalize<V: ?Sized + AsSlice<u8>>(v: &V) -> Vec<u8> {
+        // borrowck is being very picky
+        let val = {
+            let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE;
+            let v_ = if is_abs { &v.as_slice()[1..] } else { v.as_slice() };
+            let comps = normalize_helper(v_, is_abs);
+            match comps {
+                None => None,
+                Some(comps) => {
+                    if is_abs && comps.is_empty() {
+                        Some(vec![SEP_BYTE])
+                    } else {
+                        let n = if is_abs { comps.len() } else { comps.len() - 1} +
+                                comps.iter().map(|v| v.len()).sum();
+                        let mut v = Vec::with_capacity(n);
+                        let mut it = comps.into_iter();
+                        if !is_abs {
+                            match it.next() {
+                                None => (),
+                                Some(comp) => v.push_all(comp)
+                            }
+                        }
+                        for comp in it {
+                            v.push(SEP_BYTE);
+                            v.push_all(comp);
+                        }
+                        Some(v)
+                    }
+                }
+            }
+        };
+        match val {
+            None => v.as_slice().to_vec(),
+            Some(val) => val
+        }
+    }
+
+    /// Returns an iterator that yields each component of the path in turn.
+    /// Does not distinguish between absolute and relative paths, e.g.
+    /// /a/b/c and a/b/c yield the same set of components.
+    /// A path of "/" yields no components. A path of "." yields one component.
+    pub fn components<'a>(&'a self) -> Components<'a> {
+        let v = if self.repr[0] == SEP_BYTE {
+            &self.repr[1..]
+        } else { self.repr.as_slice() };
+        let is_sep_byte: fn(&u8) -> bool = is_sep_byte; // coerce to fn ptr
+        let mut ret = v.split(is_sep_byte);
+        if v.is_empty() {
+            // consume the empty "" component
+            ret.next();
+        }
+        ret
+    }
+
+    /// Returns an iterator that yields each component of the path as Option<&str>.
+    /// See components() for details.
+    pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
+        fn from_utf8(s: &[u8]) -> Option<&str> {
+            str::from_utf8(s).ok()
+        }
+        let f: fn(&[u8]) -> Option<&str> = from_utf8; // coerce to fn ptr
+        self.components().map(f)
+    }
+}
+
+// None result means the byte vector didn't need normalizing
+fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<Vec<&'a [u8]>> {
+    if is_abs && v.is_empty() {
+        return None;
+    }
+    let mut comps: Vec<&'a [u8]> = vec![];
+    let mut n_up = 0u;
+    let mut changed = false;
+    for comp in v.split(is_sep_byte) {
+        if comp.is_empty() { changed = true }
+        else if comp == b"." { changed = true }
+        else if comp == b".." {
+            if is_abs && comps.is_empty() { changed = true }
+            else if comps.len() == n_up { comps.push(dot_dot_static); n_up += 1 }
+            else { comps.pop().unwrap(); changed = true }
+        } else { comps.push(comp) }
+    }
+    if changed {
+        if comps.is_empty() && !is_abs {
+            if v == b"." {
+                return None;
+            }
+            comps.push(dot_static);
+        }
+        Some(comps)
+    } else {
+        None
+    }
+}
+
+#[allow(non_upper_case_globals)]
+static dot_static: &'static [u8] = b".";
+#[allow(non_upper_case_globals)]
+static dot_dot_static: &'static [u8] = b"..";
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    use clone::Clone;
+    use iter::IteratorExt;
+    use option::Option::{self, Some, None};
+    use old_path::GenericPath;
+    use slice::{AsSlice, SliceExt};
+    use str::{self, Str, StrExt};
+    use string::ToString;
+    use vec::Vec;
+
+    macro_rules! t {
+        (s: $path:expr, $exp:expr) => (
+            {
+                let path = $path;
+                assert_eq!(path.as_str(), Some($exp));
+            }
+        );
+        (v: $path:expr, $exp:expr) => (
+            {
+                let path = $path;
+                assert_eq!(path.as_vec(), $exp);
+            }
+        )
+    }
+
+    #[test]
+    fn test_paths() {
+        let empty: &[u8] = &[];
+        t!(v: Path::new(empty), b".");
+        t!(v: Path::new(b"/"), b"/");
+        t!(v: Path::new(b"a/b/c"), b"a/b/c");
+        t!(v: Path::new(b"a/b/c\xFF"), b"a/b/c\xFF");
+        t!(v: Path::new(b"\xFF/../foo\x80"), b"foo\x80");
+        let p = Path::new(b"a/b/c\xFF");
+        assert!(p.as_str().is_none());
+
+        t!(s: Path::new(""), ".");
+        t!(s: Path::new("/"), "/");
+        t!(s: Path::new("hi"), "hi");
+        t!(s: Path::new("hi/"), "hi");
+        t!(s: Path::new("/lib"), "/lib");
+        t!(s: Path::new("/lib/"), "/lib");
+        t!(s: Path::new("hi/there"), "hi/there");
+        t!(s: Path::new("hi/there.txt"), "hi/there.txt");
+
+        t!(s: Path::new("hi/there/"), "hi/there");
+        t!(s: Path::new("hi/../there"), "there");
+        t!(s: Path::new("../hi/there"), "../hi/there");
+        t!(s: Path::new("/../hi/there"), "/hi/there");
+        t!(s: Path::new("foo/.."), ".");
+        t!(s: Path::new("/foo/.."), "/");
+        t!(s: Path::new("/foo/../.."), "/");
+        t!(s: Path::new("/foo/../../bar"), "/bar");
+        t!(s: Path::new("/./hi/./there/."), "/hi/there");
+        t!(s: Path::new("/./hi/./there/./.."), "/hi");
+        t!(s: Path::new("foo/../.."), "..");
+        t!(s: Path::new("foo/../../.."), "../..");
+        t!(s: Path::new("foo/../../bar"), "../bar");
+
+        assert_eq!(Path::new(b"foo/bar").into_vec(), b"foo/bar");
+        assert_eq!(Path::new(b"/foo/../../bar").into_vec(),
+                   b"/bar");
+
+        let p = Path::new(b"foo/bar\x80");
+        assert!(p.as_str().is_none());
+    }
+
+    #[test]
+    fn test_opt_paths() {
+        assert!(Path::new_opt(b"foo/bar\0").is_none());
+        t!(v: Path::new_opt(b"foo/bar").unwrap(), b"foo/bar");
+        assert!(Path::new_opt("foo/bar\0").is_none());
+        t!(s: Path::new_opt("foo/bar").unwrap(), "foo/bar");
+    }
+
+    #[test]
+    fn test_null_byte() {
+        use thread::Thread;
+        let result = Thread::scoped(move|| {
+            Path::new(b"foo/bar\0")
+        }).join();
+        assert!(result.is_err());
+
+        let result = Thread::scoped(move|| {
+            Path::new("test").set_filename(b"f\0o")
+        }).join();
+        assert!(result.is_err());
+
+        let result = Thread::scoped(move|| {
+            Path::new("test").push(b"f\0o");
+        }).join();
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_display_str() {
+        macro_rules! t {
+            ($path:expr, $disp:ident, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    assert_eq!(path.$disp().to_string(), $exp);
+                }
+            )
+        }
+        t!("foo", display, "foo");
+        t!(b"foo\x80", display, "foo\u{FFFD}");
+        t!(b"foo\xFFbar", display, "foo\u{FFFD}bar");
+        t!(b"foo\xFF/bar", filename_display, "bar");
+        t!(b"foo/\xFFbar", filename_display, "\u{FFFD}bar");
+        t!(b"/", filename_display, "");
+
+        macro_rules! t {
+            ($path:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let mo = path.display().as_cow();
+                    assert_eq!(mo.as_slice(), $exp);
+                }
+            );
+            ($path:expr, $exp:expr, filename) => (
+                {
+                    let path = Path::new($path);
+                    let mo = path.filename_display().as_cow();
+                    assert_eq!(mo.as_slice(), $exp);
+                }
+            )
+        }
+
+        t!("foo", "foo");
+        t!(b"foo\x80", "foo\u{FFFD}");
+        t!(b"foo\xFFbar", "foo\u{FFFD}bar");
+        t!(b"foo\xFF/bar", "bar", filename);
+        t!(b"foo/\xFFbar", "\u{FFFD}bar", filename);
+        t!(b"/", "", filename);
+    }
+
+    #[test]
+    fn test_display() {
+        macro_rules! t {
+            ($path:expr, $exp:expr, $expf:expr) => (
+                {
+                    let path = Path::new($path);
+                    let f = format!("{}", path.display());
+                    assert_eq!(f, $exp);
+                    let f = format!("{}", path.filename_display());
+                    assert_eq!(f, $expf);
+                }
+            )
+        }
+
+        t!(b"foo", "foo", "foo");
+        t!(b"foo/bar", "foo/bar", "bar");
+        t!(b"/", "/", "");
+        t!(b"foo\xFF", "foo\u{FFFD}", "foo\u{FFFD}");
+        t!(b"foo\xFF/bar", "foo\u{FFFD}/bar", "bar");
+        t!(b"foo/\xFFbar", "foo/\u{FFFD}bar", "\u{FFFD}bar");
+        t!(b"\xFFfoo/bar\xFF", "\u{FFFD}foo/bar\u{FFFD}", "bar\u{FFFD}");
+    }
+
+    #[test]
+    fn test_components() {
+        macro_rules! t {
+            (s: $path:expr, $op:ident, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    assert_eq!(path.$op(), ($exp).as_bytes());
+                }
+            );
+            (s: $path:expr, $op:ident, $exp:expr, opt) => (
+                {
+                    let path = Path::new($path);
+                    let left = path.$op().map(|x| str::from_utf8(x).unwrap());
+                    assert_eq!(left, $exp);
+                }
+            );
+            (v: $path:expr, $op:ident, $exp:expr) => (
+                {
+                    let arg = $path;
+                    let path = Path::new(arg);
+                    assert_eq!(path.$op(), $exp);
+                }
+            );
+        }
+
+        t!(v: b"a/b/c", filename, Some(b"c"));
+        t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF"));
+        t!(v: b"a/b\xFF/c", filename, Some(b"c"));
+        t!(s: "a/b/c", filename, Some("c"), opt);
+        t!(s: "/a/b/c", filename, Some("c"), opt);
+        t!(s: "a", filename, Some("a"), opt);
+        t!(s: "/a", filename, Some("a"), opt);
+        t!(s: ".", filename, None, opt);
+        t!(s: "/", filename, None, opt);
+        t!(s: "..", filename, None, opt);
+        t!(s: "../..", filename, None, opt);
+
+        t!(v: b"a/b/c", dirname, b"a/b");
+        t!(v: b"a/b/c\xFF", dirname, b"a/b");
+        t!(v: b"a/b\xFF/c", dirname, b"a/b\xFF");
+        t!(s: "a/b/c", dirname, "a/b");
+        t!(s: "/a/b/c", dirname, "/a/b");
+        t!(s: "a", dirname, ".");
+        t!(s: "/a", dirname, "/");
+        t!(s: ".", dirname, ".");
+        t!(s: "/", dirname, "/");
+        t!(s: "..", dirname, "..");
+        t!(s: "../..", dirname, "../..");
+
+        t!(v: b"hi/there.txt", filestem, Some(b"there"));
+        t!(v: b"hi/there\x80.txt", filestem, Some(b"there\x80"));
+        t!(v: b"hi/there.t\x80xt", filestem, Some(b"there"));
+        t!(s: "hi/there.txt", filestem, Some("there"), opt);
+        t!(s: "hi/there", filestem, Some("there"), opt);
+        t!(s: "there.txt", filestem, Some("there"), opt);
+        t!(s: "there", filestem, Some("there"), opt);
+        t!(s: ".", filestem, None, opt);
+        t!(s: "/", filestem, None, opt);
+        t!(s: "foo/.bar", filestem, Some(".bar"), opt);
+        t!(s: ".bar", filestem, Some(".bar"), opt);
+        t!(s: "..bar", filestem, Some("."), opt);
+        t!(s: "hi/there..txt", filestem, Some("there."), opt);
+        t!(s: "..", filestem, None, opt);
+        t!(s: "../..", filestem, None, opt);
+
+        t!(v: b"hi/there.txt", extension, Some(b"txt"));
+        t!(v: b"hi/there\x80.txt", extension, Some(b"txt"));
+        t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt"));
+        t!(v: b"hi/there", extension, None);
+        t!(v: b"hi/there\x80", extension, None);
+        t!(s: "hi/there.txt", extension, Some("txt"), opt);
+        t!(s: "hi/there", extension, None, opt);
+        t!(s: "there.txt", extension, Some("txt"), opt);
+        t!(s: "there", extension, None, opt);
+        t!(s: ".", extension, None, opt);
+        t!(s: "/", extension, None, opt);
+        t!(s: "foo/.bar", extension, None, opt);
+        t!(s: ".bar", extension, None, opt);
+        t!(s: "..bar", extension, Some("bar"), opt);
+        t!(s: "hi/there..txt", extension, Some("txt"), opt);
+        t!(s: "..", extension, None, opt);
+        t!(s: "../..", extension, None, opt);
+    }
+
+    #[test]
+    fn test_push() {
+        macro_rules! t {
+            (s: $path:expr, $join:expr) => (
+                {
+                    let path = $path;
+                    let join = $join;
+                    let mut p1 = Path::new(path);
+                    let p2 = p1.clone();
+                    p1.push(join);
+                    assert_eq!(p1, p2.join(join));
+                }
+            )
+        }
+
+        t!(s: "a/b/c", "..");
+        t!(s: "/a/b/c", "d");
+        t!(s: "a/b", "c/d");
+        t!(s: "a/b", "/c/d");
+    }
+
+    #[test]
+    fn test_push_path() {
+        macro_rules! t {
+            (s: $path:expr, $push:expr, $exp:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    let push = Path::new($push);
+                    p.push(&push);
+                    assert_eq!(p.as_str(), Some($exp));
+                }
+            )
+        }
+
+        t!(s: "a/b/c", "d", "a/b/c/d");
+        t!(s: "/a/b/c", "d", "/a/b/c/d");
+        t!(s: "a/b", "c/d", "a/b/c/d");
+        t!(s: "a/b", "/c/d", "/c/d");
+        t!(s: "a/b", ".", "a/b");
+        t!(s: "a/b", "../c", "a/c");
+    }
+
+    #[test]
+    fn test_push_many() {
+        macro_rules! t {
+            (s: $path:expr, $push:expr, $exp:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    p.push_many(&$push);
+                    assert_eq!(p.as_str(), Some($exp));
+                }
+            );
+            (v: $path:expr, $push:expr, $exp:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    p.push_many(&$push);
+                    assert_eq!(p.as_vec(), $exp);
+                }
+            )
+        }
+
+        t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
+        t!(s: "a/b/c", ["d", "/e"], "/e");
+        t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
+        t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e");
+        t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e");
+        t!(v: b"a/b/c", [b"d", b"/e", b"f"], b"/e/f");
+        t!(v: b"a/b/c", [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e");
+    }
+
+    #[test]
+    fn test_pop() {
+        macro_rules! t {
+            (s: $path:expr, $left:expr, $right:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    let result = p.pop();
+                    assert_eq!(p.as_str(), Some($left));
+                    assert_eq!(result, $right);
+                }
+            );
+            (b: $path:expr, $left:expr, $right:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    let result = p.pop();
+                    assert_eq!(p.as_vec(), $left);
+                    assert_eq!(result, $right);
+                }
+            )
+        }
+
+        t!(b: b"a/b/c", b"a/b", true);
+        t!(b: b"a", b".", true);
+        t!(b: b".", b".", false);
+        t!(b: b"/a", b"/", true);
+        t!(b: b"/", b"/", false);
+        t!(b: b"a/b/c\x80", b"a/b", true);
+        t!(b: b"a/b\x80/c", b"a/b\x80", true);
+        t!(b: b"\xFF", b".", true);
+        t!(b: b"/\xFF", b"/", true);
+        t!(s: "a/b/c", "a/b", true);
+        t!(s: "a", ".", true);
+        t!(s: ".", ".", false);
+        t!(s: "/a", "/", true);
+        t!(s: "/", "/", false);
+    }
+
+    #[test]
+    fn test_root_path() {
+        assert_eq!(Path::new(b"a/b/c").root_path(), None);
+        assert_eq!(Path::new(b"/a/b/c").root_path(), Some(Path::new("/")));
+    }
+
+    #[test]
+    fn test_join() {
+        t!(v: Path::new(b"a/b/c").join(b".."), b"a/b");
+        t!(v: Path::new(b"/a/b/c").join(b"d"), b"/a/b/c/d");
+        t!(v: Path::new(b"a/\x80/c").join(b"\xFF"), b"a/\x80/c/\xFF");
+        t!(s: Path::new("a/b/c").join(".."), "a/b");
+        t!(s: Path::new("/a/b/c").join("d"), "/a/b/c/d");
+        t!(s: Path::new("a/b").join("c/d"), "a/b/c/d");
+        t!(s: Path::new("a/b").join("/c/d"), "/c/d");
+        t!(s: Path::new(".").join("a/b"), "a/b");
+        t!(s: Path::new("/").join("a/b"), "/a/b");
+    }
+
+    #[test]
+    fn test_join_path() {
+        macro_rules! t {
+            (s: $path:expr, $join:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let join = Path::new($join);
+                    let res = path.join(&join);
+                    assert_eq!(res.as_str(), Some($exp));
+                }
+            )
+        }
+
+        t!(s: "a/b/c", "..", "a/b");
+        t!(s: "/a/b/c", "d", "/a/b/c/d");
+        t!(s: "a/b", "c/d", "a/b/c/d");
+        t!(s: "a/b", "/c/d", "/c/d");
+        t!(s: ".", "a/b", "a/b");
+        t!(s: "/", "a/b", "/a/b");
+    }
+
+    #[test]
+    fn test_join_many() {
+        macro_rules! t {
+            (s: $path:expr, $join:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let res = path.join_many(&$join);
+                    assert_eq!(res.as_str(), Some($exp));
+                }
+            );
+            (v: $path:expr, $join:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let res = path.join_many(&$join);
+                    assert_eq!(res.as_vec(), $exp);
+                }
+            )
+        }
+
+        t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
+        t!(s: "a/b/c", ["..", "d"], "a/b/d");
+        t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
+        t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e");
+        t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e");
+        t!(v: b"a/b/c", [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e");
+    }
+
+    #[test]
+    fn test_with_helpers() {
+        let empty: &[u8] = &[];
+
+        t!(v: Path::new(b"a/b/c").with_filename(b"d"), b"a/b/d");
+        t!(v: Path::new(b"a/b/c\xFF").with_filename(b"\x80"), b"a/b/\x80");
+        t!(v: Path::new(b"/\xFF/foo").with_filename(b"\xCD"),
+              b"/\xFF/\xCD");
+        t!(s: Path::new("a/b/c").with_filename("d"), "a/b/d");
+        t!(s: Path::new(".").with_filename("foo"), "foo");
+        t!(s: Path::new("/a/b/c").with_filename("d"), "/a/b/d");
+        t!(s: Path::new("/").with_filename("foo"), "/foo");
+        t!(s: Path::new("/a").with_filename("foo"), "/foo");
+        t!(s: Path::new("foo").with_filename("bar"), "bar");
+        t!(s: Path::new("/").with_filename("foo/"), "/foo");
+        t!(s: Path::new("/a").with_filename("foo/"), "/foo");
+        t!(s: Path::new("a/b/c").with_filename(""), "a/b");
+        t!(s: Path::new("a/b/c").with_filename("."), "a/b");
+        t!(s: Path::new("a/b/c").with_filename(".."), "a");
+        t!(s: Path::new("/a").with_filename(""), "/");
+        t!(s: Path::new("foo").with_filename(""), ".");
+        t!(s: Path::new("a/b/c").with_filename("d/e"), "a/b/d/e");
+        t!(s: Path::new("a/b/c").with_filename("/d"), "a/b/d");
+        t!(s: Path::new("..").with_filename("foo"), "../foo");
+        t!(s: Path::new("../..").with_filename("foo"), "../../foo");
+        t!(s: Path::new("..").with_filename(""), "..");
+        t!(s: Path::new("../..").with_filename(""), "../..");
+
+        t!(v: Path::new(b"hi/there\x80.txt").with_extension(b"exe"),
+              b"hi/there\x80.exe");
+        t!(v: Path::new(b"hi/there.txt\x80").with_extension(b"\xFF"),
+              b"hi/there.\xFF");
+        t!(v: Path::new(b"hi/there\x80").with_extension(b"\xFF"),
+              b"hi/there\x80.\xFF");
+        t!(v: Path::new(b"hi/there.\xFF").with_extension(empty), b"hi/there");
+        t!(s: Path::new("hi/there.txt").with_extension("exe"), "hi/there.exe");
+        t!(s: Path::new("hi/there.txt").with_extension(""), "hi/there");
+        t!(s: Path::new("hi/there.txt").with_extension("."), "hi/there..");
+        t!(s: Path::new("hi/there.txt").with_extension(".."), "hi/there...");
+        t!(s: Path::new("hi/there").with_extension("txt"), "hi/there.txt");
+        t!(s: Path::new("hi/there").with_extension("."), "hi/there..");
+        t!(s: Path::new("hi/there").with_extension(".."), "hi/there...");
+        t!(s: Path::new("hi/there.").with_extension("txt"), "hi/there.txt");
+        t!(s: Path::new("hi/.foo").with_extension("txt"), "hi/.foo.txt");
+        t!(s: Path::new("hi/there.txt").with_extension(".foo"), "hi/there..foo");
+        t!(s: Path::new("/").with_extension("txt"), "/");
+        t!(s: Path::new("/").with_extension("."), "/");
+        t!(s: Path::new("/").with_extension(".."), "/");
+        t!(s: Path::new(".").with_extension("txt"), ".");
+    }
+
+    #[test]
+    fn test_setters() {
+        macro_rules! t {
+            (s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
+                {
+                    let path = $path;
+                    let arg = $arg;
+                    let mut p1 = Path::new(path);
+                    p1.$set(arg);
+                    let p2 = Path::new(path);
+                    assert_eq!(p1, p2.$with(arg));
+                }
+            );
+            (v: $path:expr, $set:ident, $with:ident, $arg:expr) => (
+                {
+                    let path = $path;
+                    let arg = $arg;
+                    let mut p1 = Path::new(path);
+                    p1.$set(arg);
+                    let p2 = Path::new(path);
+                    assert_eq!(p1, p2.$with(arg));
+                }
+            )
+        }
+
+        t!(v: b"a/b/c", set_filename, with_filename, b"d");
+        t!(v: b"/", set_filename, with_filename, b"foo");
+        t!(v: b"\x80", set_filename, with_filename, b"\xFF");
+        t!(s: "a/b/c", set_filename, with_filename, "d");
+        t!(s: "/", set_filename, with_filename, "foo");
+        t!(s: ".", set_filename, with_filename, "foo");
+        t!(s: "a/b", set_filename, with_filename, "");
+        t!(s: "a", set_filename, with_filename, "");
+
+        t!(v: b"hi/there.txt", set_extension, with_extension, b"exe");
+        t!(v: b"hi/there.t\x80xt", set_extension, with_extension, b"exe\xFF");
+        t!(s: "hi/there.txt", set_extension, with_extension, "exe");
+        t!(s: "hi/there.", set_extension, with_extension, "txt");
+        t!(s: "hi/there", set_extension, with_extension, "txt");
+        t!(s: "hi/there.txt", set_extension, with_extension, "");
+        t!(s: "hi/there", set_extension, with_extension, "");
+        t!(s: ".", set_extension, with_extension, "txt");
+    }
+
+    #[test]
+    fn test_getters() {
+        macro_rules! t {
+            (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
+                {
+                    let path = $path;
+                    assert_eq!(path.filename_str(), $filename);
+                    assert_eq!(path.dirname_str(), $dirname);
+                    assert_eq!(path.filestem_str(), $filestem);
+                    assert_eq!(path.extension_str(), $ext);
+               }
+            );
+            (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
+                {
+                    let path = $path;
+                    assert_eq!(path.filename(), $filename);
+                    assert_eq!(path.dirname(), $dirname);
+                    assert_eq!(path.filestem(), $filestem);
+                    assert_eq!(path.extension(), $ext);
+                }
+            )
+        }
+
+        t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None);
+        t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None);
+        t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi",
+              Some(b"there"), Some(b"\xFF"));
+        t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None);
+        t!(s: Path::new("."), None, Some("."), None, None);
+        t!(s: Path::new("/"), None, Some("/"), None, None);
+        t!(s: Path::new(".."), None, Some(".."), None, None);
+        t!(s: Path::new("../.."), None, Some("../.."), None, None);
+        t!(s: Path::new("hi/there.txt"), Some("there.txt"), Some("hi"),
+              Some("there"), Some("txt"));
+        t!(s: Path::new("hi/there"), Some("there"), Some("hi"), Some("there"), None);
+        t!(s: Path::new("hi/there."), Some("there."), Some("hi"),
+              Some("there"), Some(""));
+        t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None);
+        t!(s: Path::new("hi/..there"), Some("..there"), Some("hi"),
+              Some("."), Some("there"));
+        t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, None);
+        t!(s: Path::new(b"a/b/\xFF.txt"), None, Some("a/b"), None, Some("txt"));
+        t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), None);
+        t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), None);
+    }
+
+    #[test]
+    fn test_dir_path() {
+        t!(v: Path::new(b"hi/there\x80").dir_path(), b"hi");
+        t!(v: Path::new(b"hi\xFF/there").dir_path(), b"hi\xFF");
+        t!(s: Path::new("hi/there").dir_path(), "hi");
+        t!(s: Path::new("hi").dir_path(), ".");
+        t!(s: Path::new("/hi").dir_path(), "/");
+        t!(s: Path::new("/").dir_path(), "/");
+        t!(s: Path::new("..").dir_path(), "..");
+        t!(s: Path::new("../..").dir_path(), "../..");
+    }
+
+    #[test]
+    fn test_is_absolute() {
+        macro_rules! t {
+            (s: $path:expr, $abs:expr, $rel:expr) => (
+                {
+                    let path = Path::new($path);
+                    assert_eq!(path.is_absolute(), $abs);
+                    assert_eq!(path.is_relative(), $rel);
+                }
+            )
+        }
+        t!(s: "a/b/c", false, true);
+        t!(s: "/a/b/c", true, false);
+        t!(s: "a", false, true);
+        t!(s: "/a", true, false);
+        t!(s: ".", false, true);
+        t!(s: "/", true, false);
+        t!(s: "..", false, true);
+        t!(s: "../..", false, true);
+    }
+
+    #[test]
+    fn test_is_ancestor_of() {
+        macro_rules! t {
+            (s: $path:expr, $dest:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let dest = Path::new($dest);
+                    assert_eq!(path.is_ancestor_of(&dest), $exp);
+                }
+            )
+        }
+
+        t!(s: "a/b/c", "a/b/c/d", true);
+        t!(s: "a/b/c", "a/b/c", true);
+        t!(s: "a/b/c", "a/b", false);
+        t!(s: "/a/b/c", "/a/b/c", true);
+        t!(s: "/a/b", "/a/b/c", true);
+        t!(s: "/a/b/c/d", "/a/b/c", false);
+        t!(s: "/a/b", "a/b/c", false);
+        t!(s: "a/b", "/a/b/c", false);
+        t!(s: "a/b/c", "a/b/d", false);
+        t!(s: "../a/b/c", "a/b/c", false);
+        t!(s: "a/b/c", "../a/b/c", false);
+        t!(s: "a/b/c", "a/b/cd", false);
+        t!(s: "a/b/cd", "a/b/c", false);
+        t!(s: "../a/b", "../a/b/c", true);
+        t!(s: ".", "a/b", true);
+        t!(s: ".", ".", true);
+        t!(s: "/", "/", true);
+        t!(s: "/", "/a/b", true);
+        t!(s: "..", "a/b", true);
+        t!(s: "../..", "a/b", true);
+    }
+
+    #[test]
+    fn test_ends_with_path() {
+        macro_rules! t {
+            (s: $path:expr, $child:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let child = Path::new($child);
+                    assert_eq!(path.ends_with_path(&child), $exp);
+                }
+            );
+            (v: $path:expr, $child:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let child = Path::new($child);
+                    assert_eq!(path.ends_with_path(&child), $exp);
+                }
+            )
+        }
+
+        t!(s: "a/b/c", "c", true);
+        t!(s: "a/b/c", "d", false);
+        t!(s: "foo/bar/quux", "bar", false);
+        t!(s: "foo/bar/quux", "barquux", false);
+        t!(s: "a/b/c", "b/c", true);
+        t!(s: "a/b/c", "a/b/c", true);
+        t!(s: "a/b/c", "foo/a/b/c", false);
+        t!(s: "/a/b/c", "a/b/c", true);
+        t!(s: "/a/b/c", "/a/b/c", false); // child must be relative
+        t!(s: "/a/b/c", "foo/a/b/c", false);
+        t!(s: "a/b/c", "", false);
+        t!(s: "", "", true);
+        t!(s: "/a/b/c", "d/e/f", false);
+        t!(s: "a/b/c", "a/b", false);
+        t!(s: "a/b/c", "b", false);
+        t!(v: b"a/b/c", b"b/c", true);
+        t!(v: b"a/b/\xFF", b"\xFF", true);
+        t!(v: b"a/b/\xFF", b"b/\xFF", true);
+    }
+
+    #[test]
+    fn test_path_relative_from() {
+        macro_rules! t {
+            (s: $path:expr, $other:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let other = Path::new($other);
+                    let res = path.path_relative_from(&other);
+                    assert_eq!(res.as_ref().and_then(|x| x.as_str()), $exp);
+                }
+            )
+        }
+
+        t!(s: "a/b/c", "a/b", Some("c"));
+        t!(s: "a/b/c", "a/b/d", Some("../c"));
+        t!(s: "a/b/c", "a/b/c/d", Some(".."));
+        t!(s: "a/b/c", "a/b/c", Some("."));
+        t!(s: "a/b/c", "a/b/c/d/e", Some("../.."));
+        t!(s: "a/b/c", "a/d/e", Some("../../b/c"));
+        t!(s: "a/b/c", "d/e/f", Some("../../../a/b/c"));
+        t!(s: "a/b/c", "/a/b/c", None);
+        t!(s: "/a/b/c", "a/b/c", Some("/a/b/c"));
+        t!(s: "/a/b/c", "/a/b/c/d", Some(".."));
+        t!(s: "/a/b/c", "/a/b", Some("c"));
+        t!(s: "/a/b/c", "/a/b/c/d/e", Some("../.."));
+        t!(s: "/a/b/c", "/a/d/e", Some("../../b/c"));
+        t!(s: "/a/b/c", "/d/e/f", Some("../../../a/b/c"));
+        t!(s: "hi/there.txt", "hi/there", Some("../there.txt"));
+        t!(s: ".", "a", Some(".."));
+        t!(s: ".", "a/b", Some("../.."));
+        t!(s: ".", ".", Some("."));
+        t!(s: "a", ".", Some("a"));
+        t!(s: "a/b", ".", Some("a/b"));
+        t!(s: "..", ".", Some(".."));
+        t!(s: "a/b/c", "a/b/c", Some("."));
+        t!(s: "/a/b/c", "/a/b/c", Some("."));
+        t!(s: "/", "/", Some("."));
+        t!(s: "/", ".", Some("/"));
+        t!(s: "../../a", "b", Some("../../../a"));
+        t!(s: "a", "../../b", None);
+        t!(s: "../../a", "../../b", Some("../a"));
+        t!(s: "../../a", "../../a/b", Some(".."));
+        t!(s: "../../a/b", "../../a", Some("b"));
+    }
+
+    #[test]
+    fn test_components_iter() {
+        macro_rules! t {
+            (s: $path:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let comps = path.components().collect::<Vec<&[u8]>>();
+                    let exp: &[&str] = &$exp;
+                    let exps = exp.iter().map(|x| x.as_bytes()).collect::<Vec<&[u8]>>();
+                    assert_eq!(comps, exps);
+                    let comps = path.components().rev().collect::<Vec<&[u8]>>();
+                    let exps = exps.into_iter().rev().collect::<Vec<&[u8]>>();
+                    assert_eq!(comps, exps);
+                }
+            );
+            (b: $arg:expr, [$($exp:expr),*]) => (
+                {
+                    let path = Path::new($arg);
+                    let comps = path.components().collect::<Vec<&[u8]>>();
+                    let exp: &[&[u8]] = &[$($exp),*];
+                    assert_eq!(comps, exp);
+                    let comps = path.components().rev().collect::<Vec<&[u8]>>();
+                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
+                    assert_eq!(comps, exp)
+                }
+            )
+        }
+
+        t!(b: b"a/b/c", [b"a", b"b", b"c"]);
+        t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]);
+        t!(b: b"../../foo\xCDbar", [b"..", b"..", b"foo\xCDbar"]);
+        t!(s: "a/b/c", ["a", "b", "c"]);
+        t!(s: "a/b/d", ["a", "b", "d"]);
+        t!(s: "a/b/cd", ["a", "b", "cd"]);
+        t!(s: "/a/b/c", ["a", "b", "c"]);
+        t!(s: "a", ["a"]);
+        t!(s: "/a", ["a"]);
+        t!(s: "/", []);
+        t!(s: ".", ["."]);
+        t!(s: "..", [".."]);
+        t!(s: "../..", ["..", ".."]);
+        t!(s: "../../foo", ["..", "..", "foo"]);
+    }
+
+    #[test]
+    fn test_str_components() {
+        macro_rules! t {
+            (b: $arg:expr, $exp:expr) => (
+                {
+                    let path = Path::new($arg);
+                    let comps = path.str_components().collect::<Vec<Option<&str>>>();
+                    let exp: &[Option<&str>] = &$exp;
+                    assert_eq!(comps, exp);
+                    let comps = path.str_components().rev().collect::<Vec<Option<&str>>>();
+                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<Option<&str>>>();
+                    assert_eq!(comps, exp);
+                }
+            )
+        }
+
+        t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]);
+        t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]);
+        t!(b: b"../../foo\xCDbar", [Some(".."), Some(".."), None]);
+        // str_components is a wrapper around components, so no need to do
+        // the full set of tests
+    }
+}
+
+#[cfg(test)]
+mod bench {
+    extern crate test;
+    use self::test::Bencher;
+    use super::*;
+    use prelude::v1::{Clone, GenericPath};
+
+    #[bench]
+    fn join_home_dir(b: &mut Bencher) {
+        let posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.join("home");
+        });
+    }
+
+    #[bench]
+    fn join_abs_path_home_dir(b: &mut Bencher) {
+        let posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.join("/home");
+        });
+    }
+
+    #[bench]
+    fn join_many_home_dir(b: &mut Bencher) {
+        let posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.join_many(&["home"]);
+        });
+    }
+
+    #[bench]
+    fn join_many_abs_path_home_dir(b: &mut Bencher) {
+        let posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.join_many(&["/home"]);
+        });
+    }
+
+    #[bench]
+    fn push_home_dir(b: &mut Bencher) {
+        let mut posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.push("home");
+        });
+    }
+
+    #[bench]
+    fn push_abs_path_home_dir(b: &mut Bencher) {
+        let mut posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.push("/home");
+        });
+    }
+
+    #[bench]
+    fn push_many_home_dir(b: &mut Bencher) {
+        let mut posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.push_many(&["home"]);
+        });
+    }
+
+    #[bench]
+    fn push_many_abs_path_home_dir(b: &mut Bencher) {
+        let mut posix_path = Path::new("/");
+        b.iter(|| {
+            posix_path.push_many(&["/home"]);
+        });
+    }
+
+    #[bench]
+    fn ends_with_path_home_dir(b: &mut Bencher) {
+        let posix_home_path = Path::new("/home");
+        b.iter(|| {
+            posix_home_path.ends_with_path(&Path::new("home"));
+        });
+    }
+
+    #[bench]
+    fn ends_with_path_missmatch_jome_home(b: &mut Bencher) {
+        let posix_home_path = Path::new("/home");
+        b.iter(|| {
+            posix_home_path.ends_with_path(&Path::new("jome"));
+        });
+    }
+
+    #[bench]
+    fn is_ancestor_of_path_with_10_dirs(b: &mut Bencher) {
+        let path = Path::new("/home/1/2/3/4/5/6/7/8/9");
+        let mut sub = path.clone();
+        sub.pop();
+        b.iter(|| {
+            path.is_ancestor_of(&sub);
+        });
+    }
+
+    #[bench]
+    fn path_relative_from_forward(b: &mut Bencher) {
+        let path = Path::new("/a/b/c");
+        let mut other = path.clone();
+        other.pop();
+        b.iter(|| {
+            path.path_relative_from(&other);
+        });
+    }
+
+    #[bench]
+    fn path_relative_from_same_level(b: &mut Bencher) {
+        let path = Path::new("/a/b/c");
+        let mut other = path.clone();
+        other.pop();
+        other.push("d");
+        b.iter(|| {
+            path.path_relative_from(&other);
+        });
+    }
+
+    #[bench]
+    fn path_relative_from_backward(b: &mut Bencher) {
+        let path = Path::new("/a/b");
+        let mut other = path.clone();
+        other.push("c");
+        b.iter(|| {
+            path.path_relative_from(&other);
+        });
+    }
+}
diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs
new file mode 100644 (file)
index 0000000..2e25403
--- /dev/null
@@ -0,0 +1,2329 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// ignore-lexer-test FIXME #15883
+
+//! Windows file path handling
+
+use self::PathPrefix::*;
+
+use ascii::AsciiExt;
+use char::CharExt;
+use clone::Clone;
+use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
+use fmt;
+use hash;
+use old_io::Writer;
+use iter::{AdditiveIterator, Extend};
+use iter::{Iterator, IteratorExt, Map, repeat};
+use mem;
+use option::Option::{self, Some, None};
+use result::Result::{self, Ok, Err};
+use slice::{SliceExt, SliceConcatExt};
+use str::{SplitTerminator, FromStr, StrExt};
+use string::{String, ToString};
+use vec::Vec;
+
+use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
+
+/// Iterator that yields successive components of a Path as &str
+///
+/// Each component is yielded as Option<&str> for compatibility with PosixPath, but
+/// every component in WindowsPath is guaranteed to be Some.
+pub type StrComponents<'a> =
+    Map<SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>;
+
+/// Iterator that yields successive components of a Path as &[u8]
+pub type Components<'a> =
+    Map<StrComponents<'a>, fn(Option<&str>) -> &[u8]>;
+
+/// Represents a Windows path
+// Notes for Windows path impl:
+// The MAX_PATH is 260, but 253 is the practical limit due to some API bugs
+// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx for good information
+// about windows paths.
+// That same page puts a bunch of restrictions on allowed characters in a path.
+// `\foo.txt` means "relative to current drive", but will not be considered to be absolute here
+// as `∃P | P.join("\foo.txt") != "\foo.txt"`.
+// `C:` is interesting, that means "the current directory on drive C".
+// Long absolute paths need to have \\?\ prefix (or, for UNC, \\?\UNC\). I think that can be
+// ignored for now, though, and only added in a hypothetical .to_pwstr() function.
+// However, if a path is parsed that has \\?\, this needs to be preserved as it disables the
+// processing of "." and ".." components and / as a separator.
+// Experimentally, \\?\foo is not the same thing as \foo.
+// Also, \\foo is not valid either (certainly not equivalent to \foo).
+// Similarly, C:\\Users is not equivalent to C:\Users, although C:\Users\\foo is equivalent
+// to C:\Users\foo. In fact the command prompt treats C:\\foo\bar as UNC path. But it might be
+// best to just ignore that and normalize it to C:\foo\bar.
+//
+// Based on all this, I think the right approach is to do the following:
+// * Require valid utf-8 paths. Windows API may use WCHARs, but we don't, and utf-8 is convertible
+// to UTF-16 anyway (though does Windows use UTF-16 or UCS-2? Not sure).
+// * Parse the prefixes \\?\UNC\, \\?\, and \\.\ explicitly.
+// * If \\?\UNC\, treat following two path components as server\share. Don't error for missing
+//   server\share.
+// * If \\?\, parse disk from following component, if present. Don't error for missing disk.
+// * If \\.\, treat rest of path as just regular components. I don't know how . and .. are handled
+//   here, they probably aren't, but I'm not going to worry about that.
+// * Else if starts with \\, treat following two components as server\share. Don't error for missing
+//   server\share.
+// * Otherwise, attempt to parse drive from start of path.
+//
+// The only error condition imposed here is valid utf-8. All other invalid paths are simply
+// preserved by the data structure; let the Windows API error out on them.
+#[derive(Clone)]
+pub struct Path {
+    repr: String, // assumed to never be empty
+    prefix: Option<PathPrefix>,
+    sepidx: Option<uint> // index of the final separator in the non-prefix portion of repr
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.display(), f)
+    }
+}
+
+impl PartialEq for Path {
+    #[inline]
+    fn eq(&self, other: &Path) -> bool {
+        self.repr == other.repr
+    }
+}
+
+impl Eq for Path {}
+
+impl PartialOrd for Path {
+    fn partial_cmp(&self, other: &Path) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Path {
+    fn cmp(&self, other: &Path) -> Ordering {
+        self.repr.cmp(&other.repr)
+    }
+}
+
+impl FromStr for Path {
+    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(Debug, Clone, PartialEq, Copy)]
+pub struct ParsePathError;
+
+impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
+    #[cfg(not(test))]
+    #[inline]
+    fn hash(&self, state: &mut S) {
+        self.repr.hash(state)
+    }
+
+    #[cfg(test)]
+    #[inline]
+    fn hash(&self, _: &mut S) {
+        // No-op because the `hash` implementation will be wrong.
+    }
+}
+
+impl BytesContainer for Path {
+    #[inline]
+    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
+        self.as_vec()
+    }
+    #[inline]
+    fn container_as_str<'a>(&'a self) -> Option<&'a str> {
+        self.as_str()
+    }
+    #[inline]
+    fn is_str(_: Option<&Path>) -> bool { true }
+}
+
+impl GenericPathUnsafe for Path {
+    /// See `GenericPathUnsafe::from_vec_unchecked`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if not valid UTF-8.
+    #[inline]
+    unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Path {
+        let (prefix, path) = Path::normalize_(path.container_as_str().unwrap());
+        assert!(!path.is_empty());
+        let mut ret = Path{ repr: path, prefix: prefix, sepidx: None };
+        ret.update_sepidx();
+        ret
+    }
+
+    /// See `GenericPathUnsafe::set_filename_unchecked`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if not valid UTF-8.
+    unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
+        let filename = filename.container_as_str().unwrap();
+        match self.sepidx_or_prefix_len() {
+            None if ".." == self.repr => {
+                let mut s = String::with_capacity(3 + filename.len());
+                s.push_str("..");
+                s.push(SEP);
+                s.push_str(filename);
+                self.update_normalized(&s[]);
+            }
+            None => {
+                self.update_normalized(filename);
+            }
+            Some((_,idxa,end)) if &self.repr[idxa..end] == ".." => {
+                let mut s = String::with_capacity(end + 1 + filename.len());
+                s.push_str(&self.repr[..end]);
+                s.push(SEP);
+                s.push_str(filename);
+                self.update_normalized(&s[]);
+            }
+            Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => {
+                let mut s = String::with_capacity(idxb + filename.len());
+                s.push_str(&self.repr[..idxb]);
+                s.push_str(filename);
+                self.update_normalized(&s[]);
+            }
+            Some((idxb,_,_)) => {
+                let mut s = String::with_capacity(idxb + 1 + filename.len());
+                s.push_str(&self.repr[..idxb]);
+                s.push(SEP);
+                s.push_str(filename);
+                self.update_normalized(&s[]);
+            }
+        }
+    }
+
+    /// See `GenericPathUnsafe::push_unchecked`.
+    ///
+    /// Concatenating two Windows Paths is rather complicated.
+    /// For the most part, it will behave as expected, except in the case of
+    /// pushing a volume-relative path, e.g. `C:foo.txt`. Because we have no
+    /// concept of per-volume cwds like Windows does, we can't behave exactly
+    /// like Windows will. Instead, if the receiver is an absolute path on
+    /// the same volume as the new path, it will be treated as the cwd that
+    /// the new path is relative to. Otherwise, the new path will be treated
+    /// as if it were absolute and will replace the receiver outright.
+    unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
+        let path = path.container_as_str().unwrap();
+        fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool {
+            // assume prefix is Some(DiskPrefix)
+            let rest = &path[prefix_len(prefix)..];
+            !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char)
+        }
+        fn shares_volume(me: &Path, path: &str) -> bool {
+            // path is assumed to have a prefix of Some(DiskPrefix)
+            let repr = &me.repr[];
+            match me.prefix {
+                Some(DiskPrefix) => {
+                    repr.as_bytes()[0] == path.as_bytes()[0].to_ascii_uppercase()
+                }
+                Some(VerbatimDiskPrefix) => {
+                    repr.as_bytes()[4] == path.as_bytes()[0].to_ascii_uppercase()
+                }
+                _ => false
+            }
+        }
+        fn is_sep_(prefix: Option<PathPrefix>, u: u8) -> bool {
+            if prefix_is_verbatim(prefix) { is_sep_verbatim(u as char) }
+            else { is_sep(u as char) }
+        }
+
+        fn replace_path(me: &mut Path, path: &str, prefix: Option<PathPrefix>) {
+            let newpath = Path::normalize__(path, prefix);
+            me.repr = match newpath {
+                Some(p) => p,
+                None => String::from_str(path)
+            };
+            me.prefix = prefix;
+            me.update_sepidx();
+        }
+        fn append_path(me: &mut Path, path: &str) {
+            // appends a path that has no prefix
+            // if me is verbatim, we need to pre-normalize the new path
+            let path_ = if is_verbatim(me) { Path::normalize__(path, None) }
+                        else { None };
+            let pathlen = path_.as_ref().map_or(path.len(), |p| p.len());
+            let mut s = String::with_capacity(me.repr.len() + 1 + pathlen);
+            s.push_str(&me.repr[]);
+            let plen = me.prefix_len();
+            // if me is "C:" we don't want to add a path separator
+            match me.prefix {
+                Some(DiskPrefix) if me.repr.len() == plen => (),
+                _ if !(me.repr.len() > plen && me.repr.as_bytes()[me.repr.len()-1] == SEP_BYTE) => {
+                    s.push(SEP);
+                }
+                _ => ()
+            }
+            match path_ {
+                None => s.push_str(path),
+                Some(p) => s.push_str(&p[]),
+            };
+            me.update_normalized(&s[])
+        }
+
+        if !path.is_empty() {
+            let prefix = parse_prefix(path);
+            match prefix {
+                Some(DiskPrefix) if !is_vol_abs(path, prefix) && shares_volume(self, path) => {
+                    // cwd-relative path, self is on the same volume
+                    append_path(self, &path[prefix_len(prefix)..]);
+                }
+                Some(_) => {
+                    // absolute path, or cwd-relative and self is not same volume
+                    replace_path(self, path, prefix);
+                }
+                None if !path.is_empty() && is_sep_(self.prefix, path.as_bytes()[0]) => {
+                    // volume-relative path
+                    if self.prefix.is_some() {
+                        // truncate self down to the prefix, then append
+                        let n = self.prefix_len();
+                        self.repr.truncate(n);
+                        append_path(self, path);
+                    } else {
+                        // we have no prefix, so nothing to be relative to
+                        replace_path(self, path, prefix);
+                    }
+                }
+                None => {
+                    // relative path
+                    append_path(self, path);
+                }
+            }
+        }
+    }
+}
+
+impl GenericPath for Path {
+    #[inline]
+    fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
+        match path.container_as_str() {
+            None => None,
+            Some(ref s) => {
+                if contains_nul(s) {
+                    None
+                } else {
+                    Some(unsafe { GenericPathUnsafe::new_unchecked(*s) })
+                }
+            }
+        }
+    }
+
+    /// See `GenericPath::as_str` for info.
+    /// Always returns a `Some` value.
+    #[inline]
+    fn as_str<'a>(&'a self) -> Option<&'a str> {
+        Some(&self.repr[])
+    }
+
+    #[inline]
+    fn as_vec<'a>(&'a self) -> &'a [u8] {
+        self.repr.as_bytes()
+    }
+
+    #[inline]
+    fn into_vec(self) -> Vec<u8> {
+        self.repr.into_bytes()
+    }
+
+    #[inline]
+    fn dirname<'a>(&'a self) -> &'a [u8] {
+        self.dirname_str().unwrap().as_bytes()
+    }
+
+    /// See `GenericPath::dirname_str` for info.
+    /// Always returns a `Some` value.
+    fn dirname_str<'a>(&'a self) -> Option<&'a str> {
+        Some(match self.sepidx_or_prefix_len() {
+            None if ".." == self.repr => &self.repr[],
+            None => ".",
+            Some((_,idxa,end)) if &self.repr[idxa..end] == ".." => {
+                &self.repr[]
+            }
+            Some((idxb,_,end)) if &self.repr[idxb..end] == "\\" => {
+                &self.repr[]
+            }
+            Some((0,idxa,_)) => &self.repr[..idxa],
+            Some((idxb,idxa,_)) => {
+                match self.prefix {
+                    Some(DiskPrefix) | Some(VerbatimDiskPrefix) if idxb == self.prefix_len() => {
+                        &self.repr[..idxa]
+                    }
+                    _ => &self.repr[..idxb]
+                }
+            }
+        })
+    }
+
+    #[inline]
+    fn filename<'a>(&'a self) -> Option<&'a [u8]> {
+        self.filename_str().map(|x| x.as_bytes())
+    }
+
+    /// See `GenericPath::filename_str` for info.
+    /// Always returns a `Some` value if `filename` returns a `Some` value.
+    fn filename_str<'a>(&'a self) -> Option<&'a str> {
+        let repr = &self.repr[];
+        match self.sepidx_or_prefix_len() {
+            None if "." == repr || ".." == repr => None,
+            None => Some(repr),
+            Some((_,idxa,end)) if &repr[idxa..end] == ".." => None,
+            Some((_,idxa,end)) if idxa == end => None,
+            Some((_,idxa,end)) => Some(&repr[idxa..end])
+        }
+    }
+
+    /// See `GenericPath::filestem_str` for info.
+    /// Always returns a `Some` value if `filestem` returns a `Some` value.
+    #[inline]
+    fn filestem_str<'a>(&'a self) -> Option<&'a str> {
+        // filestem() returns a byte vector that's guaranteed valid UTF-8
+        self.filestem().map(|t| unsafe { mem::transmute(t) })
+    }
+
+    #[inline]
+    fn extension_str<'a>(&'a self) -> Option<&'a str> {
+        // extension() returns a byte vector that's guaranteed valid UTF-8
+        self.extension().map(|t| unsafe { mem::transmute(t) })
+    }
+
+    fn dir_path(&self) -> Path {
+        unsafe { GenericPathUnsafe::new_unchecked(self.dirname_str().unwrap()) }
+    }
+
+    #[inline]
+    fn pop(&mut self) -> bool {
+        match self.sepidx_or_prefix_len() {
+            None if "." == self.repr => false,
+            None => {
+                self.repr = String::from_str(".");
+                self.sepidx = None;
+                true
+            }
+            Some((idxb,idxa,end)) if idxb == idxa && idxb == end => false,
+            Some((idxb,_,end)) if &self.repr[idxb..end] == "\\" => false,
+            Some((idxb,idxa,_)) => {
+                let trunc = match self.prefix {
+                    Some(DiskPrefix) | Some(VerbatimDiskPrefix) | None => {
+                        let plen = self.prefix_len();
+                        if idxb == plen { idxa } else { idxb }
+                    }
+                    _ => idxb
+                };
+                self.repr.truncate(trunc);
+                self.update_sepidx();
+                true
+            }
+        }
+    }
+
+    fn root_path(&self) -> Option<Path> {
+        if self.prefix.is_some() {
+            Some(Path::new(match self.prefix {
+                Some(DiskPrefix) if self.is_absolute() => {
+                    &self.repr[..self.prefix_len()+1]
+                }
+                Some(VerbatimDiskPrefix) => {
+                    &self.repr[..self.prefix_len()+1]
+                }
+                _ => &self.repr[..self.prefix_len()]
+            }))
+        } else if is_vol_relative(self) {
+            Some(Path::new(&self.repr[..1]))
+        } else {
+            None
+        }
+    }
+
+    /// See `GenericPath::is_absolute` for info.
+    ///
+    /// A Windows Path is considered absolute only if it has a non-volume prefix,
+    /// or if it has a volume prefix and the path starts with '\'.
+    /// A path of `\foo` is not considered absolute because it's actually
+    /// relative to the "current volume". A separate method `Path::is_vol_relative`
+    /// is provided to indicate this case. Similarly a path of `C:foo` is not
+    /// considered absolute because it's relative to the cwd on volume C:. A
+    /// separate method `Path::is_cwd_relative` is provided to indicate this case.
+    #[inline]
+    fn is_absolute(&self) -> bool {
+        match self.prefix {
+            Some(DiskPrefix) => {
+                let rest = &self.repr[self.prefix_len()..];
+                rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE
+            }
+            Some(_) => true,
+            None => false
+        }
+    }
+
+    #[inline]
+    fn is_relative(&self) -> bool {
+        self.prefix.is_none() && !is_vol_relative(self)
+    }
+
+    fn is_ancestor_of(&self, other: &Path) -> bool {
+        if !self.equiv_prefix(other) {
+            false
+        } else if self.is_absolute() != other.is_absolute() ||
+                  is_vol_relative(self) != is_vol_relative(other) {
+            false
+        } else {
+            let mut ita = self.str_components().map(|x|x.unwrap());
+            let mut itb = other.str_components().map(|x|x.unwrap());
+            if "." == self.repr {
+                return itb.next() != Some("..");
+            }
+            loop {
+                match (ita.next(), itb.next()) {
+                    (None, _) => break,
+                    (Some(a), Some(b)) if a == b => { continue },
+                    (Some(a), _) if a == ".." => {
+                        // if ita contains only .. components, it's an ancestor
+                        return ita.all(|x| x == "..");
+                    }
+                    _ => return false
+                }
+            }
+            true
+        }
+    }
+
+    fn path_relative_from(&self, base: &Path) -> Option<Path> {
+        fn comp_requires_verbatim(s: &str) -> bool {
+            s == "." || s == ".." || s.contains_char(SEP2)
+        }
+
+        if !self.equiv_prefix(base) {
+            // prefixes differ
+            if self.is_absolute() {
+                Some(self.clone())
+            } else if self.prefix == Some(DiskPrefix) && base.prefix == Some(DiskPrefix) {
+                // both drives, drive letters must differ or they'd be equiv
+                Some(self.clone())
+            } else {
+                None
+            }
+        } else if self.is_absolute() != base.is_absolute() {
+            if self.is_absolute() {
+                Some(self.clone())
+            } else {
+                None
+            }
+        } else if is_vol_relative(self) != is_vol_relative(base) {
+            if is_vol_relative(self) {
+                Some(self.clone())
+            } else {
+                None
+            }
+        } else {
+            let mut ita = self.str_components().map(|x|x.unwrap());
+            let mut itb = base.str_components().map(|x|x.unwrap());
+            let mut comps = vec![];
+
+            let a_verb = is_verbatim(self);
+            let b_verb = is_verbatim(base);
+            loop {
+                match (ita.next(), itb.next()) {
+                    (None, None) => break,
+                    (Some(a), None) if a_verb && comp_requires_verbatim(a) => {
+                        return Some(self.clone())
+                    }
+                    (Some(a), None) => {
+                        comps.push(a);
+                        if !a_verb {
+                            comps.extend(ita.by_ref());
+                            break;
+                        }
+                    }
+                    (None, _) => comps.push(".."),
+                    (Some(a), Some(b)) if comps.is_empty() && a == b => (),
+                    (Some(a), Some(b)) if !b_verb && b == "." => {
+                        if a_verb && comp_requires_verbatim(a) {
+                            return Some(self.clone())
+                        } else { comps.push(a) }
+                    }
+                    (Some(_), Some(b)) if !b_verb && b == ".." => return None,
+                    (Some(a), Some(_)) if a_verb && comp_requires_verbatim(a) => {
+                        return Some(self.clone())
+                    }
+                    (Some(a), Some(_)) => {
+                        comps.push("..");
+                        for _ in itb.by_ref() {
+                            comps.push("..");
+                        }
+                        comps.push(a);
+                        if !a_verb {
+                            comps.extend(ita.by_ref());
+                            break;
+                        }
+                    }
+                }
+            }
+            Some(Path::new(comps.connect("\\")))
+        }
+    }
+
+    fn ends_with_path(&self, child: &Path) -> bool {
+        if !child.is_relative() { return false; }
+        let mut selfit = self.str_components().rev();
+        let mut childit = child.str_components().rev();
+        loop {
+            match (selfit.next(), childit.next()) {
+                (Some(a), Some(b)) => if a != b { return false; },
+                (Some(_), None) => break,
+                (None, Some(_)) => return false,
+                (None, None) => break
+            }
+        }
+        true
+    }
+}
+
+impl Path {
+    /// Returns a new `Path` from a `BytesContainer`.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the vector contains a `NUL`, or if it contains invalid UTF-8.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// println!("{}", Path::new(r"C:\some\path").display());
+    /// ```
+    #[inline]
+    pub fn new<T: BytesContainer>(path: T) -> Path {
+        GenericPath::new(path)
+    }
+
+    /// Returns a new `Some(Path)` from a `BytesContainer`.
+    ///
+    /// Returns `None` if the vector contains a `NUL`, or if it contains invalid UTF-8.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// let path = Path::new_opt(r"C:\some\path");
+    ///
+    /// match path {
+    ///     Some(path) => println!("{}", path.display()),
+    ///     None       => println!("There was a problem with your path."),
+    /// }
+    /// ```
+    #[inline]
+    pub fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
+        GenericPath::new_opt(path)
+    }
+
+    /// Returns an iterator that yields each component of the path in turn as a Option<&str>.
+    /// Every component is guaranteed to be Some.
+    /// Does not yield the path prefix (including server/share components in UNC paths).
+    /// Does not distinguish between volume-relative and relative paths, e.g.
+    /// \a\b\c and a\b\c.
+    /// Does not distinguish between absolute and cwd-relative paths, e.g.
+    /// C:\foo and C:foo.
+    pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
+        let repr = &self.repr[];
+        let s = match self.prefix {
+            Some(_) => {
+                let plen = self.prefix_len();
+                if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE {
+                    &repr[plen+1..]
+                } else { &repr[plen..] }
+            }
+            None if repr.as_bytes()[0] == SEP_BYTE => &repr[1..],
+            None => repr
+        };
+        let some: fn(&'a str) -> Option<&'a str> = Some; // coerce to fn ptr
+        let ret = s.split_terminator(SEP).map(some);
+        ret
+    }
+
+    /// Returns an iterator that yields each component of the path in turn as a &[u8].
+    /// See str_components() for details.
+    pub fn components<'a>(&'a self) -> Components<'a> {
+        fn convert<'a>(x: Option<&'a str>) -> &'a [u8] {
+            #![inline]
+            x.unwrap().as_bytes()
+        }
+        let convert: for<'b> fn(Option<&'b str>) -> &'b [u8] = convert; // coerce to fn ptr
+        self.str_components().map(convert)
+    }
+
+    fn equiv_prefix(&self, other: &Path) -> bool {
+        let s_repr = &self.repr[];
+        let o_repr = &other.repr[];
+        match (self.prefix, other.prefix) {
+            (Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
+                self.is_absolute() &&
+                    s_repr.as_bytes()[0].to_ascii_lowercase() ==
+                        o_repr.as_bytes()[4].to_ascii_lowercase()
+            }
+            (Some(VerbatimDiskPrefix), Some(DiskPrefix)) => {
+                other.is_absolute() &&
+                    s_repr.as_bytes()[4].to_ascii_lowercase() ==
+                        o_repr.as_bytes()[0].to_ascii_lowercase()
+            }
+            (Some(VerbatimDiskPrefix), Some(VerbatimDiskPrefix)) => {
+                s_repr.as_bytes()[4].to_ascii_lowercase() ==
+                    o_repr.as_bytes()[4].to_ascii_lowercase()
+            }
+            (Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => {
+                &s_repr[2..self.prefix_len()] == &o_repr[8..other.prefix_len()]
+            }
+            (Some(VerbatimUNCPrefix(_,_)), Some(UNCPrefix(_,_))) => {
+                &s_repr[8..self.prefix_len()] == &o_repr[2..other.prefix_len()]
+            }
+            (None, None) => true,
+            (a, b) if a == b => {
+                &s_repr[..self.prefix_len()] == &o_repr[..other.prefix_len()]
+            }
+            _ => false
+        }
+    }
+
+    fn normalize_(s: &str) -> (Option<PathPrefix>, String) {
+        // make borrowck happy
+        let (prefix, val) = {
+            let prefix = parse_prefix(s);
+            let path = Path::normalize__(s, prefix);
+            (prefix, path)
+        };
+        (prefix, match val {
+            None => s.to_string(),
+            Some(val) => val
+        })
+    }
+
+    fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
+        if prefix_is_verbatim(prefix) {
+            // don't do any normalization
+            match prefix {
+                Some(VerbatimUNCPrefix(x, 0)) if s.len() == 8 + x => {
+                    // the server component has no trailing '\'
+                    let mut s = String::from_str(s);
+                    s.push(SEP);
+                    Some(s)
+                }
+                _ => None
+            }
+        } else {
+            let (is_abs, comps) = normalize_helper(s, prefix);
+            let mut comps = comps;
+            match (comps.is_some(),prefix) {
+                (false, Some(DiskPrefix)) => {
+                    if s.as_bytes()[0] >= b'a' && s.as_bytes()[0] <= b'z' {
+                        comps = Some(vec![]);
+                    }
+                }
+                (false, Some(VerbatimDiskPrefix)) => {
+                    if s.as_bytes()[4] >= b'a' && s.as_bytes()[0] <= b'z' {
+                        comps = Some(vec![]);
+                    }
+                }
+                _ => ()
+            }
+            match comps {
+                None => None,
+                Some(comps) => {
+                    if prefix.is_some() && comps.is_empty() {
+                        match prefix.unwrap() {
+                            DiskPrefix => {
+                                let len = prefix_len(prefix) + is_abs as uint;
+                                let mut s = String::from_str(&s[..len]);
+                                unsafe {
+                                    let v = s.as_mut_vec();
+                                    v[0] = (*v)[0].to_ascii_uppercase();
+                                }
+                                if is_abs {
+                                    // normalize C:/ to C:\
+                                    unsafe {
+                                        s.as_mut_vec()[2] = SEP_BYTE;
+                                    }
+                                }
+                                Some(s)
+                            }
+                            VerbatimDiskPrefix => {
+                                let len = prefix_len(prefix) + is_abs as uint;
+                                let mut s = String::from_str(&s[..len]);
+                                unsafe {
+                                    let v = s.as_mut_vec();
+                                    v[4] = (*v)[4].to_ascii_uppercase();
+                                }
+                                Some(s)
+                            }
+                            _ => {
+                                let plen = prefix_len(prefix);
+                                if s.len() > plen {
+                                    Some(String::from_str(&s[..plen]))
+                                } else { None }
+                            }
+                        }
+                    } else if is_abs && comps.is_empty() {
+                        Some(repeat(SEP).take(1).collect())
+                    } else {
+                        let prefix_ = &s[..prefix_len(prefix)];
+                        let n = prefix_.len() +
+                                if is_abs { comps.len() } else { comps.len() - 1} +
+                                comps.iter().map(|v| v.len()).sum();
+                        let mut s = String::with_capacity(n);
+                        match prefix {
+                            Some(DiskPrefix) => {
+                                s.push(prefix_.as_bytes()[0].to_ascii_uppercase() as char);
+                                s.push(':');
+                            }
+                            Some(VerbatimDiskPrefix) => {
+                                s.push_str(&prefix_[..4]);
+                                s.push(prefix_.as_bytes()[4].to_ascii_uppercase() as char);
+                                s.push_str(&prefix_[5..]);
+                            }
+                            Some(UNCPrefix(a,b)) => {
+                                s.push_str("\\\\");
+                                s.push_str(&prefix_[2..a+2]);
+                                s.push(SEP);
+                                s.push_str(&prefix_[3+a..3+a+b]);
+                            }
+                            Some(_) => s.push_str(prefix_),
+                            None => ()
+                        }
+                        let mut it = comps.into_iter();
+                        if !is_abs {
+                            match it.next() {
+                                None => (),
+                                Some(comp) => s.push_str(comp)
+                            }
+                        }
+                        for comp in it {
+                            s.push(SEP);
+                            s.push_str(comp);
+                        }
+                        Some(s)
+                    }
+                }
+            }
+        }
+    }
+
+    fn update_sepidx(&mut self) {
+        let s = if self.has_nonsemantic_trailing_slash() {
+                    &self.repr[..self.repr.len()-1]
+                } else { &self.repr[] };
+        let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) {
+            is_sep
+        } else {
+            is_sep_verbatim
+        };
+        let idx = s.rfind(sep_test);
+        let prefixlen = self.prefix_len();
+        self.sepidx = idx.and_then(|x| if x < prefixlen { None } else { Some(x) });
+    }
+
+    fn prefix_len(&self) -> uint {
+        prefix_len(self.prefix)
+    }
+
+    // Returns a tuple (before, after, end) where before is the index of the separator
+    // and after is the index just after the separator.
+    // end is the length of the string, normally, or the index of the final character if it is
+    // a non-semantic trailing separator in a verbatim string.
+    // If the prefix is considered the separator, before and after are the same.
+    fn sepidx_or_prefix_len(&self) -> Option<(uint,uint,uint)> {
+        match self.sepidx {
+            None => match self.prefix_len() { 0 => None, x => Some((x,x,self.repr.len())) },
+            Some(x) => {
+                if self.has_nonsemantic_trailing_slash() {
+                    Some((x,x+1,self.repr.len()-1))
+                } else { Some((x,x+1,self.repr.len())) }
+            }
+        }
+    }
+
+    fn has_nonsemantic_trailing_slash(&self) -> bool {
+        is_verbatim(self) && self.repr.len() > self.prefix_len()+1 &&
+            self.repr.as_bytes()[self.repr.len()-1] == SEP_BYTE
+    }
+
+    fn update_normalized(&mut self, s: &str) {
+        let (prefix, path) = Path::normalize_(s);
+        self.repr = path;
+        self.prefix = prefix;
+        self.update_sepidx();
+    }
+}
+
+/// Returns whether the path is considered "volume-relative", which means a path
+/// that looks like "\foo". Paths of this form are relative to the current volume,
+/// but absolute within that volume.
+#[inline]
+pub fn is_vol_relative(path: &Path) -> bool {
+    path.prefix.is_none() && is_sep_byte(&path.repr.as_bytes()[0])
+}
+
+/// Returns whether the path is considered "cwd-relative", which means a path
+/// with a volume prefix that is not absolute. This look like "C:foo.txt". Paths
+/// of this form are relative to the cwd on the given volume.
+#[inline]
+pub fn is_cwd_relative(path: &Path) -> bool {
+    path.prefix == Some(DiskPrefix) && !path.is_absolute()
+}
+
+/// Returns the PathPrefix for this Path
+#[inline]
+pub fn prefix(path: &Path) -> Option<PathPrefix> {
+    path.prefix
+}
+
+/// Returns whether the Path's prefix is a verbatim prefix, i.e. `\\?\`
+#[inline]
+pub fn is_verbatim(path: &Path) -> bool {
+    prefix_is_verbatim(path.prefix)
+}
+
+/// Returns the non-verbatim equivalent of the input path, if possible.
+/// If the input path is a device namespace path, None is returned.
+/// If the input path is not verbatim, it is returned as-is.
+/// If the input path is verbatim, but the same path can be expressed as
+/// non-verbatim, the non-verbatim version is returned.
+/// Otherwise, None is returned.
+pub fn make_non_verbatim(path: &Path) -> Option<Path> {
+    let repr = &path.repr[];
+    let new_path = match path.prefix {
+        Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None,
+        Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()),
+        Some(VerbatimDiskPrefix) => {
+            // \\?\D:\
+            Path::new(&repr[4..])
+        }
+        Some(VerbatimUNCPrefix(_,_)) => {
+            // \\?\UNC\server\share
+            Path::new(format!(r"\{}", &repr[7..]))
+        }
+    };
+    if new_path.prefix.is_none() {
+        // \\?\UNC\server is a VerbatimUNCPrefix
+        // but \\server is nothing
+        return None;
+    }
+    // now ensure normalization didn't change anything
+    if &repr[path.prefix_len()..] == &new_path.repr[new_path.prefix_len()..] {
+        Some(new_path)
+    } else {
+        None
+    }
+}
+
+/// The standard path separator character
+pub const SEP: char = '\\';
+/// The standard path separator byte
+pub const SEP_BYTE: u8 = SEP as u8;
+
+/// The alternative path separator character
+pub const SEP2: char = '/';
+/// The alternative path separator character
+pub const SEP2_BYTE: u8 = SEP2 as u8;
+
+/// Returns whether the given char is a path separator.
+/// Allows both the primary separator '\' and the alternative separator '/'.
+#[inline]
+pub fn is_sep(c: char) -> bool {
+    c == SEP || c == SEP2
+}
+
+/// Returns whether the given char is a path separator.
+/// Only allows the primary separator '\'; use is_sep to allow '/'.
+#[inline]
+pub fn is_sep_verbatim(c: char) -> bool {
+    c == SEP
+}
+
+/// Returns whether the given byte is a path separator.
+/// Allows both the primary separator '\' and the alternative separator '/'.
+#[inline]
+pub fn is_sep_byte(u: &u8) -> bool {
+    *u == SEP_BYTE || *u == SEP2_BYTE
+}
+
+/// Returns whether the given byte is a path separator.
+/// Only allows the primary separator '\'; use is_sep_byte to allow '/'.
+#[inline]
+pub fn is_sep_byte_verbatim(u: &u8) -> bool {
+    *u == SEP_BYTE
+}
+
+/// Prefix types for Path
+#[derive(Copy, PartialEq, Clone, Debug)]
+pub enum PathPrefix {
+    /// Prefix `\\?\`, uint is the length of the following component
+    VerbatimPrefix(uint),
+    /// Prefix `\\?\UNC\`, uints are the lengths of the UNC components
+    VerbatimUNCPrefix(uint, uint),
+    /// Prefix `\\?\C:\` (for any alphabetic character)
+    VerbatimDiskPrefix,
+    /// Prefix `\\.\`, uint is the length of the following component
+    DeviceNSPrefix(uint),
+    /// UNC prefix `\\server\share`, uints are the lengths of the server/share
+    UNCPrefix(uint, uint),
+    /// Prefix `C:` for any alphabetic character
+    DiskPrefix
+}
+
+fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
+    if path.starts_with("\\\\") {
+        // \\
+        path = &path[2..];
+        if path.starts_with("?\\") {
+            // \\?\
+            path = &path[2..];
+            if path.starts_with("UNC\\") {
+                // \\?\UNC\server\share
+                path = &path[4..];
+                let (idx_a, idx_b) = match parse_two_comps(path, is_sep_verbatim) {
+                    Some(x) => x,
+                    None => (path.len(), 0)
+                };
+                return Some(VerbatimUNCPrefix(idx_a, idx_b));
+            } else {
+                // \\?\path
+                let idx = path.find('\\');
+                if idx == Some(2) && path.as_bytes()[1] == b':' {
+                    let c = path.as_bytes()[0];
+                    if c.is_ascii() && (c as char).is_alphabetic() {
+                        // \\?\C:\ path
+                        return Some(VerbatimDiskPrefix);
+                    }
+                }
+                let idx = idx.unwrap_or(path.len());
+                return Some(VerbatimPrefix(idx));
+            }
+        } else if path.starts_with(".\\") {
+            // \\.\path
+            path = &path[2..];
+            let idx = path.find('\\').unwrap_or(path.len());
+            return Some(DeviceNSPrefix(idx));
+        }
+        match parse_two_comps(path, is_sep) {
+            Some((idx_a, idx_b)) if idx_a > 0 && idx_b > 0 => {
+                // \\server\share
+                return Some(UNCPrefix(idx_a, idx_b));
+            }
+            _ => ()
+        }
+    } else if path.len() > 1 && path.as_bytes()[1] == b':' {
+        // C:
+        let c = path.as_bytes()[0];
+        if c.is_ascii() && (c as char).is_alphabetic() {
+            return Some(DiskPrefix);
+        }
+    }
+    return None;
+
+    fn parse_two_comps(mut path: &str, f: fn(char) -> bool) -> Option<(uint, uint)> {
+        let idx_a = match path.find(f) {
+            None => return None,
+            Some(x) => x
+        };
+        path = &path[idx_a+1..];
+        let idx_b = path.find(f).unwrap_or(path.len());
+        Some((idx_a, idx_b))
+    }
+}
+
+// None result means the string didn't need normalizing
+fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool, Option<Vec<&'a str>>) {
+    let f: fn(char) -> bool = if !prefix_is_verbatim(prefix) {
+        is_sep
+    } else {
+        is_sep_verbatim
+    };
+    let is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix)));
+    let s_ = &s[prefix_len(prefix)..];
+    let s_ = if is_abs { &s_[1..] } else { s_ };
+
+    if is_abs && s_.is_empty() {
+        return (is_abs, match prefix {
+            Some(DiskPrefix) | None => (if is_sep_verbatim(s.char_at(prefix_len(prefix))) { None }
+                                        else { Some(vec![]) }),
+            Some(_) => Some(vec![]), // need to trim the trailing separator
+        });
+    }
+    let mut comps: Vec<&'a str> = vec![];
+    let mut n_up = 0u;
+    let mut changed = false;
+    for comp in s_.split(f) {
+        if comp.is_empty() { changed = true }
+        else if comp == "." { changed = true }
+        else if comp == ".." {
+            let has_abs_prefix = match prefix {
+                Some(DiskPrefix) => false,
+                Some(_) => true,
+                None => false
+            };
+            if (is_abs || has_abs_prefix) && comps.is_empty() { changed = true }
+            else if comps.len() == n_up { comps.push(".."); n_up += 1 }
+            else { comps.pop().unwrap(); changed = true }
+        } else { comps.push(comp) }
+    }
+    if !changed && !prefix_is_verbatim(prefix) {
+        changed = s.find(is_sep).is_some();
+    }
+    if changed {
+        if comps.is_empty() && !is_abs && prefix.is_none() {
+            if s == "." {
+                return (is_abs, None);
+            }
+            comps.push(".");
+        }
+        (is_abs, Some(comps))
+    } else {
+        (is_abs, None)
+    }
+}
+
+fn prefix_is_verbatim(p: Option<PathPrefix>) -> bool {
+    match p {
+        Some(VerbatimPrefix(_)) | Some(VerbatimUNCPrefix(_,_)) | Some(VerbatimDiskPrefix) => true,
+        Some(DeviceNSPrefix(_)) => true, // not really sure, but I think so
+        _ => false
+    }
+}
+
+fn prefix_len(p: Option<PathPrefix>) -> uint {
+    match p {
+        None => 0,
+        Some(VerbatimPrefix(x)) => 4 + x,
+        Some(VerbatimUNCPrefix(x,y)) => 8 + x + 1 + y,
+        Some(VerbatimDiskPrefix) => 6,
+        Some(UNCPrefix(x,y)) => 2 + x + 1 + y,
+        Some(DeviceNSPrefix(x)) => 4 + x,
+        Some(DiskPrefix) => 2
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::PathPrefix::*;
+    use super::parse_prefix;
+    use super::*;
+
+    use clone::Clone;
+    use iter::IteratorExt;
+    use option::Option::{self, Some, None};
+    use old_path::GenericPath;
+    use slice::{AsSlice, SliceExt};
+    use str::Str;
+    use string::ToString;
+    use vec::Vec;
+
+    macro_rules! t {
+        (s: $path:expr, $exp:expr) => (
+            {
+                let path = $path;
+                assert_eq!(path.as_str(), Some($exp));
+            }
+        );
+        (v: $path:expr, $exp:expr) => (
+            {
+                let path = $path;
+                assert_eq!(path.as_vec(), $exp);
+            }
+        )
+    }
+
+    #[test]
+    fn test_parse_prefix() {
+        macro_rules! t {
+            ($path:expr, $exp:expr) => (
+                {
+                    let path = $path;
+                    let exp = $exp;
+                    let res = parse_prefix(path);
+                    assert_eq!(res, exp);
+                }
+            )
+        }
+
+        t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5)));
+        t!("\\\\", None);
+        t!("\\\\SERVER", None);
+        t!("\\\\SERVER\\", None);
+        t!("\\\\SERVER\\\\", None);
+        t!("\\\\SERVER\\\\foo", None);
+        t!("\\\\SERVER\\share", Some(UNCPrefix(6,5)));
+        t!("\\\\SERVER/share/foo", Some(UNCPrefix(6,5)));
+        t!("\\\\SERVER\\share/foo", Some(UNCPrefix(6,5)));
+        t!("//SERVER/share/foo", None);
+        t!("\\\\\\a\\b\\c", None);
+        t!("\\\\?\\a\\b\\c", Some(VerbatimPrefix(1)));
+        t!("\\\\?\\a/b/c", Some(VerbatimPrefix(5)));
+        t!("//?/a/b/c", None);
+        t!("\\\\.\\a\\b", Some(DeviceNSPrefix(1)));
+        t!("\\\\.\\a/b", Some(DeviceNSPrefix(3)));
+        t!("//./a/b", None);
+        t!("\\\\?\\UNC\\server\\share\\foo", Some(VerbatimUNCPrefix(6,5)));
+        t!("\\\\?\\UNC\\\\share\\foo", Some(VerbatimUNCPrefix(0,5)));
+        t!("\\\\?\\UNC\\", Some(VerbatimUNCPrefix(0,0)));
+        t!("\\\\?\\UNC\\server/share/foo", Some(VerbatimUNCPrefix(16,0)));
+        t!("\\\\?\\UNC\\server", Some(VerbatimUNCPrefix(6,0)));
+        t!("\\\\?\\UNC\\server\\", Some(VerbatimUNCPrefix(6,0)));
+        t!("\\\\?\\UNC/server/share", Some(VerbatimPrefix(16)));
+        t!("\\\\?\\UNC", Some(VerbatimPrefix(3)));
+        t!("\\\\?\\C:\\a\\b.txt", Some(VerbatimDiskPrefix));
+        t!("\\\\?\\z:\\", Some(VerbatimDiskPrefix));
+        t!("\\\\?\\C:", Some(VerbatimPrefix(2)));
+        t!("\\\\?\\C:a.txt", Some(VerbatimPrefix(7)));
+        t!("\\\\?\\C:a\\b.txt", Some(VerbatimPrefix(3)));
+        t!("\\\\?\\C:/a", Some(VerbatimPrefix(4)));
+        t!("C:\\foo", Some(DiskPrefix));
+        t!("z:/foo", Some(DiskPrefix));
+        t!("d:", Some(DiskPrefix));
+        t!("ab:", None);
+        t!("ü:\\foo", None);
+        t!("3:\\foo", None);
+        t!(" :\\foo", None);
+        t!("::\\foo", None);
+        t!("\\\\?\\C:", Some(VerbatimPrefix(2)));
+        t!("\\\\?\\z:\\", Some(VerbatimDiskPrefix));
+        t!("\\\\?\\ab:\\", Some(VerbatimPrefix(3)));
+        t!("\\\\?\\C:\\a", Some(VerbatimDiskPrefix));
+        t!("\\\\?\\C:/a", Some(VerbatimPrefix(4)));
+        t!("\\\\?\\C:\\a/b", Some(VerbatimDiskPrefix));
+    }
+
+    #[test]
+    fn test_paths() {
+        let empty: &[u8] = &[];
+        t!(v: Path::new(empty), b".");
+        t!(v: Path::new(b"\\"), b"\\");
+        t!(v: Path::new(b"a\\b\\c"), b"a\\b\\c");
+
+        t!(s: Path::new(""), ".");
+        t!(s: Path::new("\\"), "\\");
+        t!(s: Path::new("hi"), "hi");
+        t!(s: Path::new("hi\\"), "hi");
+        t!(s: Path::new("\\lib"), "\\lib");
+        t!(s: Path::new("\\lib\\"), "\\lib");
+        t!(s: Path::new("hi\\there"), "hi\\there");
+        t!(s: Path::new("hi\\there.txt"), "hi\\there.txt");
+        t!(s: Path::new("/"), "\\");
+        t!(s: Path::new("hi/"), "hi");
+        t!(s: Path::new("/lib"), "\\lib");
+        t!(s: Path::new("/lib/"), "\\lib");
+        t!(s: Path::new("hi/there"), "hi\\there");
+
+        t!(s: Path::new("hi\\there\\"), "hi\\there");
+        t!(s: Path::new("hi\\..\\there"), "there");
+        t!(s: Path::new("hi/../there"), "there");
+        t!(s: Path::new("..\\hi\\there"), "..\\hi\\there");
+        t!(s: Path::new("\\..\\hi\\there"), "\\hi\\there");
+        t!(s: Path::new("/../hi/there"), "\\hi\\there");
+        t!(s: Path::new("foo\\.."), ".");
+        t!(s: Path::new("\\foo\\.."), "\\");
+        t!(s: Path::new("\\foo\\..\\.."), "\\");
+        t!(s: Path::new("\\foo\\..\\..\\bar"), "\\bar");
+        t!(s: Path::new("\\.\\hi\\.\\there\\."), "\\hi\\there");
+        t!(s: Path::new("\\.\\hi\\.\\there\\.\\.."), "\\hi");
+        t!(s: Path::new("foo\\..\\.."), "..");
+        t!(s: Path::new("foo\\..\\..\\.."), "..\\..");
+        t!(s: Path::new("foo\\..\\..\\bar"), "..\\bar");
+
+        assert_eq!(Path::new(b"foo\\bar").into_vec(), b"foo\\bar");
+        assert_eq!(Path::new(b"\\foo\\..\\..\\bar").into_vec(), b"\\bar");
+
+        t!(s: Path::new("\\\\a"), "\\a");
+        t!(s: Path::new("\\\\a\\"), "\\a");
+        t!(s: Path::new("\\\\a\\b"), "\\\\a\\b");
+        t!(s: Path::new("\\\\a\\b\\"), "\\\\a\\b");
+        t!(s: Path::new("\\\\a\\b/"), "\\\\a\\b");
+        t!(s: Path::new("\\\\\\b"), "\\b");
+        t!(s: Path::new("\\\\a\\\\b"), "\\a\\b");
+        t!(s: Path::new("\\\\a\\b\\c"), "\\\\a\\b\\c");
+        t!(s: Path::new("\\\\server\\share/path"), "\\\\server\\share\\path");
+        t!(s: Path::new("\\\\server/share/path"), "\\\\server\\share\\path");
+        t!(s: Path::new("C:a\\b.txt"), "C:a\\b.txt");
+        t!(s: Path::new("C:a/b.txt"), "C:a\\b.txt");
+        t!(s: Path::new("z:\\a\\b.txt"), "Z:\\a\\b.txt");
+        t!(s: Path::new("z:/a/b.txt"), "Z:\\a\\b.txt");
+        t!(s: Path::new("ab:/a/b.txt"), "ab:\\a\\b.txt");
+        t!(s: Path::new("C:\\"), "C:\\");
+        t!(s: Path::new("C:"), "C:");
+        t!(s: Path::new("q:"), "Q:");
+        t!(s: Path::new("C:/"), "C:\\");
+        t!(s: Path::new("C:\\foo\\.."), "C:\\");
+        t!(s: Path::new("C:foo\\.."), "C:");
+        t!(s: Path::new("C:\\a\\"), "C:\\a");
+        t!(s: Path::new("C:\\a/"), "C:\\a");
+        t!(s: Path::new("C:\\a\\b\\"), "C:\\a\\b");
+        t!(s: Path::new("C:\\a\\b/"), "C:\\a\\b");
+        t!(s: Path::new("C:a\\"), "C:a");
+        t!(s: Path::new("C:a/"), "C:a");
+        t!(s: Path::new("C:a\\b\\"), "C:a\\b");
+        t!(s: Path::new("C:a\\b/"), "C:a\\b");
+        t!(s: Path::new("\\\\?\\z:\\a\\b.txt"), "\\\\?\\z:\\a\\b.txt");
+        t!(s: Path::new("\\\\?\\C:/a/b.txt"), "\\\\?\\C:/a/b.txt");
+        t!(s: Path::new("\\\\?\\C:\\a/b.txt"), "\\\\?\\C:\\a/b.txt");
+        t!(s: Path::new("\\\\?\\test\\a\\b.txt"), "\\\\?\\test\\a\\b.txt");
+        t!(s: Path::new("\\\\?\\foo\\bar\\"), "\\\\?\\foo\\bar\\");
+        t!(s: Path::new("\\\\.\\foo\\bar"), "\\\\.\\foo\\bar");
+        t!(s: Path::new("\\\\.\\"), "\\\\.\\");
+        t!(s: Path::new("\\\\?\\UNC\\server\\share\\foo"), "\\\\?\\UNC\\server\\share\\foo");
+        t!(s: Path::new("\\\\?\\UNC\\server/share"), "\\\\?\\UNC\\server/share\\");
+        t!(s: Path::new("\\\\?\\UNC\\server"), "\\\\?\\UNC\\server\\");
+        t!(s: Path::new("\\\\?\\UNC\\"), "\\\\?\\UNC\\\\");
+        t!(s: Path::new("\\\\?\\UNC"), "\\\\?\\UNC");
+
+        // I'm not sure whether \\.\foo/bar should normalize to \\.\foo\bar
+        // as information is sparse and this isn't really googleable.
+        // I'm going to err on the side of not normalizing it, as this skips the filesystem
+        t!(s: Path::new("\\\\.\\foo/bar"), "\\\\.\\foo/bar");
+        t!(s: Path::new("\\\\.\\foo\\bar"), "\\\\.\\foo\\bar");
+    }
+
+    #[test]
+    fn test_opt_paths() {
+        assert!(Path::new_opt(b"foo\\bar\0") == None);
+        assert!(Path::new_opt(b"foo\\bar\x80") == None);
+        t!(v: Path::new_opt(b"foo\\bar").unwrap(), b"foo\\bar");
+        assert!(Path::new_opt("foo\\bar\0") == None);
+        t!(s: Path::new_opt("foo\\bar").unwrap(), "foo\\bar");
+    }
+
+    #[test]
+    fn test_null_byte() {
+        use thread::Thread;
+        let result = Thread::scoped(move|| {
+            Path::new(b"foo/bar\0")
+        }).join();
+        assert!(result.is_err());
+
+        let result = Thread::scoped(move|| {
+            Path::new("test").set_filename(b"f\0o")
+        }).join();
+        assert!(result.is_err());
+
+        let result = Thread::scoped(move || {
+            Path::new("test").push(b"f\0o");
+        }).join();
+        assert!(result.is_err());
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_not_utf8_panics() {
+        Path::new(b"hello\x80.txt");
+    }
+
+    #[test]
+    fn test_display_str() {
+        let path = Path::new("foo");
+        assert_eq!(path.display().to_string(), "foo");
+        let path = Path::new(b"\\");
+        assert_eq!(path.filename_display().to_string(), "");
+
+        let path = Path::new("foo");
+        let mo = path.display().as_cow();
+        assert_eq!(mo.as_slice(), "foo");
+        let path = Path::new(b"\\");
+        let mo = path.filename_display().as_cow();
+        assert_eq!(mo.as_slice(), "");
+    }
+
+    #[test]
+    fn test_display() {
+        macro_rules! t {
+            ($path:expr, $exp:expr, $expf:expr) => (
+                {
+                    let path = Path::new($path);
+                    let f = format!("{}", path.display());
+                    assert_eq!(f, $exp);
+                    let f = format!("{}", path.filename_display());
+                    assert_eq!(f, $expf);
+                }
+            )
+        }
+
+        t!("foo", "foo", "foo");
+        t!("foo\\bar", "foo\\bar", "bar");
+        t!("\\", "\\", "");
+    }
+
+    #[test]
+    fn test_components() {
+        macro_rules! t {
+            (s: $path:expr, $op:ident, $exp:expr) => (
+                {
+                    let path = $path;
+                    let path = Path::new(path);
+                    assert_eq!(path.$op(), Some($exp));
+                }
+            );
+            (s: $path:expr, $op:ident, $exp:expr, opt) => (
+                {
+                    let path = $path;
+                    let path = Path::new(path);
+                    let left = path.$op();
+                    assert_eq!(left, $exp);
+                }
+            );
+            (v: $path:expr, $op:ident, $exp:expr) => (
+                {
+                    let path = $path;
+                    let path = Path::new(path);
+                    assert_eq!(path.$op(), $exp);
+                }
+            )
+        }
+
+        t!(v: b"a\\b\\c", filename, Some(b"c"));
+        t!(s: "a\\b\\c", filename_str, "c");
+        t!(s: "\\a\\b\\c", filename_str, "c");
+        t!(s: "a", filename_str, "a");
+        t!(s: "\\a", filename_str, "a");
+        t!(s: ".", filename_str, None, opt);
+        t!(s: "\\", filename_str, None, opt);
+        t!(s: "..", filename_str, None, opt);
+        t!(s: "..\\..", filename_str, None, opt);
+        t!(s: "c:\\foo.txt", filename_str, "foo.txt");
+        t!(s: "C:\\", filename_str, None, opt);
+        t!(s: "C:", filename_str, None, opt);
+        t!(s: "\\\\server\\share\\foo.txt", filename_str, "foo.txt");
+        t!(s: "\\\\server\\share", filename_str, None, opt);
+        t!(s: "\\\\server", filename_str, "server");
+        t!(s: "\\\\?\\bar\\foo.txt", filename_str, "foo.txt");
+        t!(s: "\\\\?\\bar", filename_str, None, opt);
+        t!(s: "\\\\?\\", filename_str, None, opt);
+        t!(s: "\\\\?\\UNC\\server\\share\\foo.txt", filename_str, "foo.txt");
+        t!(s: "\\\\?\\UNC\\server", filename_str, None, opt);
+        t!(s: "\\\\?\\UNC\\", filename_str, None, opt);
+        t!(s: "\\\\?\\C:\\foo.txt", filename_str, "foo.txt");
+        t!(s: "\\\\?\\C:\\", filename_str, None, opt);
+        t!(s: "\\\\?\\C:", filename_str, None, opt);
+        t!(s: "\\\\?\\foo/bar", filename_str, None, opt);
+        t!(s: "\\\\?\\C:/foo", filename_str, None, opt);
+        t!(s: "\\\\.\\foo\\bar", filename_str, "bar");
+        t!(s: "\\\\.\\foo", filename_str, None, opt);
+        t!(s: "\\\\.\\foo/bar", filename_str, None, opt);
+        t!(s: "\\\\.\\foo\\bar/baz", filename_str, "bar/baz");
+        t!(s: "\\\\.\\", filename_str, None, opt);
+        t!(s: "\\\\?\\a\\b\\", filename_str, "b");
+
+        t!(v: b"a\\b\\c", dirname, b"a\\b");
+        t!(s: "a\\b\\c", dirname_str, "a\\b");
+        t!(s: "\\a\\b\\c", dirname_str, "\\a\\b");
+        t!(s: "a", dirname_str, ".");
+        t!(s: "\\a", dirname_str, "\\");
+        t!(s: ".", dirname_str, ".");
+        t!(s: "\\", dirname_str, "\\");
+        t!(s: "..", dirname_str, "..");
+        t!(s: "..\\..", dirname_str, "..\\..");
+        t!(s: "c:\\foo.txt", dirname_str, "C:\\");
+        t!(s: "C:\\", dirname_str, "C:\\");
+        t!(s: "C:", dirname_str, "C:");
+        t!(s: "C:foo.txt", dirname_str, "C:");
+        t!(s: "\\\\server\\share\\foo.txt", dirname_str, "\\\\server\\share");
+        t!(s: "\\\\server\\share", dirname_str, "\\\\server\\share");
+        t!(s: "\\\\server", dirname_str, "\\");
+        t!(s: "\\\\?\\bar\\foo.txt", dirname_str, "\\\\?\\bar");
+        t!(s: "\\\\?\\bar", dirname_str, "\\\\?\\bar");
+        t!(s: "\\\\?\\", dirname_str, "\\\\?\\");
+        t!(s: "\\\\?\\UNC\\server\\share\\foo.txt", dirname_str, "\\\\?\\UNC\\server\\share");
+        t!(s: "\\\\?\\UNC\\server", dirname_str, "\\\\?\\UNC\\server\\");
+        t!(s: "\\\\?\\UNC\\", dirname_str, "\\\\?\\UNC\\\\");
+        t!(s: "\\\\?\\C:\\foo.txt", dirname_str, "\\\\?\\C:\\");
+        t!(s: "\\\\?\\C:\\", dirname_str, "\\\\?\\C:\\");
+        t!(s: "\\\\?\\C:", dirname_str, "\\\\?\\C:");
+        t!(s: "\\\\?\\C:/foo/bar", dirname_str, "\\\\?\\C:/foo/bar");
+        t!(s: "\\\\?\\foo/bar", dirname_str, "\\\\?\\foo/bar");
+        t!(s: "\\\\.\\foo\\bar", dirname_str, "\\\\.\\foo");
+        t!(s: "\\\\.\\foo", dirname_str, "\\\\.\\foo");
+        t!(s: "\\\\?\\a\\b\\", dirname_str, "\\\\?\\a");
+
+        t!(v: b"hi\\there.txt", filestem, Some(b"there"));
+        t!(s: "hi\\there.txt", filestem_str, "there");
+        t!(s: "hi\\there", filestem_str, "there");
+        t!(s: "there.txt", filestem_str, "there");
+        t!(s: "there", filestem_str, "there");
+        t!(s: ".", filestem_str, None, opt);
+        t!(s: "\\", filestem_str, None, opt);
+        t!(s: "foo\\.bar", filestem_str, ".bar");
+        t!(s: ".bar", filestem_str, ".bar");
+        t!(s: "..bar", filestem_str, ".");
+        t!(s: "hi\\there..txt", filestem_str, "there.");
+        t!(s: "..", filestem_str, None, opt);
+        t!(s: "..\\..", filestem_str, None, opt);
+        // filestem is based on filename, so we don't need the full set of prefix tests
+
+        t!(v: b"hi\\there.txt", extension, Some(b"txt"));
+        t!(v: b"hi\\there", extension, None);
+        t!(s: "hi\\there.txt", extension_str, Some("txt"), opt);
+        t!(s: "hi\\there", extension_str, None, opt);
+        t!(s: "there.txt", extension_str, Some("txt"), opt);
+        t!(s: "there", extension_str, None, opt);
+        t!(s: ".", extension_str, None, opt);
+        t!(s: "\\", extension_str, None, opt);
+        t!(s: "foo\\.bar", extension_str, None, opt);
+        t!(s: ".bar", extension_str, None, opt);
+        t!(s: "..bar", extension_str, Some("bar"), opt);
+        t!(s: "hi\\there..txt", extension_str, Some("txt"), opt);
+        t!(s: "..", extension_str, None, opt);
+        t!(s: "..\\..", extension_str, None, opt);
+        // extension is based on filename, so we don't need the full set of prefix tests
+    }
+
+    #[test]
+    fn test_push() {
+        macro_rules! t {
+            (s: $path:expr, $join:expr) => (
+                {
+                    let path = $path;
+                    let join = $join;
+                    let mut p1 = Path::new(path);
+                    let p2 = p1.clone();
+                    p1.push(join);
+                    assert_eq!(p1, p2.join(join));
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", "..");
+        t!(s: "\\a\\b\\c", "d");
+        t!(s: "a\\b", "c\\d");
+        t!(s: "a\\b", "\\c\\d");
+        // this is just a sanity-check test. push and join share an implementation,
+        // so there's no need for the full set of prefix tests
+
+        // we do want to check one odd case though to ensure the prefix is re-parsed
+        let mut p = Path::new("\\\\?\\C:");
+        assert_eq!(prefix(&p), Some(VerbatimPrefix(2)));
+        p.push("foo");
+        assert_eq!(prefix(&p), Some(VerbatimDiskPrefix));
+        assert_eq!(p.as_str(), Some("\\\\?\\C:\\foo"));
+
+        // and another with verbatim non-normalized paths
+        let mut p = Path::new("\\\\?\\C:\\a\\");
+        p.push("foo");
+        assert_eq!(p.as_str(), Some("\\\\?\\C:\\a\\foo"));
+    }
+
+    #[test]
+    fn test_push_path() {
+        macro_rules! t {
+            (s: $path:expr, $push:expr, $exp:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    let push = Path::new($push);
+                    p.push(&push);
+                    assert_eq!(p.as_str(), Some($exp));
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", "d", "a\\b\\c\\d");
+        t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
+        t!(s: "a\\b", "c\\d", "a\\b\\c\\d");
+        t!(s: "a\\b", "\\c\\d", "\\c\\d");
+        t!(s: "a\\b", ".", "a\\b");
+        t!(s: "a\\b", "..\\c", "a\\c");
+        t!(s: "a\\b", "C:a.txt", "C:a.txt");
+        t!(s: "a\\b", "..\\..\\..\\c", "..\\c");
+        t!(s: "a\\b", "C:\\a.txt", "C:\\a.txt");
+        t!(s: "C:\\a", "C:\\b.txt", "C:\\b.txt");
+        t!(s: "C:\\a\\b\\c", "C:d", "C:\\a\\b\\c\\d");
+        t!(s: "C:a\\b\\c", "C:d", "C:a\\b\\c\\d");
+        t!(s: "C:a\\b", "..\\..\\..\\c", "C:..\\c");
+        t!(s: "C:\\a\\b", "..\\..\\..\\c", "C:\\c");
+        t!(s: "C:", r"a\b\c", r"C:a\b\c");
+        t!(s: "C:", r"..\a", r"C:..\a");
+        t!(s: "\\\\server\\share\\foo", "bar", "\\\\server\\share\\foo\\bar");
+        t!(s: "\\\\server\\share\\foo", "..\\..\\bar", "\\\\server\\share\\bar");
+        t!(s: "\\\\server\\share\\foo", "C:baz", "C:baz");
+        t!(s: "\\\\?\\C:\\a\\b", "C:c\\d", "\\\\?\\C:\\a\\b\\c\\d");
+        t!(s: "\\\\?\\C:a\\b", "C:c\\d", "C:c\\d");
+        t!(s: "\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d");
+        t!(s: "\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz");
+        t!(s: "\\\\?\\C:\\a\\b", "..\\..\\..\\c", "\\\\?\\C:\\a\\b\\..\\..\\..\\c");
+        t!(s: "\\\\?\\foo\\bar", "..\\..\\c", "\\\\?\\foo\\bar\\..\\..\\c");
+        t!(s: "\\\\?\\", "foo", "\\\\?\\\\foo");
+        t!(s: "\\\\?\\UNC\\server\\share\\foo", "bar", "\\\\?\\UNC\\server\\share\\foo\\bar");
+        t!(s: "\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a");
+        t!(s: "\\\\?\\UNC\\server\\share", "C:a", "C:a");
+        t!(s: "\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\\\foo");
+        t!(s: "C:\\a", "\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share");
+        t!(s: "\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz");
+        t!(s: "\\\\.\\foo\\bar", "C:a", "C:a");
+        // again, not sure about the following, but I'm assuming \\.\ should be verbatim
+        t!(s: "\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar");
+
+        t!(s: "\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
+    }
+
+    #[test]
+    fn test_push_many() {
+        macro_rules! t {
+            (s: $path:expr, $push:expr, $exp:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    p.push_many(&$push);
+                    assert_eq!(p.as_str(), Some($exp));
+                }
+            );
+            (v: $path:expr, $push:expr, $exp:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    p.push_many(&$push);
+                    assert_eq!(p.as_vec(), $exp);
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
+        t!(s: "a\\b\\c", ["d", "\\e"], "\\e");
+        t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
+        t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e");
+        t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e");
+        t!(v: b"a\\b\\c", [b"d", b"\\e", b"f"], b"\\e\\f");
+        t!(v: b"a\\b\\c", [b"d".to_vec(), b"e".to_vec()],
+           b"a\\b\\c\\d\\e");
+    }
+
+    #[test]
+    fn test_pop() {
+        macro_rules! t {
+            (s: $path:expr, $left:expr, $right:expr) => (
+                {
+                    let pstr = $path;
+                    let mut p = Path::new(pstr);
+                    let result = p.pop();
+                    let left = $left;
+                    assert_eq!(p.as_str(), Some(left));
+                    assert_eq!(result, $right);
+                }
+            );
+            (b: $path:expr, $left:expr, $right:expr) => (
+                {
+                    let mut p = Path::new($path);
+                    let result = p.pop();
+                    assert_eq!(p.as_vec(), $left);
+                    assert_eq!(result, $right);
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", "a\\b", true);
+        t!(s: "a", ".", true);
+        t!(s: ".", ".", false);
+        t!(s: "\\a", "\\", true);
+        t!(s: "\\", "\\", false);
+        t!(b: b"a\\b\\c", b"a\\b", true);
+        t!(b: b"a", b".", true);
+        t!(b: b".", b".", false);
+        t!(b: b"\\a", b"\\", true);
+        t!(b: b"\\", b"\\", false);
+
+        t!(s: "C:\\a\\b", "C:\\a", true);
+        t!(s: "C:\\a", "C:\\", true);
+        t!(s: "C:\\", "C:\\", false);
+        t!(s: "C:a\\b", "C:a", true);
+        t!(s: "C:a", "C:", true);
+        t!(s: "C:", "C:", false);
+        t!(s: "\\\\server\\share\\a\\b", "\\\\server\\share\\a", true);
+        t!(s: "\\\\server\\share\\a", "\\\\server\\share", true);
+        t!(s: "\\\\server\\share", "\\\\server\\share", false);
+        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b", true);
+        t!(s: "\\\\?\\a\\b", "\\\\?\\a", true);
+        t!(s: "\\\\?\\a", "\\\\?\\a", false);
+        t!(s: "\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true);
+        t!(s: "\\\\?\\C:\\a", "\\\\?\\C:\\", true);
+        t!(s: "\\\\?\\C:\\", "\\\\?\\C:\\", false);
+        t!(s: "\\\\?\\UNC\\server\\share\\a\\b", "\\\\?\\UNC\\server\\share\\a", true);
+        t!(s: "\\\\?\\UNC\\server\\share\\a", "\\\\?\\UNC\\server\\share", true);
+        t!(s: "\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share", false);
+        t!(s: "\\\\.\\a\\b\\c", "\\\\.\\a\\b", true);
+        t!(s: "\\\\.\\a\\b", "\\\\.\\a", true);
+        t!(s: "\\\\.\\a", "\\\\.\\a", false);
+
+        t!(s: "\\\\?\\a\\b\\", "\\\\?\\a", true);
+    }
+
+    #[test]
+    fn test_root_path() {
+        assert_eq!(Path::new("a\\b\\c").root_path(),  None);
+        assert_eq!(Path::new("\\a\\b\\c").root_path(), Some(Path::new("\\")));
+        assert_eq!(Path::new("C:a").root_path(), Some(Path::new("C:")));
+        assert_eq!(Path::new("C:\\a").root_path(), Some(Path::new("C:\\")));
+        assert_eq!(Path::new("\\\\a\\b\\c").root_path(), Some(Path::new("\\\\a\\b")));
+        assert_eq!(Path::new("\\\\?\\a\\b").root_path(), Some(Path::new("\\\\?\\a")));
+        assert_eq!(Path::new("\\\\?\\C:\\a").root_path(), Some(Path::new("\\\\?\\C:\\")));
+        assert_eq!(Path::new("\\\\?\\UNC\\a\\b\\c").root_path(),
+                Some(Path::new("\\\\?\\UNC\\a\\b")));
+        assert_eq!(Path::new("\\\\.\\a\\b").root_path(), Some(Path::new("\\\\.\\a")));
+    }
+
+    #[test]
+    fn test_join() {
+        t!(s: Path::new("a\\b\\c").join(".."), "a\\b");
+        t!(s: Path::new("\\a\\b\\c").join("d"), "\\a\\b\\c\\d");
+        t!(s: Path::new("a\\b").join("c\\d"), "a\\b\\c\\d");
+        t!(s: Path::new("a\\b").join("\\c\\d"), "\\c\\d");
+        t!(s: Path::new(".").join("a\\b"), "a\\b");
+        t!(s: Path::new("\\").join("a\\b"), "\\a\\b");
+        t!(v: Path::new(b"a\\b\\c").join(b".."), b"a\\b");
+        t!(v: Path::new(b"\\a\\b\\c").join(b"d"), b"\\a\\b\\c\\d");
+        // full join testing is covered under test_push_path, so no need for
+        // the full set of prefix tests
+    }
+
+    #[test]
+    fn test_join_path() {
+        macro_rules! t {
+            (s: $path:expr, $join:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let join = Path::new($join);
+                    let res = path.join(&join);
+                    assert_eq!(res.as_str(), Some($exp));
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", "..", "a\\b");
+        t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
+        t!(s: "a\\b", "c\\d", "a\\b\\c\\d");
+        t!(s: "a\\b", "\\c\\d", "\\c\\d");
+        t!(s: ".", "a\\b", "a\\b");
+        t!(s: "\\", "a\\b", "\\a\\b");
+        // join is implemented using push, so there's no need for
+        // the full set of prefix tests
+    }
+
+    #[test]
+    fn test_join_many() {
+        macro_rules! t {
+            (s: $path:expr, $join:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let res = path.join_many(&$join);
+                    assert_eq!(res.as_str(), Some($exp));
+                }
+            );
+            (v: $path:expr, $join:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let res = path.join_many(&$join);
+                    assert_eq!(res.as_vec(), $exp);
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
+        t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d");
+        t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
+        t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e");
+        t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e");
+        t!(v: b"a\\b\\c", [b"d".to_vec(), b"e".to_vec()],
+           b"a\\b\\c\\d\\e");
+    }
+
+    #[test]
+    fn test_with_helpers() {
+        macro_rules! t {
+            (s: $path:expr, $op:ident, $arg:expr, $res:expr) => (
+                {
+                    let pstr = $path;
+                    let path = Path::new(pstr);
+                    let arg = $arg;
+                    let res = path.$op(arg);
+                    let exp = Path::new($res);
+                    assert_eq!(res, exp);
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", with_filename, "d", "a\\b\\d");
+        t!(s: ".", with_filename, "foo", "foo");
+        t!(s: "\\a\\b\\c", with_filename, "d", "\\a\\b\\d");
+        t!(s: "\\", with_filename, "foo", "\\foo");
+        t!(s: "\\a", with_filename, "foo", "\\foo");
+        t!(s: "foo", with_filename, "bar", "bar");
+        t!(s: "\\", with_filename, "foo\\", "\\foo");
+        t!(s: "\\a", with_filename, "foo\\", "\\foo");
+        t!(s: "a\\b\\c", with_filename, "", "a\\b");
+        t!(s: "a\\b\\c", with_filename, ".", "a\\b");
+        t!(s: "a\\b\\c", with_filename, "..", "a");
+        t!(s: "\\a", with_filename, "", "\\");
+        t!(s: "foo", with_filename, "", ".");
+        t!(s: "a\\b\\c", with_filename, "d\\e", "a\\b\\d\\e");
+        t!(s: "a\\b\\c", with_filename, "\\d", "a\\b\\d");
+        t!(s: "..", with_filename, "foo", "..\\foo");
+        t!(s: "..\\..", with_filename, "foo", "..\\..\\foo");
+        t!(s: "..", with_filename, "", "..");
+        t!(s: "..\\..", with_filename, "", "..\\..");
+        t!(s: "C:\\foo\\bar", with_filename, "baz", "C:\\foo\\baz");
+        t!(s: "C:\\foo", with_filename, "bar", "C:\\bar");
+        t!(s: "C:\\", with_filename, "foo", "C:\\foo");
+        t!(s: "C:foo\\bar", with_filename, "baz", "C:foo\\baz");
+        t!(s: "C:foo", with_filename, "bar", "C:bar");
+        t!(s: "C:", with_filename, "foo", "C:foo");
+        t!(s: "C:\\foo", with_filename, "", "C:\\");
+        t!(s: "C:foo", with_filename, "", "C:");
+        t!(s: "C:\\foo\\bar", with_filename, "..", "C:\\");
+        t!(s: "C:\\foo", with_filename, "..", "C:\\");
+        t!(s: "C:\\", with_filename, "..", "C:\\");
+        t!(s: "C:foo\\bar", with_filename, "..", "C:");
+        t!(s: "C:foo", with_filename, "..", "C:..");
+        t!(s: "C:", with_filename, "..", "C:..");
+        t!(s: "\\\\server\\share\\foo", with_filename, "bar", "\\\\server\\share\\bar");
+        t!(s: "\\\\server\\share", with_filename, "foo", "\\\\server\\share\\foo");
+        t!(s: "\\\\server\\share\\foo", with_filename, "", "\\\\server\\share");
+        t!(s: "\\\\server\\share", with_filename, "", "\\\\server\\share");
+        t!(s: "\\\\server\\share\\foo", with_filename, "..", "\\\\server\\share");
+        t!(s: "\\\\server\\share", with_filename, "..", "\\\\server\\share");
+        t!(s: "\\\\?\\C:\\foo\\bar", with_filename, "baz", "\\\\?\\C:\\foo\\baz");
+        t!(s: "\\\\?\\C:\\foo", with_filename, "bar", "\\\\?\\C:\\bar");
+        t!(s: "\\\\?\\C:\\", with_filename, "foo", "\\\\?\\C:\\foo");
+        t!(s: "\\\\?\\C:\\foo", with_filename, "..", "\\\\?\\C:\\..");
+        t!(s: "\\\\?\\foo\\bar", with_filename, "baz", "\\\\?\\foo\\baz");
+        t!(s: "\\\\?\\foo", with_filename, "bar", "\\\\?\\foo\\bar");
+        t!(s: "\\\\?\\", with_filename, "foo", "\\\\?\\\\foo");
+        t!(s: "\\\\?\\foo\\bar", with_filename, "..", "\\\\?\\foo\\..");
+        t!(s: "\\\\.\\foo\\bar", with_filename, "baz", "\\\\.\\foo\\baz");
+        t!(s: "\\\\.\\foo", with_filename, "bar", "\\\\.\\foo\\bar");
+        t!(s: "\\\\.\\foo\\bar", with_filename, "..", "\\\\.\\foo\\..");
+
+        t!(s: "hi\\there.txt", with_extension, "exe", "hi\\there.exe");
+        t!(s: "hi\\there.txt", with_extension, "", "hi\\there");
+        t!(s: "hi\\there.txt", with_extension, ".", "hi\\there..");
+        t!(s: "hi\\there.txt", with_extension, "..", "hi\\there...");
+        t!(s: "hi\\there", with_extension, "txt", "hi\\there.txt");
+        t!(s: "hi\\there", with_extension, ".", "hi\\there..");
+        t!(s: "hi\\there", with_extension, "..", "hi\\there...");
+        t!(s: "hi\\there.", with_extension, "txt", "hi\\there.txt");
+        t!(s: "hi\\.foo", with_extension, "txt", "hi\\.foo.txt");
+        t!(s: "hi\\there.txt", with_extension, ".foo", "hi\\there..foo");
+        t!(s: "\\", with_extension, "txt", "\\");
+        t!(s: "\\", with_extension, ".", "\\");
+        t!(s: "\\", with_extension, "..", "\\");
+        t!(s: ".", with_extension, "txt", ".");
+        // extension setter calls filename setter internally, no need for extended tests
+    }
+
+    #[test]
+    fn test_setters() {
+        macro_rules! t {
+            (s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
+                {
+                    let path = $path;
+                    let arg = $arg;
+                    let mut p1 = Path::new(path);
+                    p1.$set(arg);
+                    let p2 = Path::new(path);
+                    assert_eq!(p1, p2.$with(arg));
+                }
+            );
+            (v: $path:expr, $set:ident, $with:ident, $arg:expr) => (
+                {
+                    let path = $path;
+                    let arg = $arg;
+                    let mut p1 = Path::new(path);
+                    p1.$set(arg);
+                    let p2 = Path::new(path);
+                    assert_eq!(p1, p2.$with(arg));
+                }
+            )
+        }
+
+        t!(v: b"a\\b\\c", set_filename, with_filename, b"d");
+        t!(v: b"\\", set_filename, with_filename, b"foo");
+        t!(s: "a\\b\\c", set_filename, with_filename, "d");
+        t!(s: "\\", set_filename, with_filename, "foo");
+        t!(s: ".", set_filename, with_filename, "foo");
+        t!(s: "a\\b", set_filename, with_filename, "");
+        t!(s: "a", set_filename, with_filename, "");
+
+        t!(v: b"hi\\there.txt", set_extension, with_extension, b"exe");
+        t!(s: "hi\\there.txt", set_extension, with_extension, "exe");
+        t!(s: "hi\\there.", set_extension, with_extension, "txt");
+        t!(s: "hi\\there", set_extension, with_extension, "txt");
+        t!(s: "hi\\there.txt", set_extension, with_extension, "");
+        t!(s: "hi\\there", set_extension, with_extension, "");
+        t!(s: ".", set_extension, with_extension, "txt");
+
+        // with_ helpers use the setter internally, so the tests for the with_ helpers
+        // will suffice. No need for the full set of prefix tests.
+    }
+
+    #[test]
+    fn test_getters() {
+        macro_rules! t {
+            (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
+                {
+                    let path = $path;
+                    assert_eq!(path.filename_str(), $filename);
+                    assert_eq!(path.dirname_str(), $dirname);
+                    assert_eq!(path.filestem_str(), $filestem);
+                    assert_eq!(path.extension_str(), $ext);
+                }
+            );
+            (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
+                {
+                    let path = $path;
+                    assert_eq!(path.filename(), $filename);
+                    assert_eq!(path.dirname(), $dirname);
+                    assert_eq!(path.filestem(), $filestem);
+                    assert_eq!(path.extension(), $ext);
+                }
+            )
+        }
+
+        t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None);
+        t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
+        t!(s: Path::new("."), None, Some("."), None, None);
+        t!(s: Path::new("\\"), None, Some("\\"), None, None);
+        t!(s: Path::new(".."), None, Some(".."), None, None);
+        t!(s: Path::new("..\\.."), None, Some("..\\.."), None, None);
+        t!(s: Path::new("hi\\there.txt"), Some("there.txt"), Some("hi"),
+              Some("there"), Some("txt"));
+        t!(s: Path::new("hi\\there"), Some("there"), Some("hi"), Some("there"), None);
+        t!(s: Path::new("hi\\there."), Some("there."), Some("hi"),
+              Some("there"), Some(""));
+        t!(s: Path::new("hi\\.there"), Some(".there"), Some("hi"), Some(".there"), None);
+        t!(s: Path::new("hi\\..there"), Some("..there"), Some("hi"),
+              Some("."), Some("there"));
+
+        // these are already tested in test_components, so no need for extended tests
+    }
+
+    #[test]
+    fn test_dir_path() {
+        t!(s: Path::new("hi\\there").dir_path(), "hi");
+        t!(s: Path::new("hi").dir_path(), ".");
+        t!(s: Path::new("\\hi").dir_path(), "\\");
+        t!(s: Path::new("\\").dir_path(), "\\");
+        t!(s: Path::new("..").dir_path(), "..");
+        t!(s: Path::new("..\\..").dir_path(), "..\\..");
+
+        // dir_path is just dirname interpreted as a path.
+        // No need for extended tests
+    }
+
+    #[test]
+    fn test_is_absolute() {
+        macro_rules! t {
+            ($path:expr, $abs:expr, $vol:expr, $cwd:expr, $rel:expr) => (
+                {
+                    let path = Path::new($path);
+                    let (abs, vol, cwd, rel) = ($abs, $vol, $cwd, $rel);
+                    assert_eq!(path.is_absolute(), abs);
+                    assert_eq!(is_vol_relative(&path), vol);
+                    assert_eq!(is_cwd_relative(&path), cwd);
+                    assert_eq!(path.is_relative(), rel);
+                }
+            )
+        }
+        t!("a\\b\\c", false, false, false, true);
+        t!("\\a\\b\\c", false, true, false, false);
+        t!("a", false, false, false, true);
+        t!("\\a", false, true, false, false);
+        t!(".", false, false, false, true);
+        t!("\\", false, true, false, false);
+        t!("..", false, false, false, true);
+        t!("..\\..", false, false, false, true);
+        t!("C:a\\b.txt", false, false, true, false);
+        t!("C:\\a\\b.txt", true, false, false, false);
+        t!("\\\\server\\share\\a\\b.txt", true, false, false, false);
+        t!("\\\\?\\a\\b\\c.txt", true, false, false, false);
+        t!("\\\\?\\C:\\a\\b.txt", true, false, false, false);
+        t!("\\\\?\\C:a\\b.txt", true, false, false, false); // NB: not equivalent to C:a\b.txt
+        t!("\\\\?\\UNC\\server\\share\\a\\b.txt", true, false, false, false);
+        t!("\\\\.\\a\\b", true, false, false, false);
+    }
+
+    #[test]
+    fn test_is_ancestor_of() {
+        macro_rules! t {
+            (s: $path:expr, $dest:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let dest = Path::new($dest);
+                    let exp = $exp;
+                    let res = path.is_ancestor_of(&dest);
+                    assert_eq!(res, exp);
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", "a\\b\\c\\d", true);
+        t!(s: "a\\b\\c", "a\\b\\c", true);
+        t!(s: "a\\b\\c", "a\\b", false);
+        t!(s: "\\a\\b\\c", "\\a\\b\\c", true);
+        t!(s: "\\a\\b", "\\a\\b\\c", true);
+        t!(s: "\\a\\b\\c\\d", "\\a\\b\\c", false);
+        t!(s: "\\a\\b", "a\\b\\c", false);
+        t!(s: "a\\b", "\\a\\b\\c", false);
+        t!(s: "a\\b\\c", "a\\b\\d", false);
+        t!(s: "..\\a\\b\\c", "a\\b\\c", false);
+        t!(s: "a\\b\\c", "..\\a\\b\\c", false);
+        t!(s: "a\\b\\c", "a\\b\\cd", false);
+        t!(s: "a\\b\\cd", "a\\b\\c", false);
+        t!(s: "..\\a\\b", "..\\a\\b\\c", true);
+        t!(s: ".", "a\\b", true);
+        t!(s: ".", ".", true);
+        t!(s: "\\", "\\", true);
+        t!(s: "\\", "\\a\\b", true);
+        t!(s: "..", "a\\b", true);
+        t!(s: "..\\..", "a\\b", true);
+        t!(s: "foo\\bar", "foobar", false);
+        t!(s: "foobar", "foo\\bar", false);
+
+        t!(s: "foo", "C:foo", false);
+        t!(s: "C:foo", "foo", false);
+        t!(s: "C:foo", "C:foo\\bar", true);
+        t!(s: "C:foo\\bar", "C:foo", false);
+        t!(s: "C:\\foo", "C:\\foo\\bar", true);
+        t!(s: "C:", "C:", true);
+        t!(s: "C:", "C:\\", false);
+        t!(s: "C:\\", "C:", false);
+        t!(s: "C:\\", "C:\\", true);
+        t!(s: "C:\\foo\\bar", "C:\\foo", false);
+        t!(s: "C:foo\\bar", "C:foo", false);
+        t!(s: "C:\\foo", "\\foo", false);
+        t!(s: "\\foo", "C:\\foo", false);
+        t!(s: "\\\\server\\share\\foo", "\\\\server\\share\\foo\\bar", true);
+        t!(s: "\\\\server\\share", "\\\\server\\share\\foo", true);
+        t!(s: "\\\\server\\share\\foo", "\\\\server\\share", false);
+        t!(s: "C:\\foo", "\\\\server\\share\\foo", false);
+        t!(s: "\\\\server\\share\\foo", "C:\\foo", false);
+        t!(s: "\\\\?\\foo\\bar", "\\\\?\\foo\\bar\\baz", true);
+        t!(s: "\\\\?\\foo\\bar\\baz", "\\\\?\\foo\\bar", false);
+        t!(s: "\\\\?\\foo\\bar", "\\foo\\bar\\baz", false);
+        t!(s: "\\foo\\bar", "\\\\?\\foo\\bar\\baz", false);
+        t!(s: "\\\\?\\C:\\foo\\bar", "\\\\?\\C:\\foo\\bar\\baz", true);
+        t!(s: "\\\\?\\C:\\foo\\bar\\baz", "\\\\?\\C:\\foo\\bar", false);
+        t!(s: "\\\\?\\C:\\", "\\\\?\\C:\\foo", true);
+        t!(s: "\\\\?\\C:", "\\\\?\\C:\\", false); // this is a weird one
+        t!(s: "\\\\?\\C:\\", "\\\\?\\C:", false);
+        t!(s: "\\\\?\\C:\\a", "\\\\?\\c:\\a\\b", true);
+        t!(s: "\\\\?\\c:\\a", "\\\\?\\C:\\a\\b", true);
+        t!(s: "\\\\?\\C:\\a", "\\\\?\\D:\\a\\b", false);
+        t!(s: "\\\\?\\foo", "\\\\?\\foobar", false);
+        t!(s: "\\\\?\\a\\b", "\\\\?\\a\\b\\c", true);
+        t!(s: "\\\\?\\a\\b", "\\\\?\\a\\b\\", true);
+        t!(s: "\\\\?\\a\\b\\", "\\\\?\\a\\b", true);
+        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b", false);
+        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b\\", false);
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b\\c\\d", true);
+        t!(s: "\\\\?\\UNC\\a\\b\\c\\d", "\\\\?\\UNC\\a\\b\\c", false);
+        t!(s: "\\\\?\\UNC\\a\\b", "\\\\?\\UNC\\a\\b\\c", true);
+        t!(s: "\\\\.\\foo\\bar", "\\\\.\\foo\\bar\\baz", true);
+        t!(s: "\\\\.\\foo\\bar\\baz", "\\\\.\\foo\\bar", false);
+        t!(s: "\\\\.\\foo", "\\\\.\\foo\\bar", true);
+        t!(s: "\\\\.\\foo", "\\\\.\\foobar", false);
+
+        t!(s: "\\a\\b", "\\\\?\\a\\b", false);
+        t!(s: "\\\\?\\a\\b", "\\a\\b", false);
+        t!(s: "\\a\\b", "\\\\?\\C:\\a\\b", false);
+        t!(s: "\\\\?\\C:\\a\\b", "\\a\\b", false);
+        t!(s: "Z:\\a\\b", "\\\\?\\z:\\a\\b", true);
+        t!(s: "C:\\a\\b", "\\\\?\\D:\\a\\b", false);
+        t!(s: "a\\b", "\\\\?\\a\\b", false);
+        t!(s: "\\\\?\\a\\b", "a\\b", false);
+        t!(s: "C:\\a\\b", "\\\\?\\C:\\a\\b", true);
+        t!(s: "\\\\?\\C:\\a\\b", "C:\\a\\b", true);
+        t!(s: "C:a\\b", "\\\\?\\C:\\a\\b", false);
+        t!(s: "C:a\\b", "\\\\?\\C:a\\b", false);
+        t!(s: "\\\\?\\C:\\a\\b", "C:a\\b", false);
+        t!(s: "\\\\?\\C:a\\b", "C:a\\b", false);
+        t!(s: "C:\\a\\b", "\\\\?\\C:\\a\\b\\", true);
+        t!(s: "\\\\?\\C:\\a\\b\\", "C:\\a\\b", true);
+        t!(s: "\\\\a\\b\\c", "\\\\?\\UNC\\a\\b\\c", true);
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\a\\b\\c", true);
+    }
+
+    #[test]
+    fn test_ends_with_path() {
+        macro_rules! t {
+            (s: $path:expr, $child:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let child = Path::new($child);
+                    assert_eq!(path.ends_with_path(&child), $exp);
+                }
+            );
+        }
+
+        t!(s: "a\\b\\c", "c", true);
+        t!(s: "a\\b\\c", "d", false);
+        t!(s: "foo\\bar\\quux", "bar", false);
+        t!(s: "foo\\bar\\quux", "barquux", false);
+        t!(s: "a\\b\\c", "b\\c", true);
+        t!(s: "a\\b\\c", "a\\b\\c", true);
+        t!(s: "a\\b\\c", "foo\\a\\b\\c", false);
+        t!(s: "\\a\\b\\c", "a\\b\\c", true);
+        t!(s: "\\a\\b\\c", "\\a\\b\\c", false); // child must be relative
+        t!(s: "\\a\\b\\c", "foo\\a\\b\\c", false);
+        t!(s: "a\\b\\c", "", false);
+        t!(s: "", "", true);
+        t!(s: "\\a\\b\\c", "d\\e\\f", false);
+        t!(s: "a\\b\\c", "a\\b", false);
+        t!(s: "a\\b\\c", "b", false);
+        t!(s: "C:\\a\\b", "b", true);
+        t!(s: "C:\\a\\b", "C:b", false);
+        t!(s: "C:\\a\\b", "C:a\\b", false);
+    }
+
+    #[test]
+    fn test_path_relative_from() {
+        macro_rules! t {
+            (s: $path:expr, $other:expr, $exp:expr) => (
+                {
+                    assert_eq!(Path::new($path).path_relative_from(&Path::new($other))
+                              .as_ref().and_then(|x| x.as_str()), $exp);
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", "a\\b", Some("c"));
+        t!(s: "a\\b\\c", "a\\b\\d", Some("..\\c"));
+        t!(s: "a\\b\\c", "a\\b\\c\\d", Some(".."));
+        t!(s: "a\\b\\c", "a\\b\\c", Some("."));
+        t!(s: "a\\b\\c", "a\\b\\c\\d\\e", Some("..\\.."));
+        t!(s: "a\\b\\c", "a\\d\\e", Some("..\\..\\b\\c"));
+        t!(s: "a\\b\\c", "d\\e\\f", Some("..\\..\\..\\a\\b\\c"));
+        t!(s: "a\\b\\c", "\\a\\b\\c", None);
+        t!(s: "\\a\\b\\c", "a\\b\\c", Some("\\a\\b\\c"));
+        t!(s: "\\a\\b\\c", "\\a\\b\\c\\d", Some(".."));
+        t!(s: "\\a\\b\\c", "\\a\\b", Some("c"));
+        t!(s: "\\a\\b\\c", "\\a\\b\\c\\d\\e", Some("..\\.."));
+        t!(s: "\\a\\b\\c", "\\a\\d\\e", Some("..\\..\\b\\c"));
+        t!(s: "\\a\\b\\c", "\\d\\e\\f", Some("..\\..\\..\\a\\b\\c"));
+        t!(s: "hi\\there.txt", "hi\\there", Some("..\\there.txt"));
+        t!(s: ".", "a", Some(".."));
+        t!(s: ".", "a\\b", Some("..\\.."));
+        t!(s: ".", ".", Some("."));
+        t!(s: "a", ".", Some("a"));
+        t!(s: "a\\b", ".", Some("a\\b"));
+        t!(s: "..", ".", Some(".."));
+        t!(s: "a\\b\\c", "a\\b\\c", Some("."));
+        t!(s: "\\a\\b\\c", "\\a\\b\\c", Some("."));
+        t!(s: "\\", "\\", Some("."));
+        t!(s: "\\", ".", Some("\\"));
+        t!(s: "..\\..\\a", "b", Some("..\\..\\..\\a"));
+        t!(s: "a", "..\\..\\b", None);
+        t!(s: "..\\..\\a", "..\\..\\b", Some("..\\a"));
+        t!(s: "..\\..\\a", "..\\..\\a\\b", Some(".."));
+        t!(s: "..\\..\\a\\b", "..\\..\\a", Some("b"));
+
+        t!(s: "C:a\\b\\c", "C:a\\b", Some("c"));
+        t!(s: "C:a\\b", "C:a\\b\\c", Some(".."));
+        t!(s: "C:" ,"C:a\\b", Some("..\\.."));
+        t!(s: "C:a\\b", "C:c\\d", Some("..\\..\\a\\b"));
+        t!(s: "C:a\\b", "D:c\\d", Some("C:a\\b"));
+        t!(s: "C:a\\b", "C:..\\c", None);
+        t!(s: "C:..\\a", "C:b\\c", Some("..\\..\\..\\a"));
+        t!(s: "C:\\a\\b\\c", "C:\\a\\b", Some("c"));
+        t!(s: "C:\\a\\b", "C:\\a\\b\\c", Some(".."));
+        t!(s: "C:\\", "C:\\a\\b", Some("..\\.."));
+        t!(s: "C:\\a\\b", "C:\\c\\d", Some("..\\..\\a\\b"));
+        t!(s: "C:\\a\\b", "C:a\\b", Some("C:\\a\\b"));
+        t!(s: "C:a\\b", "C:\\a\\b", None);
+        t!(s: "\\a\\b", "C:\\a\\b", None);
+        t!(s: "\\a\\b", "C:a\\b", None);
+        t!(s: "a\\b", "C:\\a\\b", None);
+        t!(s: "a\\b", "C:a\\b", None);
+
+        t!(s: "\\\\a\\b\\c", "\\\\a\\b", Some("c"));
+        t!(s: "\\\\a\\b", "\\\\a\\b\\c", Some(".."));
+        t!(s: "\\\\a\\b\\c\\e", "\\\\a\\b\\c\\d", Some("..\\e"));
+        t!(s: "\\\\a\\c\\d", "\\\\a\\b\\d", Some("\\\\a\\c\\d"));
+        t!(s: "\\\\b\\c\\d", "\\\\a\\c\\d", Some("\\\\b\\c\\d"));
+        t!(s: "\\\\a\\b\\c", "\\d\\e", Some("\\\\a\\b\\c"));
+        t!(s: "\\d\\e", "\\\\a\\b\\c", None);
+        t!(s: "d\\e", "\\\\a\\b\\c", None);
+        t!(s: "C:\\a\\b\\c", "\\\\a\\b\\c", Some("C:\\a\\b\\c"));
+        t!(s: "C:\\c", "\\\\a\\b\\c", Some("C:\\c"));
+
+        t!(s: "\\\\?\\a\\b", "\\a\\b", Some("\\\\?\\a\\b"));
+        t!(s: "\\\\?\\a\\b", "a\\b", Some("\\\\?\\a\\b"));
+        t!(s: "\\\\?\\a\\b", "\\b", Some("\\\\?\\a\\b"));
+        t!(s: "\\\\?\\a\\b", "b", Some("\\\\?\\a\\b"));
+        t!(s: "\\\\?\\a\\b", "\\\\?\\a\\b\\c", Some(".."));
+        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b", Some("c"));
+        t!(s: "\\\\?\\a\\b", "\\\\?\\c\\d", Some("\\\\?\\a\\b"));
+        t!(s: "\\\\?\\a", "\\\\?\\b", Some("\\\\?\\a"));
+
+        t!(s: "\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", Some("b"));
+        t!(s: "\\\\?\\C:\\a", "\\\\?\\C:\\a\\b", Some(".."));
+        t!(s: "\\\\?\\C:\\a", "\\\\?\\C:\\b", Some("..\\a"));
+        t!(s: "\\\\?\\C:\\a", "\\\\?\\D:\\a", Some("\\\\?\\C:\\a"));
+        t!(s: "\\\\?\\C:\\a\\b", "\\\\?\\c:\\a", Some("b"));
+        t!(s: "\\\\?\\C:\\a\\b", "C:\\a", Some("b"));
+        t!(s: "\\\\?\\C:\\a", "C:\\a\\b", Some(".."));
+        t!(s: "C:\\a\\b", "\\\\?\\C:\\a", Some("b"));
+        t!(s: "C:\\a", "\\\\?\\C:\\a\\b", Some(".."));
+        t!(s: "\\\\?\\C:\\a", "D:\\a", Some("\\\\?\\C:\\a"));
+        t!(s: "\\\\?\\c:\\a\\b", "C:\\a", Some("b"));
+        t!(s: "\\\\?\\C:\\a\\b", "C:a\\b", Some("\\\\?\\C:\\a\\b"));
+        t!(s: "\\\\?\\C:\\a\\.\\b", "C:\\a", Some("\\\\?\\C:\\a\\.\\b"));
+        t!(s: "\\\\?\\C:\\a\\b/c", "C:\\a", Some("\\\\?\\C:\\a\\b/c"));
+        t!(s: "\\\\?\\C:\\a\\..\\b", "C:\\a", Some("\\\\?\\C:\\a\\..\\b"));
+        t!(s: "C:a\\b", "\\\\?\\C:\\a\\b", None);
+        t!(s: "\\\\?\\C:\\a\\.\\b", "\\\\?\\C:\\a", Some("\\\\?\\C:\\a\\.\\b"));
+        t!(s: "\\\\?\\C:\\a\\b/c", "\\\\?\\C:\\a", Some("\\\\?\\C:\\a\\b/c"));
+        t!(s: "\\\\?\\C:\\a\\..\\b", "\\\\?\\C:\\a", Some("\\\\?\\C:\\a\\..\\b"));
+        t!(s: "\\\\?\\C:\\a\\b\\", "\\\\?\\C:\\a", Some("b"));
+        t!(s: "\\\\?\\C:\\.\\b", "\\\\?\\C:\\.", Some("b"));
+        t!(s: "C:\\b", "\\\\?\\C:\\.", Some("..\\b"));
+        t!(s: "\\\\?\\a\\.\\b\\c", "\\\\?\\a\\.\\b", Some("c"));
+        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\.\\d", Some("..\\..\\b\\c"));
+        t!(s: "\\\\?\\a\\..\\b", "\\\\?\\a\\..", Some("b"));
+        t!(s: "\\\\?\\a\\b\\..", "\\\\?\\a\\b", Some("\\\\?\\a\\b\\.."));
+        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\..\\b", Some("..\\..\\b\\c"));
+
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b", Some("c"));
+        t!(s: "\\\\?\\UNC\\a\\b", "\\\\?\\UNC\\a\\b\\c", Some(".."));
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\c\\d", Some("\\\\?\\UNC\\a\\b\\c"));
+        t!(s: "\\\\?\\UNC\\b\\c\\d", "\\\\?\\UNC\\a\\c\\d", Some("\\\\?\\UNC\\b\\c\\d"));
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\a\\b\\c", Some("\\\\?\\UNC\\a\\b\\c"));
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\C:\\a\\b\\c", Some("\\\\?\\UNC\\a\\b\\c"));
+        t!(s: "\\\\?\\UNC\\a\\b\\c/d", "\\\\?\\UNC\\a\\b", Some("\\\\?\\UNC\\a\\b\\c/d"));
+        t!(s: "\\\\?\\UNC\\a\\b\\.", "\\\\?\\UNC\\a\\b", Some("\\\\?\\UNC\\a\\b\\."));
+        t!(s: "\\\\?\\UNC\\a\\b\\..", "\\\\?\\UNC\\a\\b", Some("\\\\?\\UNC\\a\\b\\.."));
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\a\\b", Some("c"));
+        t!(s: "\\\\?\\UNC\\a\\b", "\\\\a\\b\\c", Some(".."));
+        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\a\\c\\d", Some("\\\\?\\UNC\\a\\b\\c"));
+        t!(s: "\\\\?\\UNC\\b\\c\\d", "\\\\a\\c\\d", Some("\\\\?\\UNC\\b\\c\\d"));
+        t!(s: "\\\\?\\UNC\\a\\b\\.", "\\\\a\\b", Some("\\\\?\\UNC\\a\\b\\."));
+        t!(s: "\\\\?\\UNC\\a\\b\\c/d", "\\\\a\\b", Some("\\\\?\\UNC\\a\\b\\c/d"));
+        t!(s: "\\\\?\\UNC\\a\\b\\..", "\\\\a\\b", Some("\\\\?\\UNC\\a\\b\\.."));
+        t!(s: "\\\\a\\b\\c", "\\\\?\\UNC\\a\\b", Some("c"));
+        t!(s: "\\\\a\\b\\c", "\\\\?\\UNC\\a\\c\\d", Some("\\\\a\\b\\c"));
+    }
+
+    #[test]
+    fn test_str_components() {
+        macro_rules! t {
+            (s: $path:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let comps = path.str_components().map(|x|x.unwrap())
+                                .collect::<Vec<&str>>();
+                    let exp: &[&str] = &$exp;
+                    assert_eq!(comps, exp);
+                    let comps = path.str_components().rev().map(|x|x.unwrap())
+                                .collect::<Vec<&str>>();
+                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&str>>();
+                    assert_eq!(comps, exp);
+                }
+            );
+        }
+
+        t!(s: b"a\\b\\c", ["a", "b", "c"]);
+        t!(s: "a\\b\\c", ["a", "b", "c"]);
+        t!(s: "a\\b\\d", ["a", "b", "d"]);
+        t!(s: "a\\b\\cd", ["a", "b", "cd"]);
+        t!(s: "\\a\\b\\c", ["a", "b", "c"]);
+        t!(s: "a", ["a"]);
+        t!(s: "\\a", ["a"]);
+        t!(s: "\\", []);
+        t!(s: ".", ["."]);
+        t!(s: "..", [".."]);
+        t!(s: "..\\..", ["..", ".."]);
+        t!(s: "..\\..\\foo", ["..", "..", "foo"]);
+        t!(s: "C:foo\\bar", ["foo", "bar"]);
+        t!(s: "C:foo", ["foo"]);
+        t!(s: "C:", []);
+        t!(s: "C:\\foo\\bar", ["foo", "bar"]);
+        t!(s: "C:\\foo", ["foo"]);
+        t!(s: "C:\\", []);
+        t!(s: "\\\\server\\share\\foo\\bar", ["foo", "bar"]);
+        t!(s: "\\\\server\\share\\foo", ["foo"]);
+        t!(s: "\\\\server\\share", []);
+        t!(s: "\\\\?\\foo\\bar\\baz", ["bar", "baz"]);
+        t!(s: "\\\\?\\foo\\bar", ["bar"]);
+        t!(s: "\\\\?\\foo", []);
+        t!(s: "\\\\?\\", []);
+        t!(s: "\\\\?\\a\\b", ["b"]);
+        t!(s: "\\\\?\\a\\b\\", ["b"]);
+        t!(s: "\\\\?\\foo\\bar\\\\baz", ["bar", "", "baz"]);
+        t!(s: "\\\\?\\C:\\foo\\bar", ["foo", "bar"]);
+        t!(s: "\\\\?\\C:\\foo", ["foo"]);
+        t!(s: "\\\\?\\C:\\", []);
+        t!(s: "\\\\?\\C:\\foo\\", ["foo"]);
+        t!(s: "\\\\?\\UNC\\server\\share\\foo\\bar", ["foo", "bar"]);
+        t!(s: "\\\\?\\UNC\\server\\share\\foo", ["foo"]);
+        t!(s: "\\\\?\\UNC\\server\\share", []);
+        t!(s: "\\\\.\\foo\\bar\\baz", ["bar", "baz"]);
+        t!(s: "\\\\.\\foo\\bar", ["bar"]);
+        t!(s: "\\\\.\\foo", []);
+    }
+
+    #[test]
+    fn test_components_iter() {
+        macro_rules! t {
+            (s: $path:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let comps = path.components().collect::<Vec<&[u8]>>();
+                    let exp: &[&[u8]] = &$exp;
+                    assert_eq!(comps, exp);
+                    let comps = path.components().rev().collect::<Vec<&[u8]>>();
+                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
+                    assert_eq!(comps, exp);
+                }
+            )
+        }
+
+        t!(s: "a\\b\\c", [b"a", b"b", b"c"]);
+        t!(s: ".", [b"."]);
+        // since this is really a wrapper around str_components, those tests suffice
+    }
+
+    #[test]
+    fn test_make_non_verbatim() {
+        macro_rules! t {
+            ($path:expr, $exp:expr) => (
+                {
+                    let path = Path::new($path);
+                    let exp: Option<&str> = $exp;
+                    let exp = exp.map(|s| Path::new(s));
+                    assert_eq!(make_non_verbatim(&path), exp);
+                }
+            )
+        }
+
+        t!(r"\a\b\c", Some(r"\a\b\c"));
+        t!(r"a\b\c", Some(r"a\b\c"));
+        t!(r"C:\a\b\c", Some(r"C:\a\b\c"));
+        t!(r"C:a\b\c", Some(r"C:a\b\c"));
+        t!(r"\\server\share\foo", Some(r"\\server\share\foo"));
+        t!(r"\\.\foo", None);
+        t!(r"\\?\foo", None);
+        t!(r"\\?\C:", None);
+        t!(r"\\?\C:foo", None);
+        t!(r"\\?\C:\", Some(r"C:\"));
+        t!(r"\\?\C:\foo", Some(r"C:\foo"));
+        t!(r"\\?\C:\foo\bar\baz", Some(r"C:\foo\bar\baz"));
+        t!(r"\\?\C:\foo\.\bar\baz", None);
+        t!(r"\\?\C:\foo\bar\..\baz", None);
+        t!(r"\\?\C:\foo\bar\..", None);
+        t!(r"\\?\UNC\server\share\foo", Some(r"\\server\share\foo"));
+        t!(r"\\?\UNC\server\share", Some(r"\\server\share"));
+        t!(r"\\?\UNC\server", None);
+        t!(r"\\?\UNC\server\", None);
+    }
+}
index d92f361af0bf24508fe18e9e4b11d5ed30aa5299..36122b16ea078115b9ae204b9dd0c88bd36fde5a 100644 (file)
@@ -48,7 +48,7 @@
 use ops::{Drop, FnOnce};
 use option::Option::{Some, None};
 use option::Option;
-use path::{Path, GenericPath, BytesContainer};
+use old_path::{Path, GenericPath, BytesContainer};
 use ptr::PtrExt;
 use ptr;
 use result::Result::{Err, Ok};
@@ -267,7 +267,7 @@ pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
 ///
 /// ```rust
 /// use std::os;
-/// use std::path::Path;
+/// use std::old_path::Path;
 ///
 /// let key = "PATH";
 /// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths);
@@ -470,7 +470,7 @@ fn lookup() -> Path {
 /// # Example
 /// ```rust
 /// use std::os;
-/// use std::path::Path;
+/// use std::old_path::Path;
 ///
 /// // Assume we're in a path like /home/someuser
 /// let rel_path = Path::new("..");
@@ -500,7 +500,7 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
 /// # Example
 /// ```rust
 /// use std::os;
-/// use std::path::Path;
+/// use std::old_path::Path;
 ///
 /// let root = Path::new("/");
 /// assert!(os::change_dir(&root).is_ok());
diff --git a/src/libstd/path/mod.rs b/src/libstd/path/mod.rs
deleted file mode 100644 (file)
index 0d80258..0000000
+++ /dev/null
@@ -1,923 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Cross-platform path support
-//!
-//! This module implements support for two flavors of paths. `PosixPath` represents a path on any
-//! unix-like system, whereas `WindowsPath` represents a path on Windows. This module also exposes
-//! a typedef `Path` which is equal to the appropriate platform-specific path variant.
-//!
-//! Both `PosixPath` and `WindowsPath` implement a trait `GenericPath`, which contains the set of
-//! methods that behave the same for both paths. They each also implement some methods that could
-//! not be expressed in `GenericPath`, yet behave identically for both path flavors, such as
-//! `.components()`.
-//!
-//! The three main design goals of this module are 1) to avoid unnecessary allocation, 2) to behave
-//! the same regardless of which flavor of path is being used, and 3) to support paths that cannot
-//! be represented in UTF-8 (as Linux has no restriction on paths beyond disallowing NUL).
-//!
-//! ## Usage
-//!
-//! Usage of this module is fairly straightforward. Unless writing platform-specific code, `Path`
-//! should be used to refer to the platform-native path.
-//!
-//! Creation of a path is typically done with either `Path::new(some_str)` or
-//! `Path::new(some_vec)`. This path can be modified with `.push()` and `.pop()` (and other
-//! setters). The resulting Path can either be passed to another API that expects a path, or can be
-//! turned into a `&[u8]` with `.as_vec()` or a `Option<&str>` with `.as_str()`. Similarly,
-//! attributes of the path can be queried with methods such as `.filename()`. There are also
-//! methods that return a new path instead of modifying the receiver, such as `.join()` or
-//! `.dir_path()`.
-//!
-//! Paths are always kept in normalized form. This means that creating the path
-//! `Path::new("a/b/../c")` will return the path `a/c`. Similarly any attempt to mutate the path
-//! will always leave it in normalized form.
-//!
-//! When rendering a path to some form of output, there is a method `.display()` which is
-//! compatible with the `format!()` parameter `{}`. This will render the path as a string,
-//! replacing all non-utf8 sequences with the Replacement Character (U+FFFD). As such it is not
-//! suitable for passing to any API that actually operates on the path; it is only intended for
-//! display.
-//!
-//! ## Example
-//!
-//! ```rust
-//! use std::old_io::fs::PathExtensions;
-//!
-//! let mut path = Path::new("/tmp/path");
-//! println!("path: {}", path.display());
-//! path.set_filename("foo");
-//! path.push("bar");
-//! println!("new path: {}", path.display());
-//! println!("path exists: {}", path.exists());
-//! ```
-
-#![unstable(feature = "path")]
-
-use core::marker::Sized;
-use ffi::CString;
-use clone::Clone;
-use fmt;
-use iter::IteratorExt;
-use option::Option;
-use option::Option::{None, Some};
-use str;
-use str::StrExt;
-use string::{String, CowString};
-use slice::SliceExt;
-use vec::Vec;
-
-/// Typedef for POSIX file paths.
-/// See `posix::Path` for more info.
-pub use self::posix::Path as PosixPath;
-
-/// Typedef for Windows file paths.
-/// See `windows::Path` for more info.
-pub use self::windows::Path as WindowsPath;
-
-/// Typedef for the platform-native path type
-#[cfg(unix)]
-pub use self::posix::Path as Path;
-/// Typedef for the platform-native path type
-#[cfg(windows)]
-pub use self::windows::Path as Path;
-
-/// Typedef for the platform-native component iterator
-#[cfg(unix)]
-pub use self::posix::Components as Components;
-/// Typedef for the platform-native component iterator
-#[cfg(windows)]
-pub use self::windows::Components as Components;
-
-/// Typedef for the platform-native str component iterator
-#[cfg(unix)]
-pub use self::posix::StrComponents as StrComponents;
-/// Typedef for the platform-native str component iterator
-#[cfg(windows)]
-pub use self::windows::StrComponents as StrComponents;
-
-/// Alias for the platform-native separator character.
-#[cfg(unix)]
-pub use self::posix::SEP as SEP;
-/// Alias for the platform-native separator character.
-#[cfg(windows)]
-pub use self::windows::SEP as SEP;
-
-/// Alias for the platform-native separator byte.
-#[cfg(unix)]
-pub use self::posix::SEP_BYTE as SEP_BYTE;
-/// Alias for the platform-native separator byte.
-#[cfg(windows)]
-pub use self::windows::SEP_BYTE as SEP_BYTE;
-
-/// Typedef for the platform-native separator char func
-#[cfg(unix)]
-pub use self::posix::is_sep as is_sep;
-/// Typedef for the platform-native separator char func
-#[cfg(windows)]
-pub use self::windows::is_sep as is_sep;
-/// Typedef for the platform-native separator byte func
-#[cfg(unix)]
-pub use self::posix::is_sep_byte as is_sep_byte;
-/// Typedef for the platform-native separator byte func
-#[cfg(windows)]
-pub use self::windows::is_sep_byte as is_sep_byte;
-
-pub mod posix;
-pub mod windows;
-
-/// A trait that represents the generic operations available on paths
-pub trait GenericPath: Clone + GenericPathUnsafe {
-    /// Creates a new Path from a byte vector or string.
-    /// The resulting Path will always be normalized.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let path = Path::new("foo/bar");
-    /// # }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the path contains a NUL.
-    ///
-    /// See individual Path impls for additional restrictions.
-    #[inline]
-    fn new<T: BytesContainer>(path: T) -> Self {
-        assert!(!contains_nul(&path));
-        unsafe { GenericPathUnsafe::new_unchecked(path) }
-    }
-
-    /// Creates a new Path from a byte vector or string, if possible.
-    /// The resulting Path will always be normalized.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let x: &[u8] = b"foo\0";
-    /// assert!(Path::new_opt(x).is_none());
-    /// # }
-    /// ```
-    #[inline]
-    fn new_opt<T: BytesContainer>(path: T) -> Option<Self> {
-        if contains_nul(&path) {
-            None
-        } else {
-            Some(unsafe { GenericPathUnsafe::new_unchecked(path) })
-        }
-    }
-
-    /// Returns the path as a string, if possible.
-    /// If the path is not representable in utf-8, this returns None.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("/abc/def");
-    /// assert_eq!(p.as_str(), Some("/abc/def"));
-    /// # }
-    /// ```
-    #[inline]
-    fn as_str<'a>(&'a self) -> Option<&'a str> {
-        str::from_utf8(self.as_vec()).ok()
-    }
-
-    /// Returns the path as a byte vector
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def");
-    /// assert_eq!(p.as_vec(), b"abc/def");
-    /// # }
-    /// ```
-    fn as_vec<'a>(&'a self) -> &'a [u8];
-
-    /// Converts the Path into an owned byte vector
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def");
-    /// assert_eq!(p.into_vec(), b"abc/def".to_vec());
-    /// // attempting to use p now results in "error: use of moved value"
-    /// # }
-    /// ```
-    fn into_vec(self) -> Vec<u8>;
-
-    /// Returns an object that implements `Show` for printing paths
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def");
-    /// println!("{}", p.display()); // prints "abc/def"
-    /// # }
-    /// ```
-    fn display<'a>(&'a self) -> Display<'a, Self> {
-        Display{ path: self, filename: false }
-    }
-
-    /// Returns an object that implements `Show` for printing filenames
-    ///
-    /// If there is no filename, nothing will be printed.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def");
-    /// println!("{}", p.filename_display()); // prints "def"
-    /// # }
-    /// ```
-    fn filename_display<'a>(&'a self) -> Display<'a, Self> {
-        Display{ path: self, filename: true }
-    }
-
-    /// Returns the directory component of `self`, as a byte vector (with no trailing separator).
-    /// If `self` has no directory component, returns ['.'].
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def/ghi");
-    /// assert_eq!(p.dirname(), b"abc/def");
-    /// # }
-    /// ```
-    fn dirname<'a>(&'a self) -> &'a [u8];
-
-    /// Returns the directory component of `self`, as a string, if possible.
-    /// See `dirname` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def/ghi");
-    /// assert_eq!(p.dirname_str(), Some("abc/def"));
-    /// # }
-    /// ```
-    #[inline]
-    fn dirname_str<'a>(&'a self) -> Option<&'a str> {
-        str::from_utf8(self.dirname()).ok()
-    }
-
-    /// Returns the file component of `self`, as a byte vector.
-    /// If `self` represents the root of the file hierarchy, returns None.
-    /// If `self` is "." or "..", returns None.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def/ghi");
-    /// assert_eq!(p.filename(), Some(b"ghi"));
-    /// # }
-    /// ```
-    fn filename<'a>(&'a self) -> Option<&'a [u8]>;
-
-    /// Returns the file component of `self`, as a string, if possible.
-    /// See `filename` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def/ghi");
-    /// assert_eq!(p.filename_str(), Some("ghi"));
-    /// # }
-    /// ```
-    #[inline]
-    fn filename_str<'a>(&'a self) -> Option<&'a str> {
-        self.filename().and_then(|s| str::from_utf8(s).ok())
-    }
-
-    /// Returns the stem of the filename of `self`, as a byte vector.
-    /// The stem is the portion of the filename just before the last '.'.
-    /// If there is no '.', the entire filename is returned.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("/abc/def.txt");
-    /// assert_eq!(p.filestem(), Some(b"def"));
-    /// # }
-    /// ```
-    fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
-        match self.filename() {
-            None => None,
-            Some(name) => Some({
-                let dot = b'.';
-                match name.rposition_elem(&dot) {
-                    None | Some(0) => name,
-                    Some(1) if name == b".." => name,
-                    Some(pos) => &name[..pos]
-                }
-            })
-        }
-    }
-
-    /// Returns the stem of the filename of `self`, as a string, if possible.
-    /// See `filestem` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("/abc/def.txt");
-    /// assert_eq!(p.filestem_str(), Some("def"));
-    /// # }
-    /// ```
-    #[inline]
-    fn filestem_str<'a>(&'a self) -> Option<&'a str> {
-        self.filestem().and_then(|s| str::from_utf8(s).ok())
-    }
-
-    /// Returns the extension of the filename of `self`, as an optional byte vector.
-    /// The extension is the portion of the filename just after the last '.'.
-    /// If there is no extension, None is returned.
-    /// If the filename ends in '.', the empty vector is returned.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def.txt");
-    /// assert_eq!(p.extension(), Some(b"txt"));
-    /// # }
-    /// ```
-    fn extension<'a>(&'a self) -> Option<&'a [u8]> {
-        match self.filename() {
-            None => None,
-            Some(name) => {
-                let dot = b'.';
-                match name.rposition_elem(&dot) {
-                    None | Some(0) => None,
-                    Some(1) if name == b".." => None,
-                    Some(pos) => Some(&name[pos+1..])
-                }
-            }
-        }
-    }
-
-    /// Returns the extension of the filename of `self`, as a string, if possible.
-    /// See `extension` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def.txt");
-    /// assert_eq!(p.extension_str(), Some("txt"));
-    /// # }
-    /// ```
-    #[inline]
-    fn extension_str<'a>(&'a self) -> Option<&'a str> {
-        self.extension().and_then(|s| str::from_utf8(s).ok())
-    }
-
-    /// Replaces the filename portion of the path with the given byte vector or string.
-    /// If the replacement name is [], this is equivalent to popping the path.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let mut p = Path::new("abc/def.txt");
-    /// p.set_filename("foo.dat");
-    /// assert!(p == Path::new("abc/foo.dat"));
-    /// # }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the filename contains a NUL.
-    #[inline]
-    fn set_filename<T: BytesContainer>(&mut self, filename: T) {
-        assert!(!contains_nul(&filename));
-        unsafe { self.set_filename_unchecked(filename) }
-    }
-
-    /// Replaces the extension with the given byte vector or string.
-    /// If there is no extension in `self`, this adds one.
-    /// If the argument is [] or "", this removes the extension.
-    /// If `self` has no filename, this is a no-op.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let mut p = Path::new("abc/def.txt");
-    /// p.set_extension("csv");
-    /// assert_eq!(p, Path::new("abc/def.csv"));
-    /// # }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the extension contains a NUL.
-    fn set_extension<T: BytesContainer>(&mut self, extension: T) {
-        assert!(!contains_nul(&extension));
-
-        let val = self.filename().and_then(|name| {
-            let dot = b'.';
-            let extlen = extension.container_as_bytes().len();
-            match (name.rposition_elem(&dot), extlen) {
-                (None, 0) | (Some(0), 0) => None,
-                (Some(idx), 0) => Some(name[..idx].to_vec()),
-                (idx, extlen) => {
-                    let idx = match idx {
-                        None | Some(0) => name.len(),
-                        Some(val) => val
-                    };
-
-                    let mut v;
-                    v = Vec::with_capacity(idx + extlen + 1);
-                    v.push_all(&name[..idx]);
-                    v.push(dot);
-                    v.push_all(extension.container_as_bytes());
-                    Some(v)
-                }
-            }
-        });
-
-        match val {
-            None => (),
-            Some(v) => unsafe { self.set_filename_unchecked(v) }
-        }
-    }
-
-    /// Returns a new Path constructed by replacing the filename with the given
-    /// byte vector or string.
-    /// See `set_filename` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let mut p = Path::new("abc/def.txt");
-    /// assert_eq!(p.with_filename("foo.dat"), Path::new("abc/foo.dat"));
-    /// # }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the filename contains a NUL.
-    #[inline]
-    fn with_filename<T: BytesContainer>(&self, filename: T) -> Self {
-        let mut p = self.clone();
-        p.set_filename(filename);
-        p
-    }
-
-    /// Returns a new Path constructed by setting the extension to the given
-    /// byte vector or string.
-    /// See `set_extension` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let mut p = Path::new("abc/def.txt");
-    /// assert_eq!(p.with_extension("csv"), Path::new("abc/def.csv"));
-    /// # }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the extension contains a NUL.
-    #[inline]
-    fn with_extension<T: BytesContainer>(&self, extension: T) -> Self {
-        let mut p = self.clone();
-        p.set_extension(extension);
-        p
-    }
-
-    /// Returns the directory component of `self`, as a Path.
-    /// If `self` represents the root of the filesystem hierarchy, returns `self`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def/ghi");
-    /// assert_eq!(p.dir_path(), Path::new("abc/def"));
-    /// # }
-    /// ```
-    fn dir_path(&self) -> Self {
-        // self.dirname() returns a NUL-free vector
-        unsafe { GenericPathUnsafe::new_unchecked(self.dirname()) }
-    }
-
-    /// Returns a Path that represents the filesystem root that `self` is rooted in.
-    ///
-    /// If `self` is not absolute, or vol/cwd-relative in the case of Windows, this returns None.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// assert_eq!(Path::new("abc/def").root_path(), None);
-    /// assert_eq!(Path::new("/abc/def").root_path(), Some(Path::new("/")));
-    /// # }
-    /// ```
-    fn root_path(&self) -> Option<Self>;
-
-    /// Pushes a path (as a byte vector or string) onto `self`.
-    /// If the argument represents an absolute path, it replaces `self`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let mut p = Path::new("foo/bar");
-    /// p.push("baz.txt");
-    /// assert_eq!(p, Path::new("foo/bar/baz.txt"));
-    /// # }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the path contains a NUL.
-    #[inline]
-    fn push<T: BytesContainer>(&mut self, path: T) {
-        assert!(!contains_nul(&path));
-        unsafe { self.push_unchecked(path) }
-    }
-
-    /// Pushes multiple paths (as byte vectors or strings) onto `self`.
-    /// See `push` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let mut p = Path::new("foo");
-    /// p.push_many(&["bar", "baz.txt"]);
-    /// assert_eq!(p, Path::new("foo/bar/baz.txt"));
-    /// # }
-    /// ```
-    #[inline]
-    fn push_many<T: BytesContainer>(&mut self, paths: &[T]) {
-        let t: Option<&T> = None;
-        if BytesContainer::is_str(t) {
-            for p in paths {
-                self.push(p.container_as_str().unwrap())
-            }
-        } else {
-            for p in paths {
-                self.push(p.container_as_bytes())
-            }
-        }
-    }
-
-    /// Removes the last path component from the receiver.
-    /// Returns `true` if the receiver was modified, or `false` if it already
-    /// represented the root of the file hierarchy.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let mut p = Path::new("foo/bar/baz.txt");
-    /// p.pop();
-    /// assert_eq!(p, Path::new("foo/bar"));
-    /// # }
-    /// ```
-    fn pop(&mut self) -> bool;
-
-    /// Returns a new Path constructed by joining `self` with the given path
-    /// (as a byte vector or string).
-    /// If the given path is absolute, the new Path will represent just that.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("/foo");
-    /// assert_eq!(p.join("bar.txt"), Path::new("/foo/bar.txt"));
-    /// # }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the path contains a NUL.
-    #[inline]
-    fn join<T: BytesContainer>(&self, path: T) -> Self {
-        let mut p = self.clone();
-        p.push(path);
-        p
-    }
-
-    /// Returns a new Path constructed by joining `self` with the given paths
-    /// (as byte vectors or strings).
-    /// See `join` for details.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("foo");
-    /// let fbbq = Path::new("foo/bar/baz/quux.txt");
-    /// assert_eq!(p.join_many(&["bar", "baz", "quux.txt"]), fbbq);
-    /// # }
-    /// ```
-    #[inline]
-    fn join_many<T: BytesContainer>(&self, paths: &[T]) -> Self {
-        let mut p = self.clone();
-        p.push_many(paths);
-        p
-    }
-
-    /// Returns whether `self` represents an absolute path.
-    /// An absolute path is defined as one that, when joined to another path, will
-    /// yield back the same absolute path.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("/abc/def");
-    /// assert!(p.is_absolute());
-    /// # }
-    /// ```
-    fn is_absolute(&self) -> bool;
-
-    /// Returns whether `self` represents a relative path.
-    /// Typically this is the inverse of `is_absolute`.
-    /// But for Windows paths, it also means the path is not volume-relative or
-    /// relative to the current working directory.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("abc/def");
-    /// assert!(p.is_relative());
-    /// # }
-    /// ```
-    fn is_relative(&self) -> bool {
-        !self.is_absolute()
-    }
-
-    /// Returns whether `self` is equal to, or is an ancestor of, the given path.
-    /// If both paths are relative, they are compared as though they are relative
-    /// to the same parent path.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("foo/bar/baz/quux.txt");
-    /// let fb = Path::new("foo/bar");
-    /// let bq = Path::new("baz/quux.txt");
-    /// assert!(fb.is_ancestor_of(&p));
-    /// # }
-    /// ```
-    fn is_ancestor_of(&self, other: &Self) -> bool;
-
-    /// Returns the Path that, were it joined to `base`, would yield `self`.
-    /// If no such path exists, None is returned.
-    /// If `self` is absolute and `base` is relative, or on Windows if both
-    /// paths refer to separate drives, an absolute path is returned.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("foo/bar/baz/quux.txt");
-    /// let fb = Path::new("foo/bar");
-    /// let bq = Path::new("baz/quux.txt");
-    /// assert_eq!(p.path_relative_from(&fb), Some(bq));
-    /// # }
-    /// ```
-    fn path_relative_from(&self, base: &Self) -> Option<Self>;
-
-    /// Returns whether the relative path `child` is a suffix of `self`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// # foo();
-    /// # #[cfg(windows)] fn foo() {}
-    /// # #[cfg(unix)] fn foo() {
-    /// let p = Path::new("foo/bar/baz/quux.txt");
-    /// let bq = Path::new("baz/quux.txt");
-    /// assert!(p.ends_with_path(&bq));
-    /// # }
-    /// ```
-    fn ends_with_path(&self, child: &Self) -> bool;
-}
-
-/// A trait that represents something bytes-like (e.g. a &[u8] or a &str)
-pub trait BytesContainer {
-    /// Returns a &[u8] representing the receiver
-    fn container_as_bytes<'a>(&'a self) -> &'a [u8];
-    /// Returns the receiver interpreted as a utf-8 string, if possible
-    #[inline]
-    fn container_as_str<'a>(&'a self) -> Option<&'a str> {
-        str::from_utf8(self.container_as_bytes()).ok()
-    }
-    /// Returns whether .container_as_str() is guaranteed to not fail
-    // FIXME (#8888): Remove unused arg once ::<for T> works
-    #[inline]
-    fn is_str(_: Option<&Self>) -> bool { false }
-}
-
-/// A trait that represents the unsafe operations on GenericPaths
-pub trait GenericPathUnsafe {
-    /// Creates a new Path without checking for null bytes.
-    /// The resulting Path will always be normalized.
-    unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Self;
-
-    /// Replaces the filename portion of the path without checking for null
-    /// bytes.
-    /// See `set_filename` for details.
-    unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T);
-
-    /// Pushes a path onto `self` without checking for null bytes.
-    /// See `push` for details.
-    unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T);
-}
-
-/// Helper struct for printing paths with format!()
-pub struct Display<'a, P:'a> {
-    path: &'a P,
-    filename: bool
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, P: GenericPath> fmt::Debug for Display<'a, P> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.as_cow(), f)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, P: GenericPath> fmt::Display for Display<'a, P> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.as_cow().fmt(f)
-    }
-}
-
-impl<'a, P: GenericPath> Display<'a, P> {
-    /// Returns the path as a possibly-owned string.
-    ///
-    /// If the path is not UTF-8, invalid sequences will be replaced with the
-    /// Unicode replacement char. This involves allocation.
-    #[inline]
-    pub fn as_cow(&self) -> CowString<'a> {
-        String::from_utf8_lossy(if self.filename {
-            match self.path.filename() {
-                None => {
-                    let result: &[u8] = &[];
-                    result
-                }
-                Some(v) => v
-            }
-        } else {
-            self.path.as_vec()
-        })
-    }
-}
-
-impl BytesContainer for str {
-    #[inline]
-    fn container_as_bytes(&self) -> &[u8] {
-        self.as_bytes()
-    }
-    #[inline]
-    fn container_as_str(&self) -> Option<&str> {
-        Some(self)
-    }
-    #[inline]
-    fn is_str(_: Option<&str>) -> bool { true }
-}
-
-impl BytesContainer for String {
-    #[inline]
-    fn container_as_bytes(&self) -> &[u8] {
-        self.as_bytes()
-    }
-    #[inline]
-    fn container_as_str(&self) -> Option<&str> {
-        Some(&self[])
-    }
-    #[inline]
-    fn is_str(_: Option<&String>) -> bool { true }
-}
-
-impl BytesContainer for [u8] {
-    #[inline]
-    fn container_as_bytes(&self) -> &[u8] {
-        self
-    }
-}
-
-impl BytesContainer for Vec<u8> {
-    #[inline]
-    fn container_as_bytes(&self) -> &[u8] {
-        &self[]
-    }
-}
-
-impl BytesContainer for CString {
-    #[inline]
-    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
-        self.as_bytes()
-    }
-}
-
-impl<'a, T: ?Sized + BytesContainer> BytesContainer for &'a T {
-    #[inline]
-    fn container_as_bytes(&self) -> &[u8] {
-        (**self).container_as_bytes()
-    }
-    #[inline]
-    fn container_as_str(&self) -> Option<&str> {
-        (**self).container_as_str()
-    }
-    #[inline]
-    fn is_str(_: Option<& &'a T>) -> bool { BytesContainer::is_str(None::<&T>) }
-}
-
-#[inline(always)]
-fn contains_nul<T: BytesContainer>(v: &T) -> bool {
-    v.container_as_bytes().iter().any(|&x| x == 0)
-}
diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs
deleted file mode 100644 (file)
index 69f815e..0000000
+++ /dev/null
@@ -1,1348 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! POSIX file path handling
-
-use clone::Clone;
-use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
-use fmt;
-use hash;
-use old_io::Writer;
-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;
-
-use super::{BytesContainer, GenericPath, GenericPathUnsafe};
-
-/// Iterator that yields successive components of a Path as &[u8]
-pub type Components<'a> = Split<'a, u8, fn(&u8) -> bool>;
-
-/// Iterator that yields successive components of a Path as Option<&str>
-pub type StrComponents<'a> =
-    Map<Components<'a>, fn(&[u8]) -> Option<&str>>;
-
-/// Represents a POSIX file path
-#[derive(Clone)]
-pub struct Path {
-    repr: Vec<u8>, // assumed to never be empty or contain NULs
-    sepidx: Option<uint> // index of the final separator in repr
-}
-
-/// The standard path separator character
-pub const SEP: char = '/';
-
-/// The standard path separator byte
-pub const SEP_BYTE: u8 = SEP as u8;
-
-/// Returns whether the given byte is a path separator
-#[inline]
-pub fn is_sep_byte(u: &u8) -> bool {
-    *u as char == SEP
-}
-
-/// Returns whether the given char is a path separator
-#[inline]
-pub fn is_sep(c: char) -> bool {
-    c == SEP
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Path {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.display(), f)
-    }
-}
-
-impl PartialEq for Path {
-    #[inline]
-    fn eq(&self, other: &Path) -> bool {
-        self.repr == other.repr
-    }
-}
-
-impl Eq for Path {}
-
-impl PartialOrd for Path {
-    fn partial_cmp(&self, other: &Path) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-impl Ord for Path {
-    fn cmp(&self, other: &Path) -> Ordering {
-        self.repr.cmp(&other.repr)
-    }
-}
-
-impl FromStr for Path {
-    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(Debug, Clone, PartialEq, Copy)]
-pub struct ParsePathError;
-
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.repr.hash(state)
-    }
-}
-
-impl BytesContainer for Path {
-    #[inline]
-    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
-        self.as_vec()
-    }
-}
-
-impl GenericPathUnsafe for Path {
-    unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Path {
-        let path = Path::normalize(path.container_as_bytes());
-        assert!(!path.is_empty());
-        let idx = path.rposition_elem(&SEP_BYTE);
-        Path{ repr: path, sepidx: idx }
-    }
-
-    unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
-        let filename = filename.container_as_bytes();
-        match self.sepidx {
-            None if b".." == self.repr => {
-                let mut v = Vec::with_capacity(3 + filename.len());
-                v.push_all(dot_dot_static);
-                v.push(SEP_BYTE);
-                v.push_all(filename);
-                // FIXME: this is slow
-                self.repr = Path::normalize(v.as_slice());
-            }
-            None => {
-                self.repr = Path::normalize(filename);
-            }
-            Some(idx) if &self.repr[idx+1..] == b".." => {
-                let mut v = Vec::with_capacity(self.repr.len() + 1 + filename.len());
-                v.push_all(self.repr.as_slice());
-                v.push(SEP_BYTE);
-                v.push_all(filename);
-                // FIXME: this is slow
-                self.repr = Path::normalize(v.as_slice());
-            }
-            Some(idx) => {
-                let mut v = Vec::with_capacity(idx + 1 + filename.len());
-                v.push_all(&self.repr[..idx+1]);
-                v.push_all(filename);
-                // FIXME: this is slow
-                self.repr = Path::normalize(v.as_slice());
-            }
-        }
-        self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
-    }
-
-    unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
-        let path = path.container_as_bytes();
-        if !path.is_empty() {
-            if path[0] == SEP_BYTE {
-                self.repr = Path::normalize(path);
-            }  else {
-                let mut v = Vec::with_capacity(self.repr.len() + path.len() + 1);
-                v.push_all(self.repr.as_slice());
-                v.push(SEP_BYTE);
-                v.push_all(path);
-                // FIXME: this is slow
-                self.repr = Path::normalize(v.as_slice());
-            }
-            self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
-        }
-    }
-}
-
-impl GenericPath for Path {
-    #[inline]
-    fn as_vec<'a>(&'a self) -> &'a [u8] {
-        self.repr.as_slice()
-    }
-
-    fn into_vec(self) -> Vec<u8> {
-        self.repr
-    }
-
-    fn dirname<'a>(&'a self) -> &'a [u8] {
-        match self.sepidx {
-            None if b".." == self.repr => self.repr.as_slice(),
-            None => dot_static,
-            Some(0) => &self.repr[..1],
-            Some(idx) if &self.repr[idx+1..] == b".." => self.repr.as_slice(),
-            Some(idx) => &self.repr[..idx]
-        }
-    }
-
-    fn filename<'a>(&'a self) -> Option<&'a [u8]> {
-        match self.sepidx {
-            None if b"." == self.repr ||
-                b".." == self.repr => None,
-            None => Some(self.repr.as_slice()),
-            Some(idx) if &self.repr[idx+1..] == b".." => None,
-            Some(0) if self.repr[1..].is_empty() => None,
-            Some(idx) => Some(&self.repr[idx+1..])
-        }
-    }
-
-    fn pop(&mut self) -> bool {
-        match self.sepidx {
-            None if b"." == self.repr => false,
-            None => {
-                self.repr = vec![b'.'];
-                self.sepidx = None;
-                true
-            }
-            Some(0) if b"/" == self.repr => false,
-            Some(idx) => {
-                if idx == 0 {
-                    self.repr.truncate(idx+1);
-                } else {
-                    self.repr.truncate(idx);
-                }
-                self.sepidx = self.repr.rposition_elem(&SEP_BYTE);
-                true
-            }
-        }
-    }
-
-    fn root_path(&self) -> Option<Path> {
-        if self.is_absolute() {
-            Some(Path::new("/"))
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    fn is_absolute(&self) -> bool {
-        self.repr[0] == SEP_BYTE
-    }
-
-    fn is_ancestor_of(&self, other: &Path) -> bool {
-        if self.is_absolute() != other.is_absolute() {
-            false
-        } else {
-            let mut ita = self.components();
-            let mut itb = other.components();
-            if b"." == self.repr {
-                return match itb.next() {
-                    None => true,
-                    Some(b) => b != b".."
-                };
-            }
-            loop {
-                match (ita.next(), itb.next()) {
-                    (None, _) => break,
-                    (Some(a), Some(b)) if a == b => { continue },
-                    (Some(a), _) if a == b".." => {
-                        // if ita contains only .. components, it's an ancestor
-                        return ita.all(|x| x == b"..");
-                    }
-                    _ => return false
-                }
-            }
-            true
-        }
-    }
-
-    fn path_relative_from(&self, base: &Path) -> Option<Path> {
-        if self.is_absolute() != base.is_absolute() {
-            if self.is_absolute() {
-                Some(self.clone())
-            } else {
-                None
-            }
-        } else {
-            let mut ita = self.components();
-            let mut itb = base.components();
-            let mut comps = vec![];
-            loop {
-                match (ita.next(), itb.next()) {
-                    (None, None) => break,
-                    (Some(a), None) => {
-                        comps.push(a);
-                        comps.extend(ita.by_ref());
-                        break;
-                    }
-                    (None, _) => comps.push(dot_dot_static),
-                    (Some(a), Some(b)) if comps.is_empty() && a == b => (),
-                    (Some(a), Some(b)) if b == b"." => comps.push(a),
-                    (Some(_), Some(b)) if b == b".." => return None,
-                    (Some(a), Some(_)) => {
-                        comps.push(dot_dot_static);
-                        for _ in itb {
-                            comps.push(dot_dot_static);
-                        }
-                        comps.push(a);
-                        comps.extend(ita.by_ref());
-                        break;
-                    }
-                }
-            }
-            Some(Path::new(comps.connect(&SEP_BYTE)))
-        }
-    }
-
-    fn ends_with_path(&self, child: &Path) -> bool {
-        if !child.is_relative() { return false; }
-        let mut selfit = self.components().rev();
-        let mut childit = child.components().rev();
-        loop {
-            match (selfit.next(), childit.next()) {
-                (Some(a), Some(b)) => if a != b { return false; },
-                (Some(_), None) => break,
-                (None, Some(_)) => return false,
-                (None, None) => break
-            }
-        }
-        true
-    }
-}
-
-impl Path {
-    /// Returns a new Path from a byte vector or string
-    ///
-    /// # Panics
-    ///
-    /// Panics the task if the vector contains a NUL.
-    #[inline]
-    pub fn new<T: BytesContainer>(path: T) -> Path {
-        GenericPath::new(path)
-    }
-
-    /// Returns a new Path from a byte vector or string, if possible
-    #[inline]
-    pub fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
-        GenericPath::new_opt(path)
-    }
-
-    /// Returns a normalized byte vector representation of a path, by removing all empty
-    /// components, and unnecessary . and .. components.
-    fn normalize<V: ?Sized + AsSlice<u8>>(v: &V) -> Vec<u8> {
-        // borrowck is being very picky
-        let val = {
-            let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE;
-            let v_ = if is_abs { &v.as_slice()[1..] } else { v.as_slice() };
-            let comps = normalize_helper(v_, is_abs);
-            match comps {
-                None => None,
-                Some(comps) => {
-                    if is_abs && comps.is_empty() {
-                        Some(vec![SEP_BYTE])
-                    } else {
-                        let n = if is_abs { comps.len() } else { comps.len() - 1} +
-                                comps.iter().map(|v| v.len()).sum();
-                        let mut v = Vec::with_capacity(n);
-                        let mut it = comps.into_iter();
-                        if !is_abs {
-                            match it.next() {
-                                None => (),
-                                Some(comp) => v.push_all(comp)
-                            }
-                        }
-                        for comp in it {
-                            v.push(SEP_BYTE);
-                            v.push_all(comp);
-                        }
-                        Some(v)
-                    }
-                }
-            }
-        };
-        match val {
-            None => v.as_slice().to_vec(),
-            Some(val) => val
-        }
-    }
-
-    /// Returns an iterator that yields each component of the path in turn.
-    /// Does not distinguish between absolute and relative paths, e.g.
-    /// /a/b/c and a/b/c yield the same set of components.
-    /// A path of "/" yields no components. A path of "." yields one component.
-    pub fn components<'a>(&'a self) -> Components<'a> {
-        let v = if self.repr[0] == SEP_BYTE {
-            &self.repr[1..]
-        } else { self.repr.as_slice() };
-        let is_sep_byte: fn(&u8) -> bool = is_sep_byte; // coerce to fn ptr
-        let mut ret = v.split(is_sep_byte);
-        if v.is_empty() {
-            // consume the empty "" component
-            ret.next();
-        }
-        ret
-    }
-
-    /// Returns an iterator that yields each component of the path as Option<&str>.
-    /// See components() for details.
-    pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
-        fn from_utf8(s: &[u8]) -> Option<&str> {
-            str::from_utf8(s).ok()
-        }
-        let f: fn(&[u8]) -> Option<&str> = from_utf8; // coerce to fn ptr
-        self.components().map(f)
-    }
-}
-
-// None result means the byte vector didn't need normalizing
-fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<Vec<&'a [u8]>> {
-    if is_abs && v.is_empty() {
-        return None;
-    }
-    let mut comps: Vec<&'a [u8]> = vec![];
-    let mut n_up = 0u;
-    let mut changed = false;
-    for comp in v.split(is_sep_byte) {
-        if comp.is_empty() { changed = true }
-        else if comp == b"." { changed = true }
-        else if comp == b".." {
-            if is_abs && comps.is_empty() { changed = true }
-            else if comps.len() == n_up { comps.push(dot_dot_static); n_up += 1 }
-            else { comps.pop().unwrap(); changed = true }
-        } else { comps.push(comp) }
-    }
-    if changed {
-        if comps.is_empty() && !is_abs {
-            if v == b"." {
-                return None;
-            }
-            comps.push(dot_static);
-        }
-        Some(comps)
-    } else {
-        None
-    }
-}
-
-#[allow(non_upper_case_globals)]
-static dot_static: &'static [u8] = b".";
-#[allow(non_upper_case_globals)]
-static dot_dot_static: &'static [u8] = b"..";
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    use clone::Clone;
-    use iter::IteratorExt;
-    use option::Option::{self, Some, None};
-    use path::GenericPath;
-    use slice::{AsSlice, SliceExt};
-    use str::{self, Str, StrExt};
-    use string::ToString;
-    use vec::Vec;
-
-    macro_rules! t {
-        (s: $path:expr, $exp:expr) => (
-            {
-                let path = $path;
-                assert_eq!(path.as_str(), Some($exp));
-            }
-        );
-        (v: $path:expr, $exp:expr) => (
-            {
-                let path = $path;
-                assert_eq!(path.as_vec(), $exp);
-            }
-        )
-    }
-
-    #[test]
-    fn test_paths() {
-        let empty: &[u8] = &[];
-        t!(v: Path::new(empty), b".");
-        t!(v: Path::new(b"/"), b"/");
-        t!(v: Path::new(b"a/b/c"), b"a/b/c");
-        t!(v: Path::new(b"a/b/c\xFF"), b"a/b/c\xFF");
-        t!(v: Path::new(b"\xFF/../foo\x80"), b"foo\x80");
-        let p = Path::new(b"a/b/c\xFF");
-        assert!(p.as_str().is_none());
-
-        t!(s: Path::new(""), ".");
-        t!(s: Path::new("/"), "/");
-        t!(s: Path::new("hi"), "hi");
-        t!(s: Path::new("hi/"), "hi");
-        t!(s: Path::new("/lib"), "/lib");
-        t!(s: Path::new("/lib/"), "/lib");
-        t!(s: Path::new("hi/there"), "hi/there");
-        t!(s: Path::new("hi/there.txt"), "hi/there.txt");
-
-        t!(s: Path::new("hi/there/"), "hi/there");
-        t!(s: Path::new("hi/../there"), "there");
-        t!(s: Path::new("../hi/there"), "../hi/there");
-        t!(s: Path::new("/../hi/there"), "/hi/there");
-        t!(s: Path::new("foo/.."), ".");
-        t!(s: Path::new("/foo/.."), "/");
-        t!(s: Path::new("/foo/../.."), "/");
-        t!(s: Path::new("/foo/../../bar"), "/bar");
-        t!(s: Path::new("/./hi/./there/."), "/hi/there");
-        t!(s: Path::new("/./hi/./there/./.."), "/hi");
-        t!(s: Path::new("foo/../.."), "..");
-        t!(s: Path::new("foo/../../.."), "../..");
-        t!(s: Path::new("foo/../../bar"), "../bar");
-
-        assert_eq!(Path::new(b"foo/bar").into_vec(), b"foo/bar");
-        assert_eq!(Path::new(b"/foo/../../bar").into_vec(),
-                   b"/bar");
-
-        let p = Path::new(b"foo/bar\x80");
-        assert!(p.as_str().is_none());
-    }
-
-    #[test]
-    fn test_opt_paths() {
-        assert!(Path::new_opt(b"foo/bar\0").is_none());
-        t!(v: Path::new_opt(b"foo/bar").unwrap(), b"foo/bar");
-        assert!(Path::new_opt("foo/bar\0").is_none());
-        t!(s: Path::new_opt("foo/bar").unwrap(), "foo/bar");
-    }
-
-    #[test]
-    fn test_null_byte() {
-        use thread::Thread;
-        let result = Thread::scoped(move|| {
-            Path::new(b"foo/bar\0")
-        }).join();
-        assert!(result.is_err());
-
-        let result = Thread::scoped(move|| {
-            Path::new("test").set_filename(b"f\0o")
-        }).join();
-        assert!(result.is_err());
-
-        let result = Thread::scoped(move|| {
-            Path::new("test").push(b"f\0o");
-        }).join();
-        assert!(result.is_err());
-    }
-
-    #[test]
-    fn test_display_str() {
-        macro_rules! t {
-            ($path:expr, $disp:ident, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    assert_eq!(path.$disp().to_string(), $exp);
-                }
-            )
-        }
-        t!("foo", display, "foo");
-        t!(b"foo\x80", display, "foo\u{FFFD}");
-        t!(b"foo\xFFbar", display, "foo\u{FFFD}bar");
-        t!(b"foo\xFF/bar", filename_display, "bar");
-        t!(b"foo/\xFFbar", filename_display, "\u{FFFD}bar");
-        t!(b"/", filename_display, "");
-
-        macro_rules! t {
-            ($path:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let mo = path.display().as_cow();
-                    assert_eq!(mo.as_slice(), $exp);
-                }
-            );
-            ($path:expr, $exp:expr, filename) => (
-                {
-                    let path = Path::new($path);
-                    let mo = path.filename_display().as_cow();
-                    assert_eq!(mo.as_slice(), $exp);
-                }
-            )
-        }
-
-        t!("foo", "foo");
-        t!(b"foo\x80", "foo\u{FFFD}");
-        t!(b"foo\xFFbar", "foo\u{FFFD}bar");
-        t!(b"foo\xFF/bar", "bar", filename);
-        t!(b"foo/\xFFbar", "\u{FFFD}bar", filename);
-        t!(b"/", "", filename);
-    }
-
-    #[test]
-    fn test_display() {
-        macro_rules! t {
-            ($path:expr, $exp:expr, $expf:expr) => (
-                {
-                    let path = Path::new($path);
-                    let f = format!("{}", path.display());
-                    assert_eq!(f, $exp);
-                    let f = format!("{}", path.filename_display());
-                    assert_eq!(f, $expf);
-                }
-            )
-        }
-
-        t!(b"foo", "foo", "foo");
-        t!(b"foo/bar", "foo/bar", "bar");
-        t!(b"/", "/", "");
-        t!(b"foo\xFF", "foo\u{FFFD}", "foo\u{FFFD}");
-        t!(b"foo\xFF/bar", "foo\u{FFFD}/bar", "bar");
-        t!(b"foo/\xFFbar", "foo/\u{FFFD}bar", "\u{FFFD}bar");
-        t!(b"\xFFfoo/bar\xFF", "\u{FFFD}foo/bar\u{FFFD}", "bar\u{FFFD}");
-    }
-
-    #[test]
-    fn test_components() {
-        macro_rules! t {
-            (s: $path:expr, $op:ident, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    assert_eq!(path.$op(), ($exp).as_bytes());
-                }
-            );
-            (s: $path:expr, $op:ident, $exp:expr, opt) => (
-                {
-                    let path = Path::new($path);
-                    let left = path.$op().map(|x| str::from_utf8(x).unwrap());
-                    assert_eq!(left, $exp);
-                }
-            );
-            (v: $path:expr, $op:ident, $exp:expr) => (
-                {
-                    let arg = $path;
-                    let path = Path::new(arg);
-                    assert_eq!(path.$op(), $exp);
-                }
-            );
-        }
-
-        t!(v: b"a/b/c", filename, Some(b"c"));
-        t!(v: b"a/b/c\xFF", filename, Some(b"c\xFF"));
-        t!(v: b"a/b\xFF/c", filename, Some(b"c"));
-        t!(s: "a/b/c", filename, Some("c"), opt);
-        t!(s: "/a/b/c", filename, Some("c"), opt);
-        t!(s: "a", filename, Some("a"), opt);
-        t!(s: "/a", filename, Some("a"), opt);
-        t!(s: ".", filename, None, opt);
-        t!(s: "/", filename, None, opt);
-        t!(s: "..", filename, None, opt);
-        t!(s: "../..", filename, None, opt);
-
-        t!(v: b"a/b/c", dirname, b"a/b");
-        t!(v: b"a/b/c\xFF", dirname, b"a/b");
-        t!(v: b"a/b\xFF/c", dirname, b"a/b\xFF");
-        t!(s: "a/b/c", dirname, "a/b");
-        t!(s: "/a/b/c", dirname, "/a/b");
-        t!(s: "a", dirname, ".");
-        t!(s: "/a", dirname, "/");
-        t!(s: ".", dirname, ".");
-        t!(s: "/", dirname, "/");
-        t!(s: "..", dirname, "..");
-        t!(s: "../..", dirname, "../..");
-
-        t!(v: b"hi/there.txt", filestem, Some(b"there"));
-        t!(v: b"hi/there\x80.txt", filestem, Some(b"there\x80"));
-        t!(v: b"hi/there.t\x80xt", filestem, Some(b"there"));
-        t!(s: "hi/there.txt", filestem, Some("there"), opt);
-        t!(s: "hi/there", filestem, Some("there"), opt);
-        t!(s: "there.txt", filestem, Some("there"), opt);
-        t!(s: "there", filestem, Some("there"), opt);
-        t!(s: ".", filestem, None, opt);
-        t!(s: "/", filestem, None, opt);
-        t!(s: "foo/.bar", filestem, Some(".bar"), opt);
-        t!(s: ".bar", filestem, Some(".bar"), opt);
-        t!(s: "..bar", filestem, Some("."), opt);
-        t!(s: "hi/there..txt", filestem, Some("there."), opt);
-        t!(s: "..", filestem, None, opt);
-        t!(s: "../..", filestem, None, opt);
-
-        t!(v: b"hi/there.txt", extension, Some(b"txt"));
-        t!(v: b"hi/there\x80.txt", extension, Some(b"txt"));
-        t!(v: b"hi/there.t\x80xt", extension, Some(b"t\x80xt"));
-        t!(v: b"hi/there", extension, None);
-        t!(v: b"hi/there\x80", extension, None);
-        t!(s: "hi/there.txt", extension, Some("txt"), opt);
-        t!(s: "hi/there", extension, None, opt);
-        t!(s: "there.txt", extension, Some("txt"), opt);
-        t!(s: "there", extension, None, opt);
-        t!(s: ".", extension, None, opt);
-        t!(s: "/", extension, None, opt);
-        t!(s: "foo/.bar", extension, None, opt);
-        t!(s: ".bar", extension, None, opt);
-        t!(s: "..bar", extension, Some("bar"), opt);
-        t!(s: "hi/there..txt", extension, Some("txt"), opt);
-        t!(s: "..", extension, None, opt);
-        t!(s: "../..", extension, None, opt);
-    }
-
-    #[test]
-    fn test_push() {
-        macro_rules! t {
-            (s: $path:expr, $join:expr) => (
-                {
-                    let path = $path;
-                    let join = $join;
-                    let mut p1 = Path::new(path);
-                    let p2 = p1.clone();
-                    p1.push(join);
-                    assert_eq!(p1, p2.join(join));
-                }
-            )
-        }
-
-        t!(s: "a/b/c", "..");
-        t!(s: "/a/b/c", "d");
-        t!(s: "a/b", "c/d");
-        t!(s: "a/b", "/c/d");
-    }
-
-    #[test]
-    fn test_push_path() {
-        macro_rules! t {
-            (s: $path:expr, $push:expr, $exp:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    let push = Path::new($push);
-                    p.push(&push);
-                    assert_eq!(p.as_str(), Some($exp));
-                }
-            )
-        }
-
-        t!(s: "a/b/c", "d", "a/b/c/d");
-        t!(s: "/a/b/c", "d", "/a/b/c/d");
-        t!(s: "a/b", "c/d", "a/b/c/d");
-        t!(s: "a/b", "/c/d", "/c/d");
-        t!(s: "a/b", ".", "a/b");
-        t!(s: "a/b", "../c", "a/c");
-    }
-
-    #[test]
-    fn test_push_many() {
-        macro_rules! t {
-            (s: $path:expr, $push:expr, $exp:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    p.push_many(&$push);
-                    assert_eq!(p.as_str(), Some($exp));
-                }
-            );
-            (v: $path:expr, $push:expr, $exp:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    p.push_many(&$push);
-                    assert_eq!(p.as_vec(), $exp);
-                }
-            )
-        }
-
-        t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
-        t!(s: "a/b/c", ["d", "/e"], "/e");
-        t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
-        t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e");
-        t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e");
-        t!(v: b"a/b/c", [b"d", b"/e", b"f"], b"/e/f");
-        t!(v: b"a/b/c", [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e");
-    }
-
-    #[test]
-    fn test_pop() {
-        macro_rules! t {
-            (s: $path:expr, $left:expr, $right:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    let result = p.pop();
-                    assert_eq!(p.as_str(), Some($left));
-                    assert_eq!(result, $right);
-                }
-            );
-            (b: $path:expr, $left:expr, $right:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    let result = p.pop();
-                    assert_eq!(p.as_vec(), $left);
-                    assert_eq!(result, $right);
-                }
-            )
-        }
-
-        t!(b: b"a/b/c", b"a/b", true);
-        t!(b: b"a", b".", true);
-        t!(b: b".", b".", false);
-        t!(b: b"/a", b"/", true);
-        t!(b: b"/", b"/", false);
-        t!(b: b"a/b/c\x80", b"a/b", true);
-        t!(b: b"a/b\x80/c", b"a/b\x80", true);
-        t!(b: b"\xFF", b".", true);
-        t!(b: b"/\xFF", b"/", true);
-        t!(s: "a/b/c", "a/b", true);
-        t!(s: "a", ".", true);
-        t!(s: ".", ".", false);
-        t!(s: "/a", "/", true);
-        t!(s: "/", "/", false);
-    }
-
-    #[test]
-    fn test_root_path() {
-        assert_eq!(Path::new(b"a/b/c").root_path(), None);
-        assert_eq!(Path::new(b"/a/b/c").root_path(), Some(Path::new("/")));
-    }
-
-    #[test]
-    fn test_join() {
-        t!(v: Path::new(b"a/b/c").join(b".."), b"a/b");
-        t!(v: Path::new(b"/a/b/c").join(b"d"), b"/a/b/c/d");
-        t!(v: Path::new(b"a/\x80/c").join(b"\xFF"), b"a/\x80/c/\xFF");
-        t!(s: Path::new("a/b/c").join(".."), "a/b");
-        t!(s: Path::new("/a/b/c").join("d"), "/a/b/c/d");
-        t!(s: Path::new("a/b").join("c/d"), "a/b/c/d");
-        t!(s: Path::new("a/b").join("/c/d"), "/c/d");
-        t!(s: Path::new(".").join("a/b"), "a/b");
-        t!(s: Path::new("/").join("a/b"), "/a/b");
-    }
-
-    #[test]
-    fn test_join_path() {
-        macro_rules! t {
-            (s: $path:expr, $join:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let join = Path::new($join);
-                    let res = path.join(&join);
-                    assert_eq!(res.as_str(), Some($exp));
-                }
-            )
-        }
-
-        t!(s: "a/b/c", "..", "a/b");
-        t!(s: "/a/b/c", "d", "/a/b/c/d");
-        t!(s: "a/b", "c/d", "a/b/c/d");
-        t!(s: "a/b", "/c/d", "/c/d");
-        t!(s: ".", "a/b", "a/b");
-        t!(s: "/", "a/b", "/a/b");
-    }
-
-    #[test]
-    fn test_join_many() {
-        macro_rules! t {
-            (s: $path:expr, $join:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let res = path.join_many(&$join);
-                    assert_eq!(res.as_str(), Some($exp));
-                }
-            );
-            (v: $path:expr, $join:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let res = path.join_many(&$join);
-                    assert_eq!(res.as_vec(), $exp);
-                }
-            )
-        }
-
-        t!(s: "a/b/c", ["d", "e"], "a/b/c/d/e");
-        t!(s: "a/b/c", ["..", "d"], "a/b/d");
-        t!(s: "a/b/c", ["d", "/e", "f"], "/e/f");
-        t!(s: "a/b/c", ["d".to_string(), "e".to_string()], "a/b/c/d/e");
-        t!(v: b"a/b/c", [b"d", b"e"], b"a/b/c/d/e");
-        t!(v: b"a/b/c", [b"d".to_vec(), b"e".to_vec()], b"a/b/c/d/e");
-    }
-
-    #[test]
-    fn test_with_helpers() {
-        let empty: &[u8] = &[];
-
-        t!(v: Path::new(b"a/b/c").with_filename(b"d"), b"a/b/d");
-        t!(v: Path::new(b"a/b/c\xFF").with_filename(b"\x80"), b"a/b/\x80");
-        t!(v: Path::new(b"/\xFF/foo").with_filename(b"\xCD"),
-              b"/\xFF/\xCD");
-        t!(s: Path::new("a/b/c").with_filename("d"), "a/b/d");
-        t!(s: Path::new(".").with_filename("foo"), "foo");
-        t!(s: Path::new("/a/b/c").with_filename("d"), "/a/b/d");
-        t!(s: Path::new("/").with_filename("foo"), "/foo");
-        t!(s: Path::new("/a").with_filename("foo"), "/foo");
-        t!(s: Path::new("foo").with_filename("bar"), "bar");
-        t!(s: Path::new("/").with_filename("foo/"), "/foo");
-        t!(s: Path::new("/a").with_filename("foo/"), "/foo");
-        t!(s: Path::new("a/b/c").with_filename(""), "a/b");
-        t!(s: Path::new("a/b/c").with_filename("."), "a/b");
-        t!(s: Path::new("a/b/c").with_filename(".."), "a");
-        t!(s: Path::new("/a").with_filename(""), "/");
-        t!(s: Path::new("foo").with_filename(""), ".");
-        t!(s: Path::new("a/b/c").with_filename("d/e"), "a/b/d/e");
-        t!(s: Path::new("a/b/c").with_filename("/d"), "a/b/d");
-        t!(s: Path::new("..").with_filename("foo"), "../foo");
-        t!(s: Path::new("../..").with_filename("foo"), "../../foo");
-        t!(s: Path::new("..").with_filename(""), "..");
-        t!(s: Path::new("../..").with_filename(""), "../..");
-
-        t!(v: Path::new(b"hi/there\x80.txt").with_extension(b"exe"),
-              b"hi/there\x80.exe");
-        t!(v: Path::new(b"hi/there.txt\x80").with_extension(b"\xFF"),
-              b"hi/there.\xFF");
-        t!(v: Path::new(b"hi/there\x80").with_extension(b"\xFF"),
-              b"hi/there\x80.\xFF");
-        t!(v: Path::new(b"hi/there.\xFF").with_extension(empty), b"hi/there");
-        t!(s: Path::new("hi/there.txt").with_extension("exe"), "hi/there.exe");
-        t!(s: Path::new("hi/there.txt").with_extension(""), "hi/there");
-        t!(s: Path::new("hi/there.txt").with_extension("."), "hi/there..");
-        t!(s: Path::new("hi/there.txt").with_extension(".."), "hi/there...");
-        t!(s: Path::new("hi/there").with_extension("txt"), "hi/there.txt");
-        t!(s: Path::new("hi/there").with_extension("."), "hi/there..");
-        t!(s: Path::new("hi/there").with_extension(".."), "hi/there...");
-        t!(s: Path::new("hi/there.").with_extension("txt"), "hi/there.txt");
-        t!(s: Path::new("hi/.foo").with_extension("txt"), "hi/.foo.txt");
-        t!(s: Path::new("hi/there.txt").with_extension(".foo"), "hi/there..foo");
-        t!(s: Path::new("/").with_extension("txt"), "/");
-        t!(s: Path::new("/").with_extension("."), "/");
-        t!(s: Path::new("/").with_extension(".."), "/");
-        t!(s: Path::new(".").with_extension("txt"), ".");
-    }
-
-    #[test]
-    fn test_setters() {
-        macro_rules! t {
-            (s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
-                {
-                    let path = $path;
-                    let arg = $arg;
-                    let mut p1 = Path::new(path);
-                    p1.$set(arg);
-                    let p2 = Path::new(path);
-                    assert_eq!(p1, p2.$with(arg));
-                }
-            );
-            (v: $path:expr, $set:ident, $with:ident, $arg:expr) => (
-                {
-                    let path = $path;
-                    let arg = $arg;
-                    let mut p1 = Path::new(path);
-                    p1.$set(arg);
-                    let p2 = Path::new(path);
-                    assert_eq!(p1, p2.$with(arg));
-                }
-            )
-        }
-
-        t!(v: b"a/b/c", set_filename, with_filename, b"d");
-        t!(v: b"/", set_filename, with_filename, b"foo");
-        t!(v: b"\x80", set_filename, with_filename, b"\xFF");
-        t!(s: "a/b/c", set_filename, with_filename, "d");
-        t!(s: "/", set_filename, with_filename, "foo");
-        t!(s: ".", set_filename, with_filename, "foo");
-        t!(s: "a/b", set_filename, with_filename, "");
-        t!(s: "a", set_filename, with_filename, "");
-
-        t!(v: b"hi/there.txt", set_extension, with_extension, b"exe");
-        t!(v: b"hi/there.t\x80xt", set_extension, with_extension, b"exe\xFF");
-        t!(s: "hi/there.txt", set_extension, with_extension, "exe");
-        t!(s: "hi/there.", set_extension, with_extension, "txt");
-        t!(s: "hi/there", set_extension, with_extension, "txt");
-        t!(s: "hi/there.txt", set_extension, with_extension, "");
-        t!(s: "hi/there", set_extension, with_extension, "");
-        t!(s: ".", set_extension, with_extension, "txt");
-    }
-
-    #[test]
-    fn test_getters() {
-        macro_rules! t {
-            (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
-                {
-                    let path = $path;
-                    assert_eq!(path.filename_str(), $filename);
-                    assert_eq!(path.dirname_str(), $dirname);
-                    assert_eq!(path.filestem_str(), $filestem);
-                    assert_eq!(path.extension_str(), $ext);
-               }
-            );
-            (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
-                {
-                    let path = $path;
-                    assert_eq!(path.filename(), $filename);
-                    assert_eq!(path.dirname(), $dirname);
-                    assert_eq!(path.filestem(), $filestem);
-                    assert_eq!(path.extension(), $ext);
-                }
-            )
-        }
-
-        t!(v: Path::new(b"a/b/c"), Some(b"c"), b"a/b", Some(b"c"), None);
-        t!(v: Path::new(b"a/b/\xFF"), Some(b"\xFF"), b"a/b", Some(b"\xFF"), None);
-        t!(v: Path::new(b"hi/there.\xFF"), Some(b"there.\xFF"), b"hi",
-              Some(b"there"), Some(b"\xFF"));
-        t!(s: Path::new("a/b/c"), Some("c"), Some("a/b"), Some("c"), None);
-        t!(s: Path::new("."), None, Some("."), None, None);
-        t!(s: Path::new("/"), None, Some("/"), None, None);
-        t!(s: Path::new(".."), None, Some(".."), None, None);
-        t!(s: Path::new("../.."), None, Some("../.."), None, None);
-        t!(s: Path::new("hi/there.txt"), Some("there.txt"), Some("hi"),
-              Some("there"), Some("txt"));
-        t!(s: Path::new("hi/there"), Some("there"), Some("hi"), Some("there"), None);
-        t!(s: Path::new("hi/there."), Some("there."), Some("hi"),
-              Some("there"), Some(""));
-        t!(s: Path::new("hi/.there"), Some(".there"), Some("hi"), Some(".there"), None);
-        t!(s: Path::new("hi/..there"), Some("..there"), Some("hi"),
-              Some("."), Some("there"));
-        t!(s: Path::new(b"a/b/\xFF"), None, Some("a/b"), None, None);
-        t!(s: Path::new(b"a/b/\xFF.txt"), None, Some("a/b"), None, Some("txt"));
-        t!(s: Path::new(b"a/b/c.\x80"), None, Some("a/b"), Some("c"), None);
-        t!(s: Path::new(b"\xFF/b"), Some("b"), None, Some("b"), None);
-    }
-
-    #[test]
-    fn test_dir_path() {
-        t!(v: Path::new(b"hi/there\x80").dir_path(), b"hi");
-        t!(v: Path::new(b"hi\xFF/there").dir_path(), b"hi\xFF");
-        t!(s: Path::new("hi/there").dir_path(), "hi");
-        t!(s: Path::new("hi").dir_path(), ".");
-        t!(s: Path::new("/hi").dir_path(), "/");
-        t!(s: Path::new("/").dir_path(), "/");
-        t!(s: Path::new("..").dir_path(), "..");
-        t!(s: Path::new("../..").dir_path(), "../..");
-    }
-
-    #[test]
-    fn test_is_absolute() {
-        macro_rules! t {
-            (s: $path:expr, $abs:expr, $rel:expr) => (
-                {
-                    let path = Path::new($path);
-                    assert_eq!(path.is_absolute(), $abs);
-                    assert_eq!(path.is_relative(), $rel);
-                }
-            )
-        }
-        t!(s: "a/b/c", false, true);
-        t!(s: "/a/b/c", true, false);
-        t!(s: "a", false, true);
-        t!(s: "/a", true, false);
-        t!(s: ".", false, true);
-        t!(s: "/", true, false);
-        t!(s: "..", false, true);
-        t!(s: "../..", false, true);
-    }
-
-    #[test]
-    fn test_is_ancestor_of() {
-        macro_rules! t {
-            (s: $path:expr, $dest:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let dest = Path::new($dest);
-                    assert_eq!(path.is_ancestor_of(&dest), $exp);
-                }
-            )
-        }
-
-        t!(s: "a/b/c", "a/b/c/d", true);
-        t!(s: "a/b/c", "a/b/c", true);
-        t!(s: "a/b/c", "a/b", false);
-        t!(s: "/a/b/c", "/a/b/c", true);
-        t!(s: "/a/b", "/a/b/c", true);
-        t!(s: "/a/b/c/d", "/a/b/c", false);
-        t!(s: "/a/b", "a/b/c", false);
-        t!(s: "a/b", "/a/b/c", false);
-        t!(s: "a/b/c", "a/b/d", false);
-        t!(s: "../a/b/c", "a/b/c", false);
-        t!(s: "a/b/c", "../a/b/c", false);
-        t!(s: "a/b/c", "a/b/cd", false);
-        t!(s: "a/b/cd", "a/b/c", false);
-        t!(s: "../a/b", "../a/b/c", true);
-        t!(s: ".", "a/b", true);
-        t!(s: ".", ".", true);
-        t!(s: "/", "/", true);
-        t!(s: "/", "/a/b", true);
-        t!(s: "..", "a/b", true);
-        t!(s: "../..", "a/b", true);
-    }
-
-    #[test]
-    fn test_ends_with_path() {
-        macro_rules! t {
-            (s: $path:expr, $child:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let child = Path::new($child);
-                    assert_eq!(path.ends_with_path(&child), $exp);
-                }
-            );
-            (v: $path:expr, $child:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let child = Path::new($child);
-                    assert_eq!(path.ends_with_path(&child), $exp);
-                }
-            )
-        }
-
-        t!(s: "a/b/c", "c", true);
-        t!(s: "a/b/c", "d", false);
-        t!(s: "foo/bar/quux", "bar", false);
-        t!(s: "foo/bar/quux", "barquux", false);
-        t!(s: "a/b/c", "b/c", true);
-        t!(s: "a/b/c", "a/b/c", true);
-        t!(s: "a/b/c", "foo/a/b/c", false);
-        t!(s: "/a/b/c", "a/b/c", true);
-        t!(s: "/a/b/c", "/a/b/c", false); // child must be relative
-        t!(s: "/a/b/c", "foo/a/b/c", false);
-        t!(s: "a/b/c", "", false);
-        t!(s: "", "", true);
-        t!(s: "/a/b/c", "d/e/f", false);
-        t!(s: "a/b/c", "a/b", false);
-        t!(s: "a/b/c", "b", false);
-        t!(v: b"a/b/c", b"b/c", true);
-        t!(v: b"a/b/\xFF", b"\xFF", true);
-        t!(v: b"a/b/\xFF", b"b/\xFF", true);
-    }
-
-    #[test]
-    fn test_path_relative_from() {
-        macro_rules! t {
-            (s: $path:expr, $other:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let other = Path::new($other);
-                    let res = path.path_relative_from(&other);
-                    assert_eq!(res.as_ref().and_then(|x| x.as_str()), $exp);
-                }
-            )
-        }
-
-        t!(s: "a/b/c", "a/b", Some("c"));
-        t!(s: "a/b/c", "a/b/d", Some("../c"));
-        t!(s: "a/b/c", "a/b/c/d", Some(".."));
-        t!(s: "a/b/c", "a/b/c", Some("."));
-        t!(s: "a/b/c", "a/b/c/d/e", Some("../.."));
-        t!(s: "a/b/c", "a/d/e", Some("../../b/c"));
-        t!(s: "a/b/c", "d/e/f", Some("../../../a/b/c"));
-        t!(s: "a/b/c", "/a/b/c", None);
-        t!(s: "/a/b/c", "a/b/c", Some("/a/b/c"));
-        t!(s: "/a/b/c", "/a/b/c/d", Some(".."));
-        t!(s: "/a/b/c", "/a/b", Some("c"));
-        t!(s: "/a/b/c", "/a/b/c/d/e", Some("../.."));
-        t!(s: "/a/b/c", "/a/d/e", Some("../../b/c"));
-        t!(s: "/a/b/c", "/d/e/f", Some("../../../a/b/c"));
-        t!(s: "hi/there.txt", "hi/there", Some("../there.txt"));
-        t!(s: ".", "a", Some(".."));
-        t!(s: ".", "a/b", Some("../.."));
-        t!(s: ".", ".", Some("."));
-        t!(s: "a", ".", Some("a"));
-        t!(s: "a/b", ".", Some("a/b"));
-        t!(s: "..", ".", Some(".."));
-        t!(s: "a/b/c", "a/b/c", Some("."));
-        t!(s: "/a/b/c", "/a/b/c", Some("."));
-        t!(s: "/", "/", Some("."));
-        t!(s: "/", ".", Some("/"));
-        t!(s: "../../a", "b", Some("../../../a"));
-        t!(s: "a", "../../b", None);
-        t!(s: "../../a", "../../b", Some("../a"));
-        t!(s: "../../a", "../../a/b", Some(".."));
-        t!(s: "../../a/b", "../../a", Some("b"));
-    }
-
-    #[test]
-    fn test_components_iter() {
-        macro_rules! t {
-            (s: $path:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let comps = path.components().collect::<Vec<&[u8]>>();
-                    let exp: &[&str] = &$exp;
-                    let exps = exp.iter().map(|x| x.as_bytes()).collect::<Vec<&[u8]>>();
-                    assert_eq!(comps, exps);
-                    let comps = path.components().rev().collect::<Vec<&[u8]>>();
-                    let exps = exps.into_iter().rev().collect::<Vec<&[u8]>>();
-                    assert_eq!(comps, exps);
-                }
-            );
-            (b: $arg:expr, [$($exp:expr),*]) => (
-                {
-                    let path = Path::new($arg);
-                    let comps = path.components().collect::<Vec<&[u8]>>();
-                    let exp: &[&[u8]] = &[$($exp),*];
-                    assert_eq!(comps, exp);
-                    let comps = path.components().rev().collect::<Vec<&[u8]>>();
-                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
-                    assert_eq!(comps, exp)
-                }
-            )
-        }
-
-        t!(b: b"a/b/c", [b"a", b"b", b"c"]);
-        t!(b: b"/\xFF/a/\x80", [b"\xFF", b"a", b"\x80"]);
-        t!(b: b"../../foo\xCDbar", [b"..", b"..", b"foo\xCDbar"]);
-        t!(s: "a/b/c", ["a", "b", "c"]);
-        t!(s: "a/b/d", ["a", "b", "d"]);
-        t!(s: "a/b/cd", ["a", "b", "cd"]);
-        t!(s: "/a/b/c", ["a", "b", "c"]);
-        t!(s: "a", ["a"]);
-        t!(s: "/a", ["a"]);
-        t!(s: "/", []);
-        t!(s: ".", ["."]);
-        t!(s: "..", [".."]);
-        t!(s: "../..", ["..", ".."]);
-        t!(s: "../../foo", ["..", "..", "foo"]);
-    }
-
-    #[test]
-    fn test_str_components() {
-        macro_rules! t {
-            (b: $arg:expr, $exp:expr) => (
-                {
-                    let path = Path::new($arg);
-                    let comps = path.str_components().collect::<Vec<Option<&str>>>();
-                    let exp: &[Option<&str>] = &$exp;
-                    assert_eq!(comps, exp);
-                    let comps = path.str_components().rev().collect::<Vec<Option<&str>>>();
-                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<Option<&str>>>();
-                    assert_eq!(comps, exp);
-                }
-            )
-        }
-
-        t!(b: b"a/b/c", [Some("a"), Some("b"), Some("c")]);
-        t!(b: b"/\xFF/a/\x80", [None, Some("a"), None]);
-        t!(b: b"../../foo\xCDbar", [Some(".."), Some(".."), None]);
-        // str_components is a wrapper around components, so no need to do
-        // the full set of tests
-    }
-}
-
-#[cfg(test)]
-mod bench {
-    extern crate test;
-    use self::test::Bencher;
-    use super::*;
-    use prelude::v1::{Clone, GenericPath};
-
-    #[bench]
-    fn join_home_dir(b: &mut Bencher) {
-        let posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.join("home");
-        });
-    }
-
-    #[bench]
-    fn join_abs_path_home_dir(b: &mut Bencher) {
-        let posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.join("/home");
-        });
-    }
-
-    #[bench]
-    fn join_many_home_dir(b: &mut Bencher) {
-        let posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.join_many(&["home"]);
-        });
-    }
-
-    #[bench]
-    fn join_many_abs_path_home_dir(b: &mut Bencher) {
-        let posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.join_many(&["/home"]);
-        });
-    }
-
-    #[bench]
-    fn push_home_dir(b: &mut Bencher) {
-        let mut posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.push("home");
-        });
-    }
-
-    #[bench]
-    fn push_abs_path_home_dir(b: &mut Bencher) {
-        let mut posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.push("/home");
-        });
-    }
-
-    #[bench]
-    fn push_many_home_dir(b: &mut Bencher) {
-        let mut posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.push_many(&["home"]);
-        });
-    }
-
-    #[bench]
-    fn push_many_abs_path_home_dir(b: &mut Bencher) {
-        let mut posix_path = Path::new("/");
-        b.iter(|| {
-            posix_path.push_many(&["/home"]);
-        });
-    }
-
-    #[bench]
-    fn ends_with_path_home_dir(b: &mut Bencher) {
-        let posix_home_path = Path::new("/home");
-        b.iter(|| {
-            posix_home_path.ends_with_path(&Path::new("home"));
-        });
-    }
-
-    #[bench]
-    fn ends_with_path_missmatch_jome_home(b: &mut Bencher) {
-        let posix_home_path = Path::new("/home");
-        b.iter(|| {
-            posix_home_path.ends_with_path(&Path::new("jome"));
-        });
-    }
-
-    #[bench]
-    fn is_ancestor_of_path_with_10_dirs(b: &mut Bencher) {
-        let path = Path::new("/home/1/2/3/4/5/6/7/8/9");
-        let mut sub = path.clone();
-        sub.pop();
-        b.iter(|| {
-            path.is_ancestor_of(&sub);
-        });
-    }
-
-    #[bench]
-    fn path_relative_from_forward(b: &mut Bencher) {
-        let path = Path::new("/a/b/c");
-        let mut other = path.clone();
-        other.pop();
-        b.iter(|| {
-            path.path_relative_from(&other);
-        });
-    }
-
-    #[bench]
-    fn path_relative_from_same_level(b: &mut Bencher) {
-        let path = Path::new("/a/b/c");
-        let mut other = path.clone();
-        other.pop();
-        other.push("d");
-        b.iter(|| {
-            path.path_relative_from(&other);
-        });
-    }
-
-    #[bench]
-    fn path_relative_from_backward(b: &mut Bencher) {
-        let path = Path::new("/a/b");
-        let mut other = path.clone();
-        other.push("c");
-        b.iter(|| {
-            path.path_relative_from(&other);
-        });
-    }
-}
diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs
deleted file mode 100644 (file)
index fcdebaf..0000000
+++ /dev/null
@@ -1,2329 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-// ignore-lexer-test FIXME #15883
-
-//! Windows file path handling
-
-use self::PathPrefix::*;
-
-use ascii::AsciiExt;
-use char::CharExt;
-use clone::Clone;
-use cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd};
-use fmt;
-use hash;
-use old_io::Writer;
-use iter::{AdditiveIterator, Extend};
-use iter::{Iterator, IteratorExt, Map, repeat};
-use mem;
-use option::Option::{self, Some, None};
-use result::Result::{self, Ok, Err};
-use slice::{SliceExt, SliceConcatExt};
-use str::{SplitTerminator, FromStr, StrExt};
-use string::{String, ToString};
-use vec::Vec;
-
-use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe};
-
-/// Iterator that yields successive components of a Path as &str
-///
-/// Each component is yielded as Option<&str> for compatibility with PosixPath, but
-/// every component in WindowsPath is guaranteed to be Some.
-pub type StrComponents<'a> =
-    Map<SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>;
-
-/// Iterator that yields successive components of a Path as &[u8]
-pub type Components<'a> =
-    Map<StrComponents<'a>, fn(Option<&str>) -> &[u8]>;
-
-/// Represents a Windows path
-// Notes for Windows path impl:
-// The MAX_PATH is 260, but 253 is the practical limit due to some API bugs
-// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx for good information
-// about windows paths.
-// That same page puts a bunch of restrictions on allowed characters in a path.
-// `\foo.txt` means "relative to current drive", but will not be considered to be absolute here
-// as `∃P | P.join("\foo.txt") != "\foo.txt"`.
-// `C:` is interesting, that means "the current directory on drive C".
-// Long absolute paths need to have \\?\ prefix (or, for UNC, \\?\UNC\). I think that can be
-// ignored for now, though, and only added in a hypothetical .to_pwstr() function.
-// However, if a path is parsed that has \\?\, this needs to be preserved as it disables the
-// processing of "." and ".." components and / as a separator.
-// Experimentally, \\?\foo is not the same thing as \foo.
-// Also, \\foo is not valid either (certainly not equivalent to \foo).
-// Similarly, C:\\Users is not equivalent to C:\Users, although C:\Users\\foo is equivalent
-// to C:\Users\foo. In fact the command prompt treats C:\\foo\bar as UNC path. But it might be
-// best to just ignore that and normalize it to C:\foo\bar.
-//
-// Based on all this, I think the right approach is to do the following:
-// * Require valid utf-8 paths. Windows API may use WCHARs, but we don't, and utf-8 is convertible
-// to UTF-16 anyway (though does Windows use UTF-16 or UCS-2? Not sure).
-// * Parse the prefixes \\?\UNC\, \\?\, and \\.\ explicitly.
-// * If \\?\UNC\, treat following two path components as server\share. Don't error for missing
-//   server\share.
-// * If \\?\, parse disk from following component, if present. Don't error for missing disk.
-// * If \\.\, treat rest of path as just regular components. I don't know how . and .. are handled
-//   here, they probably aren't, but I'm not going to worry about that.
-// * Else if starts with \\, treat following two components as server\share. Don't error for missing
-//   server\share.
-// * Otherwise, attempt to parse drive from start of path.
-//
-// The only error condition imposed here is valid utf-8. All other invalid paths are simply
-// preserved by the data structure; let the Windows API error out on them.
-#[derive(Clone)]
-pub struct Path {
-    repr: String, // assumed to never be empty
-    prefix: Option<PathPrefix>,
-    sepidx: Option<uint> // index of the final separator in the non-prefix portion of repr
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Path {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.display(), f)
-    }
-}
-
-impl PartialEq for Path {
-    #[inline]
-    fn eq(&self, other: &Path) -> bool {
-        self.repr == other.repr
-    }
-}
-
-impl Eq for Path {}
-
-impl PartialOrd for Path {
-    fn partial_cmp(&self, other: &Path) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-impl Ord for Path {
-    fn cmp(&self, other: &Path) -> Ordering {
-        self.repr.cmp(&other.repr)
-    }
-}
-
-impl FromStr for Path {
-    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(Debug, Clone, PartialEq, Copy)]
-pub struct ParsePathError;
-
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
-    #[cfg(not(test))]
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.repr.hash(state)
-    }
-
-    #[cfg(test)]
-    #[inline]
-    fn hash(&self, _: &mut S) {
-        // No-op because the `hash` implementation will be wrong.
-    }
-}
-
-impl BytesContainer for Path {
-    #[inline]
-    fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
-        self.as_vec()
-    }
-    #[inline]
-    fn container_as_str<'a>(&'a self) -> Option<&'a str> {
-        self.as_str()
-    }
-    #[inline]
-    fn is_str(_: Option<&Path>) -> bool { true }
-}
-
-impl GenericPathUnsafe for Path {
-    /// See `GenericPathUnsafe::from_vec_unchecked`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if not valid UTF-8.
-    #[inline]
-    unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Path {
-        let (prefix, path) = Path::normalize_(path.container_as_str().unwrap());
-        assert!(!path.is_empty());
-        let mut ret = Path{ repr: path, prefix: prefix, sepidx: None };
-        ret.update_sepidx();
-        ret
-    }
-
-    /// See `GenericPathUnsafe::set_filename_unchecked`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if not valid UTF-8.
-    unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
-        let filename = filename.container_as_str().unwrap();
-        match self.sepidx_or_prefix_len() {
-            None if ".." == self.repr => {
-                let mut s = String::with_capacity(3 + filename.len());
-                s.push_str("..");
-                s.push(SEP);
-                s.push_str(filename);
-                self.update_normalized(&s[]);
-            }
-            None => {
-                self.update_normalized(filename);
-            }
-            Some((_,idxa,end)) if &self.repr[idxa..end] == ".." => {
-                let mut s = String::with_capacity(end + 1 + filename.len());
-                s.push_str(&self.repr[..end]);
-                s.push(SEP);
-                s.push_str(filename);
-                self.update_normalized(&s[]);
-            }
-            Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => {
-                let mut s = String::with_capacity(idxb + filename.len());
-                s.push_str(&self.repr[..idxb]);
-                s.push_str(filename);
-                self.update_normalized(&s[]);
-            }
-            Some((idxb,_,_)) => {
-                let mut s = String::with_capacity(idxb + 1 + filename.len());
-                s.push_str(&self.repr[..idxb]);
-                s.push(SEP);
-                s.push_str(filename);
-                self.update_normalized(&s[]);
-            }
-        }
-    }
-
-    /// See `GenericPathUnsafe::push_unchecked`.
-    ///
-    /// Concatenating two Windows Paths is rather complicated.
-    /// For the most part, it will behave as expected, except in the case of
-    /// pushing a volume-relative path, e.g. `C:foo.txt`. Because we have no
-    /// concept of per-volume cwds like Windows does, we can't behave exactly
-    /// like Windows will. Instead, if the receiver is an absolute path on
-    /// the same volume as the new path, it will be treated as the cwd that
-    /// the new path is relative to. Otherwise, the new path will be treated
-    /// as if it were absolute and will replace the receiver outright.
-    unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
-        let path = path.container_as_str().unwrap();
-        fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool {
-            // assume prefix is Some(DiskPrefix)
-            let rest = &path[prefix_len(prefix)..];
-            !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char)
-        }
-        fn shares_volume(me: &Path, path: &str) -> bool {
-            // path is assumed to have a prefix of Some(DiskPrefix)
-            let repr = &me.repr[];
-            match me.prefix {
-                Some(DiskPrefix) => {
-                    repr.as_bytes()[0] == path.as_bytes()[0].to_ascii_uppercase()
-                }
-                Some(VerbatimDiskPrefix) => {
-                    repr.as_bytes()[4] == path.as_bytes()[0].to_ascii_uppercase()
-                }
-                _ => false
-            }
-        }
-        fn is_sep_(prefix: Option<PathPrefix>, u: u8) -> bool {
-            if prefix_is_verbatim(prefix) { is_sep_verbatim(u as char) }
-            else { is_sep(u as char) }
-        }
-
-        fn replace_path(me: &mut Path, path: &str, prefix: Option<PathPrefix>) {
-            let newpath = Path::normalize__(path, prefix);
-            me.repr = match newpath {
-                Some(p) => p,
-                None => String::from_str(path)
-            };
-            me.prefix = prefix;
-            me.update_sepidx();
-        }
-        fn append_path(me: &mut Path, path: &str) {
-            // appends a path that has no prefix
-            // if me is verbatim, we need to pre-normalize the new path
-            let path_ = if is_verbatim(me) { Path::normalize__(path, None) }
-                        else { None };
-            let pathlen = path_.as_ref().map_or(path.len(), |p| p.len());
-            let mut s = String::with_capacity(me.repr.len() + 1 + pathlen);
-            s.push_str(&me.repr[]);
-            let plen = me.prefix_len();
-            // if me is "C:" we don't want to add a path separator
-            match me.prefix {
-                Some(DiskPrefix) if me.repr.len() == plen => (),
-                _ if !(me.repr.len() > plen && me.repr.as_bytes()[me.repr.len()-1] == SEP_BYTE) => {
-                    s.push(SEP);
-                }
-                _ => ()
-            }
-            match path_ {
-                None => s.push_str(path),
-                Some(p) => s.push_str(&p[]),
-            };
-            me.update_normalized(&s[])
-        }
-
-        if !path.is_empty() {
-            let prefix = parse_prefix(path);
-            match prefix {
-                Some(DiskPrefix) if !is_vol_abs(path, prefix) && shares_volume(self, path) => {
-                    // cwd-relative path, self is on the same volume
-                    append_path(self, &path[prefix_len(prefix)..]);
-                }
-                Some(_) => {
-                    // absolute path, or cwd-relative and self is not same volume
-                    replace_path(self, path, prefix);
-                }
-                None if !path.is_empty() && is_sep_(self.prefix, path.as_bytes()[0]) => {
-                    // volume-relative path
-                    if self.prefix.is_some() {
-                        // truncate self down to the prefix, then append
-                        let n = self.prefix_len();
-                        self.repr.truncate(n);
-                        append_path(self, path);
-                    } else {
-                        // we have no prefix, so nothing to be relative to
-                        replace_path(self, path, prefix);
-                    }
-                }
-                None => {
-                    // relative path
-                    append_path(self, path);
-                }
-            }
-        }
-    }
-}
-
-impl GenericPath for Path {
-    #[inline]
-    fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
-        match path.container_as_str() {
-            None => None,
-            Some(ref s) => {
-                if contains_nul(s) {
-                    None
-                } else {
-                    Some(unsafe { GenericPathUnsafe::new_unchecked(*s) })
-                }
-            }
-        }
-    }
-
-    /// See `GenericPath::as_str` for info.
-    /// Always returns a `Some` value.
-    #[inline]
-    fn as_str<'a>(&'a self) -> Option<&'a str> {
-        Some(&self.repr[])
-    }
-
-    #[inline]
-    fn as_vec<'a>(&'a self) -> &'a [u8] {
-        self.repr.as_bytes()
-    }
-
-    #[inline]
-    fn into_vec(self) -> Vec<u8> {
-        self.repr.into_bytes()
-    }
-
-    #[inline]
-    fn dirname<'a>(&'a self) -> &'a [u8] {
-        self.dirname_str().unwrap().as_bytes()
-    }
-
-    /// See `GenericPath::dirname_str` for info.
-    /// Always returns a `Some` value.
-    fn dirname_str<'a>(&'a self) -> Option<&'a str> {
-        Some(match self.sepidx_or_prefix_len() {
-            None if ".." == self.repr => &self.repr[],
-            None => ".",
-            Some((_,idxa,end)) if &self.repr[idxa..end] == ".." => {
-                &self.repr[]
-            }
-            Some((idxb,_,end)) if &self.repr[idxb..end] == "\\" => {
-                &self.repr[]
-            }
-            Some((0,idxa,_)) => &self.repr[..idxa],
-            Some((idxb,idxa,_)) => {
-                match self.prefix {
-                    Some(DiskPrefix) | Some(VerbatimDiskPrefix) if idxb == self.prefix_len() => {
-                        &self.repr[..idxa]
-                    }
-                    _ => &self.repr[..idxb]
-                }
-            }
-        })
-    }
-
-    #[inline]
-    fn filename<'a>(&'a self) -> Option<&'a [u8]> {
-        self.filename_str().map(|x| x.as_bytes())
-    }
-
-    /// See `GenericPath::filename_str` for info.
-    /// Always returns a `Some` value if `filename` returns a `Some` value.
-    fn filename_str<'a>(&'a self) -> Option<&'a str> {
-        let repr = &self.repr[];
-        match self.sepidx_or_prefix_len() {
-            None if "." == repr || ".." == repr => None,
-            None => Some(repr),
-            Some((_,idxa,end)) if &repr[idxa..end] == ".." => None,
-            Some((_,idxa,end)) if idxa == end => None,
-            Some((_,idxa,end)) => Some(&repr[idxa..end])
-        }
-    }
-
-    /// See `GenericPath::filestem_str` for info.
-    /// Always returns a `Some` value if `filestem` returns a `Some` value.
-    #[inline]
-    fn filestem_str<'a>(&'a self) -> Option<&'a str> {
-        // filestem() returns a byte vector that's guaranteed valid UTF-8
-        self.filestem().map(|t| unsafe { mem::transmute(t) })
-    }
-
-    #[inline]
-    fn extension_str<'a>(&'a self) -> Option<&'a str> {
-        // extension() returns a byte vector that's guaranteed valid UTF-8
-        self.extension().map(|t| unsafe { mem::transmute(t) })
-    }
-
-    fn dir_path(&self) -> Path {
-        unsafe { GenericPathUnsafe::new_unchecked(self.dirname_str().unwrap()) }
-    }
-
-    #[inline]
-    fn pop(&mut self) -> bool {
-        match self.sepidx_or_prefix_len() {
-            None if "." == self.repr => false,
-            None => {
-                self.repr = String::from_str(".");
-                self.sepidx = None;
-                true
-            }
-            Some((idxb,idxa,end)) if idxb == idxa && idxb == end => false,
-            Some((idxb,_,end)) if &self.repr[idxb..end] == "\\" => false,
-            Some((idxb,idxa,_)) => {
-                let trunc = match self.prefix {
-                    Some(DiskPrefix) | Some(VerbatimDiskPrefix) | None => {
-                        let plen = self.prefix_len();
-                        if idxb == plen { idxa } else { idxb }
-                    }
-                    _ => idxb
-                };
-                self.repr.truncate(trunc);
-                self.update_sepidx();
-                true
-            }
-        }
-    }
-
-    fn root_path(&self) -> Option<Path> {
-        if self.prefix.is_some() {
-            Some(Path::new(match self.prefix {
-                Some(DiskPrefix) if self.is_absolute() => {
-                    &self.repr[..self.prefix_len()+1]
-                }
-                Some(VerbatimDiskPrefix) => {
-                    &self.repr[..self.prefix_len()+1]
-                }
-                _ => &self.repr[..self.prefix_len()]
-            }))
-        } else if is_vol_relative(self) {
-            Some(Path::new(&self.repr[..1]))
-        } else {
-            None
-        }
-    }
-
-    /// See `GenericPath::is_absolute` for info.
-    ///
-    /// A Windows Path is considered absolute only if it has a non-volume prefix,
-    /// or if it has a volume prefix and the path starts with '\'.
-    /// A path of `\foo` is not considered absolute because it's actually
-    /// relative to the "current volume". A separate method `Path::is_vol_relative`
-    /// is provided to indicate this case. Similarly a path of `C:foo` is not
-    /// considered absolute because it's relative to the cwd on volume C:. A
-    /// separate method `Path::is_cwd_relative` is provided to indicate this case.
-    #[inline]
-    fn is_absolute(&self) -> bool {
-        match self.prefix {
-            Some(DiskPrefix) => {
-                let rest = &self.repr[self.prefix_len()..];
-                rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE
-            }
-            Some(_) => true,
-            None => false
-        }
-    }
-
-    #[inline]
-    fn is_relative(&self) -> bool {
-        self.prefix.is_none() && !is_vol_relative(self)
-    }
-
-    fn is_ancestor_of(&self, other: &Path) -> bool {
-        if !self.equiv_prefix(other) {
-            false
-        } else if self.is_absolute() != other.is_absolute() ||
-                  is_vol_relative(self) != is_vol_relative(other) {
-            false
-        } else {
-            let mut ita = self.str_components().map(|x|x.unwrap());
-            let mut itb = other.str_components().map(|x|x.unwrap());
-            if "." == self.repr {
-                return itb.next() != Some("..");
-            }
-            loop {
-                match (ita.next(), itb.next()) {
-                    (None, _) => break,
-                    (Some(a), Some(b)) if a == b => { continue },
-                    (Some(a), _) if a == ".." => {
-                        // if ita contains only .. components, it's an ancestor
-                        return ita.all(|x| x == "..");
-                    }
-                    _ => return false
-                }
-            }
-            true
-        }
-    }
-
-    fn path_relative_from(&self, base: &Path) -> Option<Path> {
-        fn comp_requires_verbatim(s: &str) -> bool {
-            s == "." || s == ".." || s.contains_char(SEP2)
-        }
-
-        if !self.equiv_prefix(base) {
-            // prefixes differ
-            if self.is_absolute() {
-                Some(self.clone())
-            } else if self.prefix == Some(DiskPrefix) && base.prefix == Some(DiskPrefix) {
-                // both drives, drive letters must differ or they'd be equiv
-                Some(self.clone())
-            } else {
-                None
-            }
-        } else if self.is_absolute() != base.is_absolute() {
-            if self.is_absolute() {
-                Some(self.clone())
-            } else {
-                None
-            }
-        } else if is_vol_relative(self) != is_vol_relative(base) {
-            if is_vol_relative(self) {
-                Some(self.clone())
-            } else {
-                None
-            }
-        } else {
-            let mut ita = self.str_components().map(|x|x.unwrap());
-            let mut itb = base.str_components().map(|x|x.unwrap());
-            let mut comps = vec![];
-
-            let a_verb = is_verbatim(self);
-            let b_verb = is_verbatim(base);
-            loop {
-                match (ita.next(), itb.next()) {
-                    (None, None) => break,
-                    (Some(a), None) if a_verb && comp_requires_verbatim(a) => {
-                        return Some(self.clone())
-                    }
-                    (Some(a), None) => {
-                        comps.push(a);
-                        if !a_verb {
-                            comps.extend(ita.by_ref());
-                            break;
-                        }
-                    }
-                    (None, _) => comps.push(".."),
-                    (Some(a), Some(b)) if comps.is_empty() && a == b => (),
-                    (Some(a), Some(b)) if !b_verb && b == "." => {
-                        if a_verb && comp_requires_verbatim(a) {
-                            return Some(self.clone())
-                        } else { comps.push(a) }
-                    }
-                    (Some(_), Some(b)) if !b_verb && b == ".." => return None,
-                    (Some(a), Some(_)) if a_verb && comp_requires_verbatim(a) => {
-                        return Some(self.clone())
-                    }
-                    (Some(a), Some(_)) => {
-                        comps.push("..");
-                        for _ in itb.by_ref() {
-                            comps.push("..");
-                        }
-                        comps.push(a);
-                        if !a_verb {
-                            comps.extend(ita.by_ref());
-                            break;
-                        }
-                    }
-                }
-            }
-            Some(Path::new(comps.connect("\\")))
-        }
-    }
-
-    fn ends_with_path(&self, child: &Path) -> bool {
-        if !child.is_relative() { return false; }
-        let mut selfit = self.str_components().rev();
-        let mut childit = child.str_components().rev();
-        loop {
-            match (selfit.next(), childit.next()) {
-                (Some(a), Some(b)) => if a != b { return false; },
-                (Some(_), None) => break,
-                (None, Some(_)) => return false,
-                (None, None) => break
-            }
-        }
-        true
-    }
-}
-
-impl Path {
-    /// Returns a new `Path` from a `BytesContainer`.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the vector contains a `NUL`, or if it contains invalid UTF-8.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// println!("{}", Path::new(r"C:\some\path").display());
-    /// ```
-    #[inline]
-    pub fn new<T: BytesContainer>(path: T) -> Path {
-        GenericPath::new(path)
-    }
-
-    /// Returns a new `Some(Path)` from a `BytesContainer`.
-    ///
-    /// Returns `None` if the vector contains a `NUL`, or if it contains invalid UTF-8.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// let path = Path::new_opt(r"C:\some\path");
-    ///
-    /// match path {
-    ///     Some(path) => println!("{}", path.display()),
-    ///     None       => println!("There was a problem with your path."),
-    /// }
-    /// ```
-    #[inline]
-    pub fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
-        GenericPath::new_opt(path)
-    }
-
-    /// Returns an iterator that yields each component of the path in turn as a Option<&str>.
-    /// Every component is guaranteed to be Some.
-    /// Does not yield the path prefix (including server/share components in UNC paths).
-    /// Does not distinguish between volume-relative and relative paths, e.g.
-    /// \a\b\c and a\b\c.
-    /// Does not distinguish between absolute and cwd-relative paths, e.g.
-    /// C:\foo and C:foo.
-    pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
-        let repr = &self.repr[];
-        let s = match self.prefix {
-            Some(_) => {
-                let plen = self.prefix_len();
-                if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE {
-                    &repr[plen+1..]
-                } else { &repr[plen..] }
-            }
-            None if repr.as_bytes()[0] == SEP_BYTE => &repr[1..],
-            None => repr
-        };
-        let some: fn(&'a str) -> Option<&'a str> = Some; // coerce to fn ptr
-        let ret = s.split_terminator(SEP).map(some);
-        ret
-    }
-
-    /// Returns an iterator that yields each component of the path in turn as a &[u8].
-    /// See str_components() for details.
-    pub fn components<'a>(&'a self) -> Components<'a> {
-        fn convert<'a>(x: Option<&'a str>) -> &'a [u8] {
-            #![inline]
-            x.unwrap().as_bytes()
-        }
-        let convert: for<'b> fn(Option<&'b str>) -> &'b [u8] = convert; // coerce to fn ptr
-        self.str_components().map(convert)
-    }
-
-    fn equiv_prefix(&self, other: &Path) -> bool {
-        let s_repr = &self.repr[];
-        let o_repr = &other.repr[];
-        match (self.prefix, other.prefix) {
-            (Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
-                self.is_absolute() &&
-                    s_repr.as_bytes()[0].to_ascii_lowercase() ==
-                        o_repr.as_bytes()[4].to_ascii_lowercase()
-            }
-            (Some(VerbatimDiskPrefix), Some(DiskPrefix)) => {
-                other.is_absolute() &&
-                    s_repr.as_bytes()[4].to_ascii_lowercase() ==
-                        o_repr.as_bytes()[0].to_ascii_lowercase()
-            }
-            (Some(VerbatimDiskPrefix), Some(VerbatimDiskPrefix)) => {
-                s_repr.as_bytes()[4].to_ascii_lowercase() ==
-                    o_repr.as_bytes()[4].to_ascii_lowercase()
-            }
-            (Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => {
-                &s_repr[2..self.prefix_len()] == &o_repr[8..other.prefix_len()]
-            }
-            (Some(VerbatimUNCPrefix(_,_)), Some(UNCPrefix(_,_))) => {
-                &s_repr[8..self.prefix_len()] == &o_repr[2..other.prefix_len()]
-            }
-            (None, None) => true,
-            (a, b) if a == b => {
-                &s_repr[..self.prefix_len()] == &o_repr[..other.prefix_len()]
-            }
-            _ => false
-        }
-    }
-
-    fn normalize_(s: &str) -> (Option<PathPrefix>, String) {
-        // make borrowck happy
-        let (prefix, val) = {
-            let prefix = parse_prefix(s);
-            let path = Path::normalize__(s, prefix);
-            (prefix, path)
-        };
-        (prefix, match val {
-            None => s.to_string(),
-            Some(val) => val
-        })
-    }
-
-    fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
-        if prefix_is_verbatim(prefix) {
-            // don't do any normalization
-            match prefix {
-                Some(VerbatimUNCPrefix(x, 0)) if s.len() == 8 + x => {
-                    // the server component has no trailing '\'
-                    let mut s = String::from_str(s);
-                    s.push(SEP);
-                    Some(s)
-                }
-                _ => None
-            }
-        } else {
-            let (is_abs, comps) = normalize_helper(s, prefix);
-            let mut comps = comps;
-            match (comps.is_some(),prefix) {
-                (false, Some(DiskPrefix)) => {
-                    if s.as_bytes()[0] >= b'a' && s.as_bytes()[0] <= b'z' {
-                        comps = Some(vec![]);
-                    }
-                }
-                (false, Some(VerbatimDiskPrefix)) => {
-                    if s.as_bytes()[4] >= b'a' && s.as_bytes()[0] <= b'z' {
-                        comps = Some(vec![]);
-                    }
-                }
-                _ => ()
-            }
-            match comps {
-                None => None,
-                Some(comps) => {
-                    if prefix.is_some() && comps.is_empty() {
-                        match prefix.unwrap() {
-                            DiskPrefix => {
-                                let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(&s[..len]);
-                                unsafe {
-                                    let v = s.as_mut_vec();
-                                    v[0] = (*v)[0].to_ascii_uppercase();
-                                }
-                                if is_abs {
-                                    // normalize C:/ to C:\
-                                    unsafe {
-                                        s.as_mut_vec()[2] = SEP_BYTE;
-                                    }
-                                }
-                                Some(s)
-                            }
-                            VerbatimDiskPrefix => {
-                                let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(&s[..len]);
-                                unsafe {
-                                    let v = s.as_mut_vec();
-                                    v[4] = (*v)[4].to_ascii_uppercase();
-                                }
-                                Some(s)
-                            }
-                            _ => {
-                                let plen = prefix_len(prefix);
-                                if s.len() > plen {
-                                    Some(String::from_str(&s[..plen]))
-                                } else { None }
-                            }
-                        }
-                    } else if is_abs && comps.is_empty() {
-                        Some(repeat(SEP).take(1).collect())
-                    } else {
-                        let prefix_ = &s[..prefix_len(prefix)];
-                        let n = prefix_.len() +
-                                if is_abs { comps.len() } else { comps.len() - 1} +
-                                comps.iter().map(|v| v.len()).sum();
-                        let mut s = String::with_capacity(n);
-                        match prefix {
-                            Some(DiskPrefix) => {
-                                s.push(prefix_.as_bytes()[0].to_ascii_uppercase() as char);
-                                s.push(':');
-                            }
-                            Some(VerbatimDiskPrefix) => {
-                                s.push_str(&prefix_[..4]);
-                                s.push(prefix_.as_bytes()[4].to_ascii_uppercase() as char);
-                                s.push_str(&prefix_[5..]);
-                            }
-                            Some(UNCPrefix(a,b)) => {
-                                s.push_str("\\\\");
-                                s.push_str(&prefix_[2..a+2]);
-                                s.push(SEP);
-                                s.push_str(&prefix_[3+a..3+a+b]);
-                            }
-                            Some(_) => s.push_str(prefix_),
-                            None => ()
-                        }
-                        let mut it = comps.into_iter();
-                        if !is_abs {
-                            match it.next() {
-                                None => (),
-                                Some(comp) => s.push_str(comp)
-                            }
-                        }
-                        for comp in it {
-                            s.push(SEP);
-                            s.push_str(comp);
-                        }
-                        Some(s)
-                    }
-                }
-            }
-        }
-    }
-
-    fn update_sepidx(&mut self) {
-        let s = if self.has_nonsemantic_trailing_slash() {
-                    &self.repr[..self.repr.len()-1]
-                } else { &self.repr[] };
-        let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) {
-            is_sep
-        } else {
-            is_sep_verbatim
-        };
-        let idx = s.rfind(sep_test);
-        let prefixlen = self.prefix_len();
-        self.sepidx = idx.and_then(|x| if x < prefixlen { None } else { Some(x) });
-    }
-
-    fn prefix_len(&self) -> uint {
-        prefix_len(self.prefix)
-    }
-
-    // Returns a tuple (before, after, end) where before is the index of the separator
-    // and after is the index just after the separator.
-    // end is the length of the string, normally, or the index of the final character if it is
-    // a non-semantic trailing separator in a verbatim string.
-    // If the prefix is considered the separator, before and after are the same.
-    fn sepidx_or_prefix_len(&self) -> Option<(uint,uint,uint)> {
-        match self.sepidx {
-            None => match self.prefix_len() { 0 => None, x => Some((x,x,self.repr.len())) },
-            Some(x) => {
-                if self.has_nonsemantic_trailing_slash() {
-                    Some((x,x+1,self.repr.len()-1))
-                } else { Some((x,x+1,self.repr.len())) }
-            }
-        }
-    }
-
-    fn has_nonsemantic_trailing_slash(&self) -> bool {
-        is_verbatim(self) && self.repr.len() > self.prefix_len()+1 &&
-            self.repr.as_bytes()[self.repr.len()-1] == SEP_BYTE
-    }
-
-    fn update_normalized(&mut self, s: &str) {
-        let (prefix, path) = Path::normalize_(s);
-        self.repr = path;
-        self.prefix = prefix;
-        self.update_sepidx();
-    }
-}
-
-/// Returns whether the path is considered "volume-relative", which means a path
-/// that looks like "\foo". Paths of this form are relative to the current volume,
-/// but absolute within that volume.
-#[inline]
-pub fn is_vol_relative(path: &Path) -> bool {
-    path.prefix.is_none() && is_sep_byte(&path.repr.as_bytes()[0])
-}
-
-/// Returns whether the path is considered "cwd-relative", which means a path
-/// with a volume prefix that is not absolute. This look like "C:foo.txt". Paths
-/// of this form are relative to the cwd on the given volume.
-#[inline]
-pub fn is_cwd_relative(path: &Path) -> bool {
-    path.prefix == Some(DiskPrefix) && !path.is_absolute()
-}
-
-/// Returns the PathPrefix for this Path
-#[inline]
-pub fn prefix(path: &Path) -> Option<PathPrefix> {
-    path.prefix
-}
-
-/// Returns whether the Path's prefix is a verbatim prefix, i.e. `\\?\`
-#[inline]
-pub fn is_verbatim(path: &Path) -> bool {
-    prefix_is_verbatim(path.prefix)
-}
-
-/// Returns the non-verbatim equivalent of the input path, if possible.
-/// If the input path is a device namespace path, None is returned.
-/// If the input path is not verbatim, it is returned as-is.
-/// If the input path is verbatim, but the same path can be expressed as
-/// non-verbatim, the non-verbatim version is returned.
-/// Otherwise, None is returned.
-pub fn make_non_verbatim(path: &Path) -> Option<Path> {
-    let repr = &path.repr[];
-    let new_path = match path.prefix {
-        Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None,
-        Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()),
-        Some(VerbatimDiskPrefix) => {
-            // \\?\D:\
-            Path::new(&repr[4..])
-        }
-        Some(VerbatimUNCPrefix(_,_)) => {
-            // \\?\UNC\server\share
-            Path::new(format!(r"\{}", &repr[7..]))
-        }
-    };
-    if new_path.prefix.is_none() {
-        // \\?\UNC\server is a VerbatimUNCPrefix
-        // but \\server is nothing
-        return None;
-    }
-    // now ensure normalization didn't change anything
-    if &repr[path.prefix_len()..] == &new_path.repr[new_path.prefix_len()..] {
-        Some(new_path)
-    } else {
-        None
-    }
-}
-
-/// The standard path separator character
-pub const SEP: char = '\\';
-/// The standard path separator byte
-pub const SEP_BYTE: u8 = SEP as u8;
-
-/// The alternative path separator character
-pub const SEP2: char = '/';
-/// The alternative path separator character
-pub const SEP2_BYTE: u8 = SEP2 as u8;
-
-/// Returns whether the given char is a path separator.
-/// Allows both the primary separator '\' and the alternative separator '/'.
-#[inline]
-pub fn is_sep(c: char) -> bool {
-    c == SEP || c == SEP2
-}
-
-/// Returns whether the given char is a path separator.
-/// Only allows the primary separator '\'; use is_sep to allow '/'.
-#[inline]
-pub fn is_sep_verbatim(c: char) -> bool {
-    c == SEP
-}
-
-/// Returns whether the given byte is a path separator.
-/// Allows both the primary separator '\' and the alternative separator '/'.
-#[inline]
-pub fn is_sep_byte(u: &u8) -> bool {
-    *u == SEP_BYTE || *u == SEP2_BYTE
-}
-
-/// Returns whether the given byte is a path separator.
-/// Only allows the primary separator '\'; use is_sep_byte to allow '/'.
-#[inline]
-pub fn is_sep_byte_verbatim(u: &u8) -> bool {
-    *u == SEP_BYTE
-}
-
-/// Prefix types for Path
-#[derive(Copy, PartialEq, Clone, Debug)]
-pub enum PathPrefix {
-    /// Prefix `\\?\`, uint is the length of the following component
-    VerbatimPrefix(uint),
-    /// Prefix `\\?\UNC\`, uints are the lengths of the UNC components
-    VerbatimUNCPrefix(uint, uint),
-    /// Prefix `\\?\C:\` (for any alphabetic character)
-    VerbatimDiskPrefix,
-    /// Prefix `\\.\`, uint is the length of the following component
-    DeviceNSPrefix(uint),
-    /// UNC prefix `\\server\share`, uints are the lengths of the server/share
-    UNCPrefix(uint, uint),
-    /// Prefix `C:` for any alphabetic character
-    DiskPrefix
-}
-
-fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
-    if path.starts_with("\\\\") {
-        // \\
-        path = &path[2..];
-        if path.starts_with("?\\") {
-            // \\?\
-            path = &path[2..];
-            if path.starts_with("UNC\\") {
-                // \\?\UNC\server\share
-                path = &path[4..];
-                let (idx_a, idx_b) = match parse_two_comps(path, is_sep_verbatim) {
-                    Some(x) => x,
-                    None => (path.len(), 0)
-                };
-                return Some(VerbatimUNCPrefix(idx_a, idx_b));
-            } else {
-                // \\?\path
-                let idx = path.find('\\');
-                if idx == Some(2) && path.as_bytes()[1] == b':' {
-                    let c = path.as_bytes()[0];
-                    if c.is_ascii() && (c as char).is_alphabetic() {
-                        // \\?\C:\ path
-                        return Some(VerbatimDiskPrefix);
-                    }
-                }
-                let idx = idx.unwrap_or(path.len());
-                return Some(VerbatimPrefix(idx));
-            }
-        } else if path.starts_with(".\\") {
-            // \\.\path
-            path = &path[2..];
-            let idx = path.find('\\').unwrap_or(path.len());
-            return Some(DeviceNSPrefix(idx));
-        }
-        match parse_two_comps(path, is_sep) {
-            Some((idx_a, idx_b)) if idx_a > 0 && idx_b > 0 => {
-                // \\server\share
-                return Some(UNCPrefix(idx_a, idx_b));
-            }
-            _ => ()
-        }
-    } else if path.len() > 1 && path.as_bytes()[1] == b':' {
-        // C:
-        let c = path.as_bytes()[0];
-        if c.is_ascii() && (c as char).is_alphabetic() {
-            return Some(DiskPrefix);
-        }
-    }
-    return None;
-
-    fn parse_two_comps(mut path: &str, f: fn(char) -> bool) -> Option<(uint, uint)> {
-        let idx_a = match path.find(f) {
-            None => return None,
-            Some(x) => x
-        };
-        path = &path[idx_a+1..];
-        let idx_b = path.find(f).unwrap_or(path.len());
-        Some((idx_a, idx_b))
-    }
-}
-
-// None result means the string didn't need normalizing
-fn normalize_helper<'a>(s: &'a str, prefix: Option<PathPrefix>) -> (bool, Option<Vec<&'a str>>) {
-    let f: fn(char) -> bool = if !prefix_is_verbatim(prefix) {
-        is_sep
-    } else {
-        is_sep_verbatim
-    };
-    let is_abs = s.len() > prefix_len(prefix) && f(s.char_at(prefix_len(prefix)));
-    let s_ = &s[prefix_len(prefix)..];
-    let s_ = if is_abs { &s_[1..] } else { s_ };
-
-    if is_abs && s_.is_empty() {
-        return (is_abs, match prefix {
-            Some(DiskPrefix) | None => (if is_sep_verbatim(s.char_at(prefix_len(prefix))) { None }
-                                        else { Some(vec![]) }),
-            Some(_) => Some(vec![]), // need to trim the trailing separator
-        });
-    }
-    let mut comps: Vec<&'a str> = vec![];
-    let mut n_up = 0u;
-    let mut changed = false;
-    for comp in s_.split(f) {
-        if comp.is_empty() { changed = true }
-        else if comp == "." { changed = true }
-        else if comp == ".." {
-            let has_abs_prefix = match prefix {
-                Some(DiskPrefix) => false,
-                Some(_) => true,
-                None => false
-            };
-            if (is_abs || has_abs_prefix) && comps.is_empty() { changed = true }
-            else if comps.len() == n_up { comps.push(".."); n_up += 1 }
-            else { comps.pop().unwrap(); changed = true }
-        } else { comps.push(comp) }
-    }
-    if !changed && !prefix_is_verbatim(prefix) {
-        changed = s.find(is_sep).is_some();
-    }
-    if changed {
-        if comps.is_empty() && !is_abs && prefix.is_none() {
-            if s == "." {
-                return (is_abs, None);
-            }
-            comps.push(".");
-        }
-        (is_abs, Some(comps))
-    } else {
-        (is_abs, None)
-    }
-}
-
-fn prefix_is_verbatim(p: Option<PathPrefix>) -> bool {
-    match p {
-        Some(VerbatimPrefix(_)) | Some(VerbatimUNCPrefix(_,_)) | Some(VerbatimDiskPrefix) => true,
-        Some(DeviceNSPrefix(_)) => true, // not really sure, but I think so
-        _ => false
-    }
-}
-
-fn prefix_len(p: Option<PathPrefix>) -> uint {
-    match p {
-        None => 0,
-        Some(VerbatimPrefix(x)) => 4 + x,
-        Some(VerbatimUNCPrefix(x,y)) => 8 + x + 1 + y,
-        Some(VerbatimDiskPrefix) => 6,
-        Some(UNCPrefix(x,y)) => 2 + x + 1 + y,
-        Some(DeviceNSPrefix(x)) => 4 + x,
-        Some(DiskPrefix) => 2
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::PathPrefix::*;
-    use super::parse_prefix;
-    use super::*;
-
-    use clone::Clone;
-    use iter::IteratorExt;
-    use option::Option::{self, Some, None};
-    use path::GenericPath;
-    use slice::{AsSlice, SliceExt};
-    use str::Str;
-    use string::ToString;
-    use vec::Vec;
-
-    macro_rules! t {
-        (s: $path:expr, $exp:expr) => (
-            {
-                let path = $path;
-                assert_eq!(path.as_str(), Some($exp));
-            }
-        );
-        (v: $path:expr, $exp:expr) => (
-            {
-                let path = $path;
-                assert_eq!(path.as_vec(), $exp);
-            }
-        )
-    }
-
-    #[test]
-    fn test_parse_prefix() {
-        macro_rules! t {
-            ($path:expr, $exp:expr) => (
-                {
-                    let path = $path;
-                    let exp = $exp;
-                    let res = parse_prefix(path);
-                    assert_eq!(res, exp);
-                }
-            )
-        }
-
-        t!("\\\\SERVER\\share\\foo", Some(UNCPrefix(6,5)));
-        t!("\\\\", None);
-        t!("\\\\SERVER", None);
-        t!("\\\\SERVER\\", None);
-        t!("\\\\SERVER\\\\", None);
-        t!("\\\\SERVER\\\\foo", None);
-        t!("\\\\SERVER\\share", Some(UNCPrefix(6,5)));
-        t!("\\\\SERVER/share/foo", Some(UNCPrefix(6,5)));
-        t!("\\\\SERVER\\share/foo", Some(UNCPrefix(6,5)));
-        t!("//SERVER/share/foo", None);
-        t!("\\\\\\a\\b\\c", None);
-        t!("\\\\?\\a\\b\\c", Some(VerbatimPrefix(1)));
-        t!("\\\\?\\a/b/c", Some(VerbatimPrefix(5)));
-        t!("//?/a/b/c", None);
-        t!("\\\\.\\a\\b", Some(DeviceNSPrefix(1)));
-        t!("\\\\.\\a/b", Some(DeviceNSPrefix(3)));
-        t!("//./a/b", None);
-        t!("\\\\?\\UNC\\server\\share\\foo", Some(VerbatimUNCPrefix(6,5)));
-        t!("\\\\?\\UNC\\\\share\\foo", Some(VerbatimUNCPrefix(0,5)));
-        t!("\\\\?\\UNC\\", Some(VerbatimUNCPrefix(0,0)));
-        t!("\\\\?\\UNC\\server/share/foo", Some(VerbatimUNCPrefix(16,0)));
-        t!("\\\\?\\UNC\\server", Some(VerbatimUNCPrefix(6,0)));
-        t!("\\\\?\\UNC\\server\\", Some(VerbatimUNCPrefix(6,0)));
-        t!("\\\\?\\UNC/server/share", Some(VerbatimPrefix(16)));
-        t!("\\\\?\\UNC", Some(VerbatimPrefix(3)));
-        t!("\\\\?\\C:\\a\\b.txt", Some(VerbatimDiskPrefix));
-        t!("\\\\?\\z:\\", Some(VerbatimDiskPrefix));
-        t!("\\\\?\\C:", Some(VerbatimPrefix(2)));
-        t!("\\\\?\\C:a.txt", Some(VerbatimPrefix(7)));
-        t!("\\\\?\\C:a\\b.txt", Some(VerbatimPrefix(3)));
-        t!("\\\\?\\C:/a", Some(VerbatimPrefix(4)));
-        t!("C:\\foo", Some(DiskPrefix));
-        t!("z:/foo", Some(DiskPrefix));
-        t!("d:", Some(DiskPrefix));
-        t!("ab:", None);
-        t!("ü:\\foo", None);
-        t!("3:\\foo", None);
-        t!(" :\\foo", None);
-        t!("::\\foo", None);
-        t!("\\\\?\\C:", Some(VerbatimPrefix(2)));
-        t!("\\\\?\\z:\\", Some(VerbatimDiskPrefix));
-        t!("\\\\?\\ab:\\", Some(VerbatimPrefix(3)));
-        t!("\\\\?\\C:\\a", Some(VerbatimDiskPrefix));
-        t!("\\\\?\\C:/a", Some(VerbatimPrefix(4)));
-        t!("\\\\?\\C:\\a/b", Some(VerbatimDiskPrefix));
-    }
-
-    #[test]
-    fn test_paths() {
-        let empty: &[u8] = &[];
-        t!(v: Path::new(empty), b".");
-        t!(v: Path::new(b"\\"), b"\\");
-        t!(v: Path::new(b"a\\b\\c"), b"a\\b\\c");
-
-        t!(s: Path::new(""), ".");
-        t!(s: Path::new("\\"), "\\");
-        t!(s: Path::new("hi"), "hi");
-        t!(s: Path::new("hi\\"), "hi");
-        t!(s: Path::new("\\lib"), "\\lib");
-        t!(s: Path::new("\\lib\\"), "\\lib");
-        t!(s: Path::new("hi\\there"), "hi\\there");
-        t!(s: Path::new("hi\\there.txt"), "hi\\there.txt");
-        t!(s: Path::new("/"), "\\");
-        t!(s: Path::new("hi/"), "hi");
-        t!(s: Path::new("/lib"), "\\lib");
-        t!(s: Path::new("/lib/"), "\\lib");
-        t!(s: Path::new("hi/there"), "hi\\there");
-
-        t!(s: Path::new("hi\\there\\"), "hi\\there");
-        t!(s: Path::new("hi\\..\\there"), "there");
-        t!(s: Path::new("hi/../there"), "there");
-        t!(s: Path::new("..\\hi\\there"), "..\\hi\\there");
-        t!(s: Path::new("\\..\\hi\\there"), "\\hi\\there");
-        t!(s: Path::new("/../hi/there"), "\\hi\\there");
-        t!(s: Path::new("foo\\.."), ".");
-        t!(s: Path::new("\\foo\\.."), "\\");
-        t!(s: Path::new("\\foo\\..\\.."), "\\");
-        t!(s: Path::new("\\foo\\..\\..\\bar"), "\\bar");
-        t!(s: Path::new("\\.\\hi\\.\\there\\."), "\\hi\\there");
-        t!(s: Path::new("\\.\\hi\\.\\there\\.\\.."), "\\hi");
-        t!(s: Path::new("foo\\..\\.."), "..");
-        t!(s: Path::new("foo\\..\\..\\.."), "..\\..");
-        t!(s: Path::new("foo\\..\\..\\bar"), "..\\bar");
-
-        assert_eq!(Path::new(b"foo\\bar").into_vec(), b"foo\\bar");
-        assert_eq!(Path::new(b"\\foo\\..\\..\\bar").into_vec(), b"\\bar");
-
-        t!(s: Path::new("\\\\a"), "\\a");
-        t!(s: Path::new("\\\\a\\"), "\\a");
-        t!(s: Path::new("\\\\a\\b"), "\\\\a\\b");
-        t!(s: Path::new("\\\\a\\b\\"), "\\\\a\\b");
-        t!(s: Path::new("\\\\a\\b/"), "\\\\a\\b");
-        t!(s: Path::new("\\\\\\b"), "\\b");
-        t!(s: Path::new("\\\\a\\\\b"), "\\a\\b");
-        t!(s: Path::new("\\\\a\\b\\c"), "\\\\a\\b\\c");
-        t!(s: Path::new("\\\\server\\share/path"), "\\\\server\\share\\path");
-        t!(s: Path::new("\\\\server/share/path"), "\\\\server\\share\\path");
-        t!(s: Path::new("C:a\\b.txt"), "C:a\\b.txt");
-        t!(s: Path::new("C:a/b.txt"), "C:a\\b.txt");
-        t!(s: Path::new("z:\\a\\b.txt"), "Z:\\a\\b.txt");
-        t!(s: Path::new("z:/a/b.txt"), "Z:\\a\\b.txt");
-        t!(s: Path::new("ab:/a/b.txt"), "ab:\\a\\b.txt");
-        t!(s: Path::new("C:\\"), "C:\\");
-        t!(s: Path::new("C:"), "C:");
-        t!(s: Path::new("q:"), "Q:");
-        t!(s: Path::new("C:/"), "C:\\");
-        t!(s: Path::new("C:\\foo\\.."), "C:\\");
-        t!(s: Path::new("C:foo\\.."), "C:");
-        t!(s: Path::new("C:\\a\\"), "C:\\a");
-        t!(s: Path::new("C:\\a/"), "C:\\a");
-        t!(s: Path::new("C:\\a\\b\\"), "C:\\a\\b");
-        t!(s: Path::new("C:\\a\\b/"), "C:\\a\\b");
-        t!(s: Path::new("C:a\\"), "C:a");
-        t!(s: Path::new("C:a/"), "C:a");
-        t!(s: Path::new("C:a\\b\\"), "C:a\\b");
-        t!(s: Path::new("C:a\\b/"), "C:a\\b");
-        t!(s: Path::new("\\\\?\\z:\\a\\b.txt"), "\\\\?\\z:\\a\\b.txt");
-        t!(s: Path::new("\\\\?\\C:/a/b.txt"), "\\\\?\\C:/a/b.txt");
-        t!(s: Path::new("\\\\?\\C:\\a/b.txt"), "\\\\?\\C:\\a/b.txt");
-        t!(s: Path::new("\\\\?\\test\\a\\b.txt"), "\\\\?\\test\\a\\b.txt");
-        t!(s: Path::new("\\\\?\\foo\\bar\\"), "\\\\?\\foo\\bar\\");
-        t!(s: Path::new("\\\\.\\foo\\bar"), "\\\\.\\foo\\bar");
-        t!(s: Path::new("\\\\.\\"), "\\\\.\\");
-        t!(s: Path::new("\\\\?\\UNC\\server\\share\\foo"), "\\\\?\\UNC\\server\\share\\foo");
-        t!(s: Path::new("\\\\?\\UNC\\server/share"), "\\\\?\\UNC\\server/share\\");
-        t!(s: Path::new("\\\\?\\UNC\\server"), "\\\\?\\UNC\\server\\");
-        t!(s: Path::new("\\\\?\\UNC\\"), "\\\\?\\UNC\\\\");
-        t!(s: Path::new("\\\\?\\UNC"), "\\\\?\\UNC");
-
-        // I'm not sure whether \\.\foo/bar should normalize to \\.\foo\bar
-        // as information is sparse and this isn't really googleable.
-        // I'm going to err on the side of not normalizing it, as this skips the filesystem
-        t!(s: Path::new("\\\\.\\foo/bar"), "\\\\.\\foo/bar");
-        t!(s: Path::new("\\\\.\\foo\\bar"), "\\\\.\\foo\\bar");
-    }
-
-    #[test]
-    fn test_opt_paths() {
-        assert!(Path::new_opt(b"foo\\bar\0") == None);
-        assert!(Path::new_opt(b"foo\\bar\x80") == None);
-        t!(v: Path::new_opt(b"foo\\bar").unwrap(), b"foo\\bar");
-        assert!(Path::new_opt("foo\\bar\0") == None);
-        t!(s: Path::new_opt("foo\\bar").unwrap(), "foo\\bar");
-    }
-
-    #[test]
-    fn test_null_byte() {
-        use thread::Thread;
-        let result = Thread::scoped(move|| {
-            Path::new(b"foo/bar\0")
-        }).join();
-        assert!(result.is_err());
-
-        let result = Thread::scoped(move|| {
-            Path::new("test").set_filename(b"f\0o")
-        }).join();
-        assert!(result.is_err());
-
-        let result = Thread::scoped(move || {
-            Path::new("test").push(b"f\0o");
-        }).join();
-        assert!(result.is_err());
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_not_utf8_panics() {
-        Path::new(b"hello\x80.txt");
-    }
-
-    #[test]
-    fn test_display_str() {
-        let path = Path::new("foo");
-        assert_eq!(path.display().to_string(), "foo");
-        let path = Path::new(b"\\");
-        assert_eq!(path.filename_display().to_string(), "");
-
-        let path = Path::new("foo");
-        let mo = path.display().as_cow();
-        assert_eq!(mo.as_slice(), "foo");
-        let path = Path::new(b"\\");
-        let mo = path.filename_display().as_cow();
-        assert_eq!(mo.as_slice(), "");
-    }
-
-    #[test]
-    fn test_display() {
-        macro_rules! t {
-            ($path:expr, $exp:expr, $expf:expr) => (
-                {
-                    let path = Path::new($path);
-                    let f = format!("{}", path.display());
-                    assert_eq!(f, $exp);
-                    let f = format!("{}", path.filename_display());
-                    assert_eq!(f, $expf);
-                }
-            )
-        }
-
-        t!("foo", "foo", "foo");
-        t!("foo\\bar", "foo\\bar", "bar");
-        t!("\\", "\\", "");
-    }
-
-    #[test]
-    fn test_components() {
-        macro_rules! t {
-            (s: $path:expr, $op:ident, $exp:expr) => (
-                {
-                    let path = $path;
-                    let path = Path::new(path);
-                    assert_eq!(path.$op(), Some($exp));
-                }
-            );
-            (s: $path:expr, $op:ident, $exp:expr, opt) => (
-                {
-                    let path = $path;
-                    let path = Path::new(path);
-                    let left = path.$op();
-                    assert_eq!(left, $exp);
-                }
-            );
-            (v: $path:expr, $op:ident, $exp:expr) => (
-                {
-                    let path = $path;
-                    let path = Path::new(path);
-                    assert_eq!(path.$op(), $exp);
-                }
-            )
-        }
-
-        t!(v: b"a\\b\\c", filename, Some(b"c"));
-        t!(s: "a\\b\\c", filename_str, "c");
-        t!(s: "\\a\\b\\c", filename_str, "c");
-        t!(s: "a", filename_str, "a");
-        t!(s: "\\a", filename_str, "a");
-        t!(s: ".", filename_str, None, opt);
-        t!(s: "\\", filename_str, None, opt);
-        t!(s: "..", filename_str, None, opt);
-        t!(s: "..\\..", filename_str, None, opt);
-        t!(s: "c:\\foo.txt", filename_str, "foo.txt");
-        t!(s: "C:\\", filename_str, None, opt);
-        t!(s: "C:", filename_str, None, opt);
-        t!(s: "\\\\server\\share\\foo.txt", filename_str, "foo.txt");
-        t!(s: "\\\\server\\share", filename_str, None, opt);
-        t!(s: "\\\\server", filename_str, "server");
-        t!(s: "\\\\?\\bar\\foo.txt", filename_str, "foo.txt");
-        t!(s: "\\\\?\\bar", filename_str, None, opt);
-        t!(s: "\\\\?\\", filename_str, None, opt);
-        t!(s: "\\\\?\\UNC\\server\\share\\foo.txt", filename_str, "foo.txt");
-        t!(s: "\\\\?\\UNC\\server", filename_str, None, opt);
-        t!(s: "\\\\?\\UNC\\", filename_str, None, opt);
-        t!(s: "\\\\?\\C:\\foo.txt", filename_str, "foo.txt");
-        t!(s: "\\\\?\\C:\\", filename_str, None, opt);
-        t!(s: "\\\\?\\C:", filename_str, None, opt);
-        t!(s: "\\\\?\\foo/bar", filename_str, None, opt);
-        t!(s: "\\\\?\\C:/foo", filename_str, None, opt);
-        t!(s: "\\\\.\\foo\\bar", filename_str, "bar");
-        t!(s: "\\\\.\\foo", filename_str, None, opt);
-        t!(s: "\\\\.\\foo/bar", filename_str, None, opt);
-        t!(s: "\\\\.\\foo\\bar/baz", filename_str, "bar/baz");
-        t!(s: "\\\\.\\", filename_str, None, opt);
-        t!(s: "\\\\?\\a\\b\\", filename_str, "b");
-
-        t!(v: b"a\\b\\c", dirname, b"a\\b");
-        t!(s: "a\\b\\c", dirname_str, "a\\b");
-        t!(s: "\\a\\b\\c", dirname_str, "\\a\\b");
-        t!(s: "a", dirname_str, ".");
-        t!(s: "\\a", dirname_str, "\\");
-        t!(s: ".", dirname_str, ".");
-        t!(s: "\\", dirname_str, "\\");
-        t!(s: "..", dirname_str, "..");
-        t!(s: "..\\..", dirname_str, "..\\..");
-        t!(s: "c:\\foo.txt", dirname_str, "C:\\");
-        t!(s: "C:\\", dirname_str, "C:\\");
-        t!(s: "C:", dirname_str, "C:");
-        t!(s: "C:foo.txt", dirname_str, "C:");
-        t!(s: "\\\\server\\share\\foo.txt", dirname_str, "\\\\server\\share");
-        t!(s: "\\\\server\\share", dirname_str, "\\\\server\\share");
-        t!(s: "\\\\server", dirname_str, "\\");
-        t!(s: "\\\\?\\bar\\foo.txt", dirname_str, "\\\\?\\bar");
-        t!(s: "\\\\?\\bar", dirname_str, "\\\\?\\bar");
-        t!(s: "\\\\?\\", dirname_str, "\\\\?\\");
-        t!(s: "\\\\?\\UNC\\server\\share\\foo.txt", dirname_str, "\\\\?\\UNC\\server\\share");
-        t!(s: "\\\\?\\UNC\\server", dirname_str, "\\\\?\\UNC\\server\\");
-        t!(s: "\\\\?\\UNC\\", dirname_str, "\\\\?\\UNC\\\\");
-        t!(s: "\\\\?\\C:\\foo.txt", dirname_str, "\\\\?\\C:\\");
-        t!(s: "\\\\?\\C:\\", dirname_str, "\\\\?\\C:\\");
-        t!(s: "\\\\?\\C:", dirname_str, "\\\\?\\C:");
-        t!(s: "\\\\?\\C:/foo/bar", dirname_str, "\\\\?\\C:/foo/bar");
-        t!(s: "\\\\?\\foo/bar", dirname_str, "\\\\?\\foo/bar");
-        t!(s: "\\\\.\\foo\\bar", dirname_str, "\\\\.\\foo");
-        t!(s: "\\\\.\\foo", dirname_str, "\\\\.\\foo");
-        t!(s: "\\\\?\\a\\b\\", dirname_str, "\\\\?\\a");
-
-        t!(v: b"hi\\there.txt", filestem, Some(b"there"));
-        t!(s: "hi\\there.txt", filestem_str, "there");
-        t!(s: "hi\\there", filestem_str, "there");
-        t!(s: "there.txt", filestem_str, "there");
-        t!(s: "there", filestem_str, "there");
-        t!(s: ".", filestem_str, None, opt);
-        t!(s: "\\", filestem_str, None, opt);
-        t!(s: "foo\\.bar", filestem_str, ".bar");
-        t!(s: ".bar", filestem_str, ".bar");
-        t!(s: "..bar", filestem_str, ".");
-        t!(s: "hi\\there..txt", filestem_str, "there.");
-        t!(s: "..", filestem_str, None, opt);
-        t!(s: "..\\..", filestem_str, None, opt);
-        // filestem is based on filename, so we don't need the full set of prefix tests
-
-        t!(v: b"hi\\there.txt", extension, Some(b"txt"));
-        t!(v: b"hi\\there", extension, None);
-        t!(s: "hi\\there.txt", extension_str, Some("txt"), opt);
-        t!(s: "hi\\there", extension_str, None, opt);
-        t!(s: "there.txt", extension_str, Some("txt"), opt);
-        t!(s: "there", extension_str, None, opt);
-        t!(s: ".", extension_str, None, opt);
-        t!(s: "\\", extension_str, None, opt);
-        t!(s: "foo\\.bar", extension_str, None, opt);
-        t!(s: ".bar", extension_str, None, opt);
-        t!(s: "..bar", extension_str, Some("bar"), opt);
-        t!(s: "hi\\there..txt", extension_str, Some("txt"), opt);
-        t!(s: "..", extension_str, None, opt);
-        t!(s: "..\\..", extension_str, None, opt);
-        // extension is based on filename, so we don't need the full set of prefix tests
-    }
-
-    #[test]
-    fn test_push() {
-        macro_rules! t {
-            (s: $path:expr, $join:expr) => (
-                {
-                    let path = $path;
-                    let join = $join;
-                    let mut p1 = Path::new(path);
-                    let p2 = p1.clone();
-                    p1.push(join);
-                    assert_eq!(p1, p2.join(join));
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", "..");
-        t!(s: "\\a\\b\\c", "d");
-        t!(s: "a\\b", "c\\d");
-        t!(s: "a\\b", "\\c\\d");
-        // this is just a sanity-check test. push and join share an implementation,
-        // so there's no need for the full set of prefix tests
-
-        // we do want to check one odd case though to ensure the prefix is re-parsed
-        let mut p = Path::new("\\\\?\\C:");
-        assert_eq!(prefix(&p), Some(VerbatimPrefix(2)));
-        p.push("foo");
-        assert_eq!(prefix(&p), Some(VerbatimDiskPrefix));
-        assert_eq!(p.as_str(), Some("\\\\?\\C:\\foo"));
-
-        // and another with verbatim non-normalized paths
-        let mut p = Path::new("\\\\?\\C:\\a\\");
-        p.push("foo");
-        assert_eq!(p.as_str(), Some("\\\\?\\C:\\a\\foo"));
-    }
-
-    #[test]
-    fn test_push_path() {
-        macro_rules! t {
-            (s: $path:expr, $push:expr, $exp:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    let push = Path::new($push);
-                    p.push(&push);
-                    assert_eq!(p.as_str(), Some($exp));
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", "d", "a\\b\\c\\d");
-        t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
-        t!(s: "a\\b", "c\\d", "a\\b\\c\\d");
-        t!(s: "a\\b", "\\c\\d", "\\c\\d");
-        t!(s: "a\\b", ".", "a\\b");
-        t!(s: "a\\b", "..\\c", "a\\c");
-        t!(s: "a\\b", "C:a.txt", "C:a.txt");
-        t!(s: "a\\b", "..\\..\\..\\c", "..\\c");
-        t!(s: "a\\b", "C:\\a.txt", "C:\\a.txt");
-        t!(s: "C:\\a", "C:\\b.txt", "C:\\b.txt");
-        t!(s: "C:\\a\\b\\c", "C:d", "C:\\a\\b\\c\\d");
-        t!(s: "C:a\\b\\c", "C:d", "C:a\\b\\c\\d");
-        t!(s: "C:a\\b", "..\\..\\..\\c", "C:..\\c");
-        t!(s: "C:\\a\\b", "..\\..\\..\\c", "C:\\c");
-        t!(s: "C:", r"a\b\c", r"C:a\b\c");
-        t!(s: "C:", r"..\a", r"C:..\a");
-        t!(s: "\\\\server\\share\\foo", "bar", "\\\\server\\share\\foo\\bar");
-        t!(s: "\\\\server\\share\\foo", "..\\..\\bar", "\\\\server\\share\\bar");
-        t!(s: "\\\\server\\share\\foo", "C:baz", "C:baz");
-        t!(s: "\\\\?\\C:\\a\\b", "C:c\\d", "\\\\?\\C:\\a\\b\\c\\d");
-        t!(s: "\\\\?\\C:a\\b", "C:c\\d", "C:c\\d");
-        t!(s: "\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d");
-        t!(s: "\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz");
-        t!(s: "\\\\?\\C:\\a\\b", "..\\..\\..\\c", "\\\\?\\C:\\a\\b\\..\\..\\..\\c");
-        t!(s: "\\\\?\\foo\\bar", "..\\..\\c", "\\\\?\\foo\\bar\\..\\..\\c");
-        t!(s: "\\\\?\\", "foo", "\\\\?\\\\foo");
-        t!(s: "\\\\?\\UNC\\server\\share\\foo", "bar", "\\\\?\\UNC\\server\\share\\foo\\bar");
-        t!(s: "\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a");
-        t!(s: "\\\\?\\UNC\\server\\share", "C:a", "C:a");
-        t!(s: "\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\\\foo");
-        t!(s: "C:\\a", "\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share");
-        t!(s: "\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz");
-        t!(s: "\\\\.\\foo\\bar", "C:a", "C:a");
-        // again, not sure about the following, but I'm assuming \\.\ should be verbatim
-        t!(s: "\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar");
-
-        t!(s: "\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
-    }
-
-    #[test]
-    fn test_push_many() {
-        macro_rules! t {
-            (s: $path:expr, $push:expr, $exp:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    p.push_many(&$push);
-                    assert_eq!(p.as_str(), Some($exp));
-                }
-            );
-            (v: $path:expr, $push:expr, $exp:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    p.push_many(&$push);
-                    assert_eq!(p.as_vec(), $exp);
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
-        t!(s: "a\\b\\c", ["d", "\\e"], "\\e");
-        t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
-        t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e");
-        t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e");
-        t!(v: b"a\\b\\c", [b"d", b"\\e", b"f"], b"\\e\\f");
-        t!(v: b"a\\b\\c", [b"d".to_vec(), b"e".to_vec()],
-           b"a\\b\\c\\d\\e");
-    }
-
-    #[test]
-    fn test_pop() {
-        macro_rules! t {
-            (s: $path:expr, $left:expr, $right:expr) => (
-                {
-                    let pstr = $path;
-                    let mut p = Path::new(pstr);
-                    let result = p.pop();
-                    let left = $left;
-                    assert_eq!(p.as_str(), Some(left));
-                    assert_eq!(result, $right);
-                }
-            );
-            (b: $path:expr, $left:expr, $right:expr) => (
-                {
-                    let mut p = Path::new($path);
-                    let result = p.pop();
-                    assert_eq!(p.as_vec(), $left);
-                    assert_eq!(result, $right);
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", "a\\b", true);
-        t!(s: "a", ".", true);
-        t!(s: ".", ".", false);
-        t!(s: "\\a", "\\", true);
-        t!(s: "\\", "\\", false);
-        t!(b: b"a\\b\\c", b"a\\b", true);
-        t!(b: b"a", b".", true);
-        t!(b: b".", b".", false);
-        t!(b: b"\\a", b"\\", true);
-        t!(b: b"\\", b"\\", false);
-
-        t!(s: "C:\\a\\b", "C:\\a", true);
-        t!(s: "C:\\a", "C:\\", true);
-        t!(s: "C:\\", "C:\\", false);
-        t!(s: "C:a\\b", "C:a", true);
-        t!(s: "C:a", "C:", true);
-        t!(s: "C:", "C:", false);
-        t!(s: "\\\\server\\share\\a\\b", "\\\\server\\share\\a", true);
-        t!(s: "\\\\server\\share\\a", "\\\\server\\share", true);
-        t!(s: "\\\\server\\share", "\\\\server\\share", false);
-        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b", true);
-        t!(s: "\\\\?\\a\\b", "\\\\?\\a", true);
-        t!(s: "\\\\?\\a", "\\\\?\\a", false);
-        t!(s: "\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true);
-        t!(s: "\\\\?\\C:\\a", "\\\\?\\C:\\", true);
-        t!(s: "\\\\?\\C:\\", "\\\\?\\C:\\", false);
-        t!(s: "\\\\?\\UNC\\server\\share\\a\\b", "\\\\?\\UNC\\server\\share\\a", true);
-        t!(s: "\\\\?\\UNC\\server\\share\\a", "\\\\?\\UNC\\server\\share", true);
-        t!(s: "\\\\?\\UNC\\server\\share", "\\\\?\\UNC\\server\\share", false);
-        t!(s: "\\\\.\\a\\b\\c", "\\\\.\\a\\b", true);
-        t!(s: "\\\\.\\a\\b", "\\\\.\\a", true);
-        t!(s: "\\\\.\\a", "\\\\.\\a", false);
-
-        t!(s: "\\\\?\\a\\b\\", "\\\\?\\a", true);
-    }
-
-    #[test]
-    fn test_root_path() {
-        assert_eq!(Path::new("a\\b\\c").root_path(),  None);
-        assert_eq!(Path::new("\\a\\b\\c").root_path(), Some(Path::new("\\")));
-        assert_eq!(Path::new("C:a").root_path(), Some(Path::new("C:")));
-        assert_eq!(Path::new("C:\\a").root_path(), Some(Path::new("C:\\")));
-        assert_eq!(Path::new("\\\\a\\b\\c").root_path(), Some(Path::new("\\\\a\\b")));
-        assert_eq!(Path::new("\\\\?\\a\\b").root_path(), Some(Path::new("\\\\?\\a")));
-        assert_eq!(Path::new("\\\\?\\C:\\a").root_path(), Some(Path::new("\\\\?\\C:\\")));
-        assert_eq!(Path::new("\\\\?\\UNC\\a\\b\\c").root_path(),
-                Some(Path::new("\\\\?\\UNC\\a\\b")));
-        assert_eq!(Path::new("\\\\.\\a\\b").root_path(), Some(Path::new("\\\\.\\a")));
-    }
-
-    #[test]
-    fn test_join() {
-        t!(s: Path::new("a\\b\\c").join(".."), "a\\b");
-        t!(s: Path::new("\\a\\b\\c").join("d"), "\\a\\b\\c\\d");
-        t!(s: Path::new("a\\b").join("c\\d"), "a\\b\\c\\d");
-        t!(s: Path::new("a\\b").join("\\c\\d"), "\\c\\d");
-        t!(s: Path::new(".").join("a\\b"), "a\\b");
-        t!(s: Path::new("\\").join("a\\b"), "\\a\\b");
-        t!(v: Path::new(b"a\\b\\c").join(b".."), b"a\\b");
-        t!(v: Path::new(b"\\a\\b\\c").join(b"d"), b"\\a\\b\\c\\d");
-        // full join testing is covered under test_push_path, so no need for
-        // the full set of prefix tests
-    }
-
-    #[test]
-    fn test_join_path() {
-        macro_rules! t {
-            (s: $path:expr, $join:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let join = Path::new($join);
-                    let res = path.join(&join);
-                    assert_eq!(res.as_str(), Some($exp));
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", "..", "a\\b");
-        t!(s: "\\a\\b\\c", "d", "\\a\\b\\c\\d");
-        t!(s: "a\\b", "c\\d", "a\\b\\c\\d");
-        t!(s: "a\\b", "\\c\\d", "\\c\\d");
-        t!(s: ".", "a\\b", "a\\b");
-        t!(s: "\\", "a\\b", "\\a\\b");
-        // join is implemented using push, so there's no need for
-        // the full set of prefix tests
-    }
-
-    #[test]
-    fn test_join_many() {
-        macro_rules! t {
-            (s: $path:expr, $join:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let res = path.join_many(&$join);
-                    assert_eq!(res.as_str(), Some($exp));
-                }
-            );
-            (v: $path:expr, $join:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let res = path.join_many(&$join);
-                    assert_eq!(res.as_vec(), $exp);
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", ["d", "e"], "a\\b\\c\\d\\e");
-        t!(s: "a\\b\\c", ["..", "d"], "a\\b\\d");
-        t!(s: "a\\b\\c", ["d", "\\e", "f"], "\\e\\f");
-        t!(s: "a\\b\\c", ["d".to_string(), "e".to_string()], "a\\b\\c\\d\\e");
-        t!(v: b"a\\b\\c", [b"d", b"e"], b"a\\b\\c\\d\\e");
-        t!(v: b"a\\b\\c", [b"d".to_vec(), b"e".to_vec()],
-           b"a\\b\\c\\d\\e");
-    }
-
-    #[test]
-    fn test_with_helpers() {
-        macro_rules! t {
-            (s: $path:expr, $op:ident, $arg:expr, $res:expr) => (
-                {
-                    let pstr = $path;
-                    let path = Path::new(pstr);
-                    let arg = $arg;
-                    let res = path.$op(arg);
-                    let exp = Path::new($res);
-                    assert_eq!(res, exp);
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", with_filename, "d", "a\\b\\d");
-        t!(s: ".", with_filename, "foo", "foo");
-        t!(s: "\\a\\b\\c", with_filename, "d", "\\a\\b\\d");
-        t!(s: "\\", with_filename, "foo", "\\foo");
-        t!(s: "\\a", with_filename, "foo", "\\foo");
-        t!(s: "foo", with_filename, "bar", "bar");
-        t!(s: "\\", with_filename, "foo\\", "\\foo");
-        t!(s: "\\a", with_filename, "foo\\", "\\foo");
-        t!(s: "a\\b\\c", with_filename, "", "a\\b");
-        t!(s: "a\\b\\c", with_filename, ".", "a\\b");
-        t!(s: "a\\b\\c", with_filename, "..", "a");
-        t!(s: "\\a", with_filename, "", "\\");
-        t!(s: "foo", with_filename, "", ".");
-        t!(s: "a\\b\\c", with_filename, "d\\e", "a\\b\\d\\e");
-        t!(s: "a\\b\\c", with_filename, "\\d", "a\\b\\d");
-        t!(s: "..", with_filename, "foo", "..\\foo");
-        t!(s: "..\\..", with_filename, "foo", "..\\..\\foo");
-        t!(s: "..", with_filename, "", "..");
-        t!(s: "..\\..", with_filename, "", "..\\..");
-        t!(s: "C:\\foo\\bar", with_filename, "baz", "C:\\foo\\baz");
-        t!(s: "C:\\foo", with_filename, "bar", "C:\\bar");
-        t!(s: "C:\\", with_filename, "foo", "C:\\foo");
-        t!(s: "C:foo\\bar", with_filename, "baz", "C:foo\\baz");
-        t!(s: "C:foo", with_filename, "bar", "C:bar");
-        t!(s: "C:", with_filename, "foo", "C:foo");
-        t!(s: "C:\\foo", with_filename, "", "C:\\");
-        t!(s: "C:foo", with_filename, "", "C:");
-        t!(s: "C:\\foo\\bar", with_filename, "..", "C:\\");
-        t!(s: "C:\\foo", with_filename, "..", "C:\\");
-        t!(s: "C:\\", with_filename, "..", "C:\\");
-        t!(s: "C:foo\\bar", with_filename, "..", "C:");
-        t!(s: "C:foo", with_filename, "..", "C:..");
-        t!(s: "C:", with_filename, "..", "C:..");
-        t!(s: "\\\\server\\share\\foo", with_filename, "bar", "\\\\server\\share\\bar");
-        t!(s: "\\\\server\\share", with_filename, "foo", "\\\\server\\share\\foo");
-        t!(s: "\\\\server\\share\\foo", with_filename, "", "\\\\server\\share");
-        t!(s: "\\\\server\\share", with_filename, "", "\\\\server\\share");
-        t!(s: "\\\\server\\share\\foo", with_filename, "..", "\\\\server\\share");
-        t!(s: "\\\\server\\share", with_filename, "..", "\\\\server\\share");
-        t!(s: "\\\\?\\C:\\foo\\bar", with_filename, "baz", "\\\\?\\C:\\foo\\baz");
-        t!(s: "\\\\?\\C:\\foo", with_filename, "bar", "\\\\?\\C:\\bar");
-        t!(s: "\\\\?\\C:\\", with_filename, "foo", "\\\\?\\C:\\foo");
-        t!(s: "\\\\?\\C:\\foo", with_filename, "..", "\\\\?\\C:\\..");
-        t!(s: "\\\\?\\foo\\bar", with_filename, "baz", "\\\\?\\foo\\baz");
-        t!(s: "\\\\?\\foo", with_filename, "bar", "\\\\?\\foo\\bar");
-        t!(s: "\\\\?\\", with_filename, "foo", "\\\\?\\\\foo");
-        t!(s: "\\\\?\\foo\\bar", with_filename, "..", "\\\\?\\foo\\..");
-        t!(s: "\\\\.\\foo\\bar", with_filename, "baz", "\\\\.\\foo\\baz");
-        t!(s: "\\\\.\\foo", with_filename, "bar", "\\\\.\\foo\\bar");
-        t!(s: "\\\\.\\foo\\bar", with_filename, "..", "\\\\.\\foo\\..");
-
-        t!(s: "hi\\there.txt", with_extension, "exe", "hi\\there.exe");
-        t!(s: "hi\\there.txt", with_extension, "", "hi\\there");
-        t!(s: "hi\\there.txt", with_extension, ".", "hi\\there..");
-        t!(s: "hi\\there.txt", with_extension, "..", "hi\\there...");
-        t!(s: "hi\\there", with_extension, "txt", "hi\\there.txt");
-        t!(s: "hi\\there", with_extension, ".", "hi\\there..");
-        t!(s: "hi\\there", with_extension, "..", "hi\\there...");
-        t!(s: "hi\\there.", with_extension, "txt", "hi\\there.txt");
-        t!(s: "hi\\.foo", with_extension, "txt", "hi\\.foo.txt");
-        t!(s: "hi\\there.txt", with_extension, ".foo", "hi\\there..foo");
-        t!(s: "\\", with_extension, "txt", "\\");
-        t!(s: "\\", with_extension, ".", "\\");
-        t!(s: "\\", with_extension, "..", "\\");
-        t!(s: ".", with_extension, "txt", ".");
-        // extension setter calls filename setter internally, no need for extended tests
-    }
-
-    #[test]
-    fn test_setters() {
-        macro_rules! t {
-            (s: $path:expr, $set:ident, $with:ident, $arg:expr) => (
-                {
-                    let path = $path;
-                    let arg = $arg;
-                    let mut p1 = Path::new(path);
-                    p1.$set(arg);
-                    let p2 = Path::new(path);
-                    assert_eq!(p1, p2.$with(arg));
-                }
-            );
-            (v: $path:expr, $set:ident, $with:ident, $arg:expr) => (
-                {
-                    let path = $path;
-                    let arg = $arg;
-                    let mut p1 = Path::new(path);
-                    p1.$set(arg);
-                    let p2 = Path::new(path);
-                    assert_eq!(p1, p2.$with(arg));
-                }
-            )
-        }
-
-        t!(v: b"a\\b\\c", set_filename, with_filename, b"d");
-        t!(v: b"\\", set_filename, with_filename, b"foo");
-        t!(s: "a\\b\\c", set_filename, with_filename, "d");
-        t!(s: "\\", set_filename, with_filename, "foo");
-        t!(s: ".", set_filename, with_filename, "foo");
-        t!(s: "a\\b", set_filename, with_filename, "");
-        t!(s: "a", set_filename, with_filename, "");
-
-        t!(v: b"hi\\there.txt", set_extension, with_extension, b"exe");
-        t!(s: "hi\\there.txt", set_extension, with_extension, "exe");
-        t!(s: "hi\\there.", set_extension, with_extension, "txt");
-        t!(s: "hi\\there", set_extension, with_extension, "txt");
-        t!(s: "hi\\there.txt", set_extension, with_extension, "");
-        t!(s: "hi\\there", set_extension, with_extension, "");
-        t!(s: ".", set_extension, with_extension, "txt");
-
-        // with_ helpers use the setter internally, so the tests for the with_ helpers
-        // will suffice. No need for the full set of prefix tests.
-    }
-
-    #[test]
-    fn test_getters() {
-        macro_rules! t {
-            (s: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
-                {
-                    let path = $path;
-                    assert_eq!(path.filename_str(), $filename);
-                    assert_eq!(path.dirname_str(), $dirname);
-                    assert_eq!(path.filestem_str(), $filestem);
-                    assert_eq!(path.extension_str(), $ext);
-                }
-            );
-            (v: $path:expr, $filename:expr, $dirname:expr, $filestem:expr, $ext:expr) => (
-                {
-                    let path = $path;
-                    assert_eq!(path.filename(), $filename);
-                    assert_eq!(path.dirname(), $dirname);
-                    assert_eq!(path.filestem(), $filestem);
-                    assert_eq!(path.extension(), $ext);
-                }
-            )
-        }
-
-        t!(v: Path::new(b"a\\b\\c"), Some(b"c"), b"a\\b", Some(b"c"), None);
-        t!(s: Path::new("a\\b\\c"), Some("c"), Some("a\\b"), Some("c"), None);
-        t!(s: Path::new("."), None, Some("."), None, None);
-        t!(s: Path::new("\\"), None, Some("\\"), None, None);
-        t!(s: Path::new(".."), None, Some(".."), None, None);
-        t!(s: Path::new("..\\.."), None, Some("..\\.."), None, None);
-        t!(s: Path::new("hi\\there.txt"), Some("there.txt"), Some("hi"),
-              Some("there"), Some("txt"));
-        t!(s: Path::new("hi\\there"), Some("there"), Some("hi"), Some("there"), None);
-        t!(s: Path::new("hi\\there."), Some("there."), Some("hi"),
-              Some("there"), Some(""));
-        t!(s: Path::new("hi\\.there"), Some(".there"), Some("hi"), Some(".there"), None);
-        t!(s: Path::new("hi\\..there"), Some("..there"), Some("hi"),
-              Some("."), Some("there"));
-
-        // these are already tested in test_components, so no need for extended tests
-    }
-
-    #[test]
-    fn test_dir_path() {
-        t!(s: Path::new("hi\\there").dir_path(), "hi");
-        t!(s: Path::new("hi").dir_path(), ".");
-        t!(s: Path::new("\\hi").dir_path(), "\\");
-        t!(s: Path::new("\\").dir_path(), "\\");
-        t!(s: Path::new("..").dir_path(), "..");
-        t!(s: Path::new("..\\..").dir_path(), "..\\..");
-
-        // dir_path is just dirname interpreted as a path.
-        // No need for extended tests
-    }
-
-    #[test]
-    fn test_is_absolute() {
-        macro_rules! t {
-            ($path:expr, $abs:expr, $vol:expr, $cwd:expr, $rel:expr) => (
-                {
-                    let path = Path::new($path);
-                    let (abs, vol, cwd, rel) = ($abs, $vol, $cwd, $rel);
-                    assert_eq!(path.is_absolute(), abs);
-                    assert_eq!(is_vol_relative(&path), vol);
-                    assert_eq!(is_cwd_relative(&path), cwd);
-                    assert_eq!(path.is_relative(), rel);
-                }
-            )
-        }
-        t!("a\\b\\c", false, false, false, true);
-        t!("\\a\\b\\c", false, true, false, false);
-        t!("a", false, false, false, true);
-        t!("\\a", false, true, false, false);
-        t!(".", false, false, false, true);
-        t!("\\", false, true, false, false);
-        t!("..", false, false, false, true);
-        t!("..\\..", false, false, false, true);
-        t!("C:a\\b.txt", false, false, true, false);
-        t!("C:\\a\\b.txt", true, false, false, false);
-        t!("\\\\server\\share\\a\\b.txt", true, false, false, false);
-        t!("\\\\?\\a\\b\\c.txt", true, false, false, false);
-        t!("\\\\?\\C:\\a\\b.txt", true, false, false, false);
-        t!("\\\\?\\C:a\\b.txt", true, false, false, false); // NB: not equivalent to C:a\b.txt
-        t!("\\\\?\\UNC\\server\\share\\a\\b.txt", true, false, false, false);
-        t!("\\\\.\\a\\b", true, false, false, false);
-    }
-
-    #[test]
-    fn test_is_ancestor_of() {
-        macro_rules! t {
-            (s: $path:expr, $dest:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let dest = Path::new($dest);
-                    let exp = $exp;
-                    let res = path.is_ancestor_of(&dest);
-                    assert_eq!(res, exp);
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", "a\\b\\c\\d", true);
-        t!(s: "a\\b\\c", "a\\b\\c", true);
-        t!(s: "a\\b\\c", "a\\b", false);
-        t!(s: "\\a\\b\\c", "\\a\\b\\c", true);
-        t!(s: "\\a\\b", "\\a\\b\\c", true);
-        t!(s: "\\a\\b\\c\\d", "\\a\\b\\c", false);
-        t!(s: "\\a\\b", "a\\b\\c", false);
-        t!(s: "a\\b", "\\a\\b\\c", false);
-        t!(s: "a\\b\\c", "a\\b\\d", false);
-        t!(s: "..\\a\\b\\c", "a\\b\\c", false);
-        t!(s: "a\\b\\c", "..\\a\\b\\c", false);
-        t!(s: "a\\b\\c", "a\\b\\cd", false);
-        t!(s: "a\\b\\cd", "a\\b\\c", false);
-        t!(s: "..\\a\\b", "..\\a\\b\\c", true);
-        t!(s: ".", "a\\b", true);
-        t!(s: ".", ".", true);
-        t!(s: "\\", "\\", true);
-        t!(s: "\\", "\\a\\b", true);
-        t!(s: "..", "a\\b", true);
-        t!(s: "..\\..", "a\\b", true);
-        t!(s: "foo\\bar", "foobar", false);
-        t!(s: "foobar", "foo\\bar", false);
-
-        t!(s: "foo", "C:foo", false);
-        t!(s: "C:foo", "foo", false);
-        t!(s: "C:foo", "C:foo\\bar", true);
-        t!(s: "C:foo\\bar", "C:foo", false);
-        t!(s: "C:\\foo", "C:\\foo\\bar", true);
-        t!(s: "C:", "C:", true);
-        t!(s: "C:", "C:\\", false);
-        t!(s: "C:\\", "C:", false);
-        t!(s: "C:\\", "C:\\", true);
-        t!(s: "C:\\foo\\bar", "C:\\foo", false);
-        t!(s: "C:foo\\bar", "C:foo", false);
-        t!(s: "C:\\foo", "\\foo", false);
-        t!(s: "\\foo", "C:\\foo", false);
-        t!(s: "\\\\server\\share\\foo", "\\\\server\\share\\foo\\bar", true);
-        t!(s: "\\\\server\\share", "\\\\server\\share\\foo", true);
-        t!(s: "\\\\server\\share\\foo", "\\\\server\\share", false);
-        t!(s: "C:\\foo", "\\\\server\\share\\foo", false);
-        t!(s: "\\\\server\\share\\foo", "C:\\foo", false);
-        t!(s: "\\\\?\\foo\\bar", "\\\\?\\foo\\bar\\baz", true);
-        t!(s: "\\\\?\\foo\\bar\\baz", "\\\\?\\foo\\bar", false);
-        t!(s: "\\\\?\\foo\\bar", "\\foo\\bar\\baz", false);
-        t!(s: "\\foo\\bar", "\\\\?\\foo\\bar\\baz", false);
-        t!(s: "\\\\?\\C:\\foo\\bar", "\\\\?\\C:\\foo\\bar\\baz", true);
-        t!(s: "\\\\?\\C:\\foo\\bar\\baz", "\\\\?\\C:\\foo\\bar", false);
-        t!(s: "\\\\?\\C:\\", "\\\\?\\C:\\foo", true);
-        t!(s: "\\\\?\\C:", "\\\\?\\C:\\", false); // this is a weird one
-        t!(s: "\\\\?\\C:\\", "\\\\?\\C:", false);
-        t!(s: "\\\\?\\C:\\a", "\\\\?\\c:\\a\\b", true);
-        t!(s: "\\\\?\\c:\\a", "\\\\?\\C:\\a\\b", true);
-        t!(s: "\\\\?\\C:\\a", "\\\\?\\D:\\a\\b", false);
-        t!(s: "\\\\?\\foo", "\\\\?\\foobar", false);
-        t!(s: "\\\\?\\a\\b", "\\\\?\\a\\b\\c", true);
-        t!(s: "\\\\?\\a\\b", "\\\\?\\a\\b\\", true);
-        t!(s: "\\\\?\\a\\b\\", "\\\\?\\a\\b", true);
-        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b", false);
-        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b\\", false);
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b\\c\\d", true);
-        t!(s: "\\\\?\\UNC\\a\\b\\c\\d", "\\\\?\\UNC\\a\\b\\c", false);
-        t!(s: "\\\\?\\UNC\\a\\b", "\\\\?\\UNC\\a\\b\\c", true);
-        t!(s: "\\\\.\\foo\\bar", "\\\\.\\foo\\bar\\baz", true);
-        t!(s: "\\\\.\\foo\\bar\\baz", "\\\\.\\foo\\bar", false);
-        t!(s: "\\\\.\\foo", "\\\\.\\foo\\bar", true);
-        t!(s: "\\\\.\\foo", "\\\\.\\foobar", false);
-
-        t!(s: "\\a\\b", "\\\\?\\a\\b", false);
-        t!(s: "\\\\?\\a\\b", "\\a\\b", false);
-        t!(s: "\\a\\b", "\\\\?\\C:\\a\\b", false);
-        t!(s: "\\\\?\\C:\\a\\b", "\\a\\b", false);
-        t!(s: "Z:\\a\\b", "\\\\?\\z:\\a\\b", true);
-        t!(s: "C:\\a\\b", "\\\\?\\D:\\a\\b", false);
-        t!(s: "a\\b", "\\\\?\\a\\b", false);
-        t!(s: "\\\\?\\a\\b", "a\\b", false);
-        t!(s: "C:\\a\\b", "\\\\?\\C:\\a\\b", true);
-        t!(s: "\\\\?\\C:\\a\\b", "C:\\a\\b", true);
-        t!(s: "C:a\\b", "\\\\?\\C:\\a\\b", false);
-        t!(s: "C:a\\b", "\\\\?\\C:a\\b", false);
-        t!(s: "\\\\?\\C:\\a\\b", "C:a\\b", false);
-        t!(s: "\\\\?\\C:a\\b", "C:a\\b", false);
-        t!(s: "C:\\a\\b", "\\\\?\\C:\\a\\b\\", true);
-        t!(s: "\\\\?\\C:\\a\\b\\", "C:\\a\\b", true);
-        t!(s: "\\\\a\\b\\c", "\\\\?\\UNC\\a\\b\\c", true);
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\a\\b\\c", true);
-    }
-
-    #[test]
-    fn test_ends_with_path() {
-        macro_rules! t {
-            (s: $path:expr, $child:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let child = Path::new($child);
-                    assert_eq!(path.ends_with_path(&child), $exp);
-                }
-            );
-        }
-
-        t!(s: "a\\b\\c", "c", true);
-        t!(s: "a\\b\\c", "d", false);
-        t!(s: "foo\\bar\\quux", "bar", false);
-        t!(s: "foo\\bar\\quux", "barquux", false);
-        t!(s: "a\\b\\c", "b\\c", true);
-        t!(s: "a\\b\\c", "a\\b\\c", true);
-        t!(s: "a\\b\\c", "foo\\a\\b\\c", false);
-        t!(s: "\\a\\b\\c", "a\\b\\c", true);
-        t!(s: "\\a\\b\\c", "\\a\\b\\c", false); // child must be relative
-        t!(s: "\\a\\b\\c", "foo\\a\\b\\c", false);
-        t!(s: "a\\b\\c", "", false);
-        t!(s: "", "", true);
-        t!(s: "\\a\\b\\c", "d\\e\\f", false);
-        t!(s: "a\\b\\c", "a\\b", false);
-        t!(s: "a\\b\\c", "b", false);
-        t!(s: "C:\\a\\b", "b", true);
-        t!(s: "C:\\a\\b", "C:b", false);
-        t!(s: "C:\\a\\b", "C:a\\b", false);
-    }
-
-    #[test]
-    fn test_path_relative_from() {
-        macro_rules! t {
-            (s: $path:expr, $other:expr, $exp:expr) => (
-                {
-                    assert_eq!(Path::new($path).path_relative_from(&Path::new($other))
-                              .as_ref().and_then(|x| x.as_str()), $exp);
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", "a\\b", Some("c"));
-        t!(s: "a\\b\\c", "a\\b\\d", Some("..\\c"));
-        t!(s: "a\\b\\c", "a\\b\\c\\d", Some(".."));
-        t!(s: "a\\b\\c", "a\\b\\c", Some("."));
-        t!(s: "a\\b\\c", "a\\b\\c\\d\\e", Some("..\\.."));
-        t!(s: "a\\b\\c", "a\\d\\e", Some("..\\..\\b\\c"));
-        t!(s: "a\\b\\c", "d\\e\\f", Some("..\\..\\..\\a\\b\\c"));
-        t!(s: "a\\b\\c", "\\a\\b\\c", None);
-        t!(s: "\\a\\b\\c", "a\\b\\c", Some("\\a\\b\\c"));
-        t!(s: "\\a\\b\\c", "\\a\\b\\c\\d", Some(".."));
-        t!(s: "\\a\\b\\c", "\\a\\b", Some("c"));
-        t!(s: "\\a\\b\\c", "\\a\\b\\c\\d\\e", Some("..\\.."));
-        t!(s: "\\a\\b\\c", "\\a\\d\\e", Some("..\\..\\b\\c"));
-        t!(s: "\\a\\b\\c", "\\d\\e\\f", Some("..\\..\\..\\a\\b\\c"));
-        t!(s: "hi\\there.txt", "hi\\there", Some("..\\there.txt"));
-        t!(s: ".", "a", Some(".."));
-        t!(s: ".", "a\\b", Some("..\\.."));
-        t!(s: ".", ".", Some("."));
-        t!(s: "a", ".", Some("a"));
-        t!(s: "a\\b", ".", Some("a\\b"));
-        t!(s: "..", ".", Some(".."));
-        t!(s: "a\\b\\c", "a\\b\\c", Some("."));
-        t!(s: "\\a\\b\\c", "\\a\\b\\c", Some("."));
-        t!(s: "\\", "\\", Some("."));
-        t!(s: "\\", ".", Some("\\"));
-        t!(s: "..\\..\\a", "b", Some("..\\..\\..\\a"));
-        t!(s: "a", "..\\..\\b", None);
-        t!(s: "..\\..\\a", "..\\..\\b", Some("..\\a"));
-        t!(s: "..\\..\\a", "..\\..\\a\\b", Some(".."));
-        t!(s: "..\\..\\a\\b", "..\\..\\a", Some("b"));
-
-        t!(s: "C:a\\b\\c", "C:a\\b", Some("c"));
-        t!(s: "C:a\\b", "C:a\\b\\c", Some(".."));
-        t!(s: "C:" ,"C:a\\b", Some("..\\.."));
-        t!(s: "C:a\\b", "C:c\\d", Some("..\\..\\a\\b"));
-        t!(s: "C:a\\b", "D:c\\d", Some("C:a\\b"));
-        t!(s: "C:a\\b", "C:..\\c", None);
-        t!(s: "C:..\\a", "C:b\\c", Some("..\\..\\..\\a"));
-        t!(s: "C:\\a\\b\\c", "C:\\a\\b", Some("c"));
-        t!(s: "C:\\a\\b", "C:\\a\\b\\c", Some(".."));
-        t!(s: "C:\\", "C:\\a\\b", Some("..\\.."));
-        t!(s: "C:\\a\\b", "C:\\c\\d", Some("..\\..\\a\\b"));
-        t!(s: "C:\\a\\b", "C:a\\b", Some("C:\\a\\b"));
-        t!(s: "C:a\\b", "C:\\a\\b", None);
-        t!(s: "\\a\\b", "C:\\a\\b", None);
-        t!(s: "\\a\\b", "C:a\\b", None);
-        t!(s: "a\\b", "C:\\a\\b", None);
-        t!(s: "a\\b", "C:a\\b", None);
-
-        t!(s: "\\\\a\\b\\c", "\\\\a\\b", Some("c"));
-        t!(s: "\\\\a\\b", "\\\\a\\b\\c", Some(".."));
-        t!(s: "\\\\a\\b\\c\\e", "\\\\a\\b\\c\\d", Some("..\\e"));
-        t!(s: "\\\\a\\c\\d", "\\\\a\\b\\d", Some("\\\\a\\c\\d"));
-        t!(s: "\\\\b\\c\\d", "\\\\a\\c\\d", Some("\\\\b\\c\\d"));
-        t!(s: "\\\\a\\b\\c", "\\d\\e", Some("\\\\a\\b\\c"));
-        t!(s: "\\d\\e", "\\\\a\\b\\c", None);
-        t!(s: "d\\e", "\\\\a\\b\\c", None);
-        t!(s: "C:\\a\\b\\c", "\\\\a\\b\\c", Some("C:\\a\\b\\c"));
-        t!(s: "C:\\c", "\\\\a\\b\\c", Some("C:\\c"));
-
-        t!(s: "\\\\?\\a\\b", "\\a\\b", Some("\\\\?\\a\\b"));
-        t!(s: "\\\\?\\a\\b", "a\\b", Some("\\\\?\\a\\b"));
-        t!(s: "\\\\?\\a\\b", "\\b", Some("\\\\?\\a\\b"));
-        t!(s: "\\\\?\\a\\b", "b", Some("\\\\?\\a\\b"));
-        t!(s: "\\\\?\\a\\b", "\\\\?\\a\\b\\c", Some(".."));
-        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\b", Some("c"));
-        t!(s: "\\\\?\\a\\b", "\\\\?\\c\\d", Some("\\\\?\\a\\b"));
-        t!(s: "\\\\?\\a", "\\\\?\\b", Some("\\\\?\\a"));
-
-        t!(s: "\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", Some("b"));
-        t!(s: "\\\\?\\C:\\a", "\\\\?\\C:\\a\\b", Some(".."));
-        t!(s: "\\\\?\\C:\\a", "\\\\?\\C:\\b", Some("..\\a"));
-        t!(s: "\\\\?\\C:\\a", "\\\\?\\D:\\a", Some("\\\\?\\C:\\a"));
-        t!(s: "\\\\?\\C:\\a\\b", "\\\\?\\c:\\a", Some("b"));
-        t!(s: "\\\\?\\C:\\a\\b", "C:\\a", Some("b"));
-        t!(s: "\\\\?\\C:\\a", "C:\\a\\b", Some(".."));
-        t!(s: "C:\\a\\b", "\\\\?\\C:\\a", Some("b"));
-        t!(s: "C:\\a", "\\\\?\\C:\\a\\b", Some(".."));
-        t!(s: "\\\\?\\C:\\a", "D:\\a", Some("\\\\?\\C:\\a"));
-        t!(s: "\\\\?\\c:\\a\\b", "C:\\a", Some("b"));
-        t!(s: "\\\\?\\C:\\a\\b", "C:a\\b", Some("\\\\?\\C:\\a\\b"));
-        t!(s: "\\\\?\\C:\\a\\.\\b", "C:\\a", Some("\\\\?\\C:\\a\\.\\b"));
-        t!(s: "\\\\?\\C:\\a\\b/c", "C:\\a", Some("\\\\?\\C:\\a\\b/c"));
-        t!(s: "\\\\?\\C:\\a\\..\\b", "C:\\a", Some("\\\\?\\C:\\a\\..\\b"));
-        t!(s: "C:a\\b", "\\\\?\\C:\\a\\b", None);
-        t!(s: "\\\\?\\C:\\a\\.\\b", "\\\\?\\C:\\a", Some("\\\\?\\C:\\a\\.\\b"));
-        t!(s: "\\\\?\\C:\\a\\b/c", "\\\\?\\C:\\a", Some("\\\\?\\C:\\a\\b/c"));
-        t!(s: "\\\\?\\C:\\a\\..\\b", "\\\\?\\C:\\a", Some("\\\\?\\C:\\a\\..\\b"));
-        t!(s: "\\\\?\\C:\\a\\b\\", "\\\\?\\C:\\a", Some("b"));
-        t!(s: "\\\\?\\C:\\.\\b", "\\\\?\\C:\\.", Some("b"));
-        t!(s: "C:\\b", "\\\\?\\C:\\.", Some("..\\b"));
-        t!(s: "\\\\?\\a\\.\\b\\c", "\\\\?\\a\\.\\b", Some("c"));
-        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\.\\d", Some("..\\..\\b\\c"));
-        t!(s: "\\\\?\\a\\..\\b", "\\\\?\\a\\..", Some("b"));
-        t!(s: "\\\\?\\a\\b\\..", "\\\\?\\a\\b", Some("\\\\?\\a\\b\\.."));
-        t!(s: "\\\\?\\a\\b\\c", "\\\\?\\a\\..\\b", Some("..\\..\\b\\c"));
-
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\b", Some("c"));
-        t!(s: "\\\\?\\UNC\\a\\b", "\\\\?\\UNC\\a\\b\\c", Some(".."));
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\UNC\\a\\c\\d", Some("\\\\?\\UNC\\a\\b\\c"));
-        t!(s: "\\\\?\\UNC\\b\\c\\d", "\\\\?\\UNC\\a\\c\\d", Some("\\\\?\\UNC\\b\\c\\d"));
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\a\\b\\c", Some("\\\\?\\UNC\\a\\b\\c"));
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\?\\C:\\a\\b\\c", Some("\\\\?\\UNC\\a\\b\\c"));
-        t!(s: "\\\\?\\UNC\\a\\b\\c/d", "\\\\?\\UNC\\a\\b", Some("\\\\?\\UNC\\a\\b\\c/d"));
-        t!(s: "\\\\?\\UNC\\a\\b\\.", "\\\\?\\UNC\\a\\b", Some("\\\\?\\UNC\\a\\b\\."));
-        t!(s: "\\\\?\\UNC\\a\\b\\..", "\\\\?\\UNC\\a\\b", Some("\\\\?\\UNC\\a\\b\\.."));
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\a\\b", Some("c"));
-        t!(s: "\\\\?\\UNC\\a\\b", "\\\\a\\b\\c", Some(".."));
-        t!(s: "\\\\?\\UNC\\a\\b\\c", "\\\\a\\c\\d", Some("\\\\?\\UNC\\a\\b\\c"));
-        t!(s: "\\\\?\\UNC\\b\\c\\d", "\\\\a\\c\\d", Some("\\\\?\\UNC\\b\\c\\d"));
-        t!(s: "\\\\?\\UNC\\a\\b\\.", "\\\\a\\b", Some("\\\\?\\UNC\\a\\b\\."));
-        t!(s: "\\\\?\\UNC\\a\\b\\c/d", "\\\\a\\b", Some("\\\\?\\UNC\\a\\b\\c/d"));
-        t!(s: "\\\\?\\UNC\\a\\b\\..", "\\\\a\\b", Some("\\\\?\\UNC\\a\\b\\.."));
-        t!(s: "\\\\a\\b\\c", "\\\\?\\UNC\\a\\b", Some("c"));
-        t!(s: "\\\\a\\b\\c", "\\\\?\\UNC\\a\\c\\d", Some("\\\\a\\b\\c"));
-    }
-
-    #[test]
-    fn test_str_components() {
-        macro_rules! t {
-            (s: $path:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let comps = path.str_components().map(|x|x.unwrap())
-                                .collect::<Vec<&str>>();
-                    let exp: &[&str] = &$exp;
-                    assert_eq!(comps, exp);
-                    let comps = path.str_components().rev().map(|x|x.unwrap())
-                                .collect::<Vec<&str>>();
-                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&str>>();
-                    assert_eq!(comps, exp);
-                }
-            );
-        }
-
-        t!(s: b"a\\b\\c", ["a", "b", "c"]);
-        t!(s: "a\\b\\c", ["a", "b", "c"]);
-        t!(s: "a\\b\\d", ["a", "b", "d"]);
-        t!(s: "a\\b\\cd", ["a", "b", "cd"]);
-        t!(s: "\\a\\b\\c", ["a", "b", "c"]);
-        t!(s: "a", ["a"]);
-        t!(s: "\\a", ["a"]);
-        t!(s: "\\", []);
-        t!(s: ".", ["."]);
-        t!(s: "..", [".."]);
-        t!(s: "..\\..", ["..", ".."]);
-        t!(s: "..\\..\\foo", ["..", "..", "foo"]);
-        t!(s: "C:foo\\bar", ["foo", "bar"]);
-        t!(s: "C:foo", ["foo"]);
-        t!(s: "C:", []);
-        t!(s: "C:\\foo\\bar", ["foo", "bar"]);
-        t!(s: "C:\\foo", ["foo"]);
-        t!(s: "C:\\", []);
-        t!(s: "\\\\server\\share\\foo\\bar", ["foo", "bar"]);
-        t!(s: "\\\\server\\share\\foo", ["foo"]);
-        t!(s: "\\\\server\\share", []);
-        t!(s: "\\\\?\\foo\\bar\\baz", ["bar", "baz"]);
-        t!(s: "\\\\?\\foo\\bar", ["bar"]);
-        t!(s: "\\\\?\\foo", []);
-        t!(s: "\\\\?\\", []);
-        t!(s: "\\\\?\\a\\b", ["b"]);
-        t!(s: "\\\\?\\a\\b\\", ["b"]);
-        t!(s: "\\\\?\\foo\\bar\\\\baz", ["bar", "", "baz"]);
-        t!(s: "\\\\?\\C:\\foo\\bar", ["foo", "bar"]);
-        t!(s: "\\\\?\\C:\\foo", ["foo"]);
-        t!(s: "\\\\?\\C:\\", []);
-        t!(s: "\\\\?\\C:\\foo\\", ["foo"]);
-        t!(s: "\\\\?\\UNC\\server\\share\\foo\\bar", ["foo", "bar"]);
-        t!(s: "\\\\?\\UNC\\server\\share\\foo", ["foo"]);
-        t!(s: "\\\\?\\UNC\\server\\share", []);
-        t!(s: "\\\\.\\foo\\bar\\baz", ["bar", "baz"]);
-        t!(s: "\\\\.\\foo\\bar", ["bar"]);
-        t!(s: "\\\\.\\foo", []);
-    }
-
-    #[test]
-    fn test_components_iter() {
-        macro_rules! t {
-            (s: $path:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let comps = path.components().collect::<Vec<&[u8]>>();
-                    let exp: &[&[u8]] = &$exp;
-                    assert_eq!(comps, exp);
-                    let comps = path.components().rev().collect::<Vec<&[u8]>>();
-                    let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
-                    assert_eq!(comps, exp);
-                }
-            )
-        }
-
-        t!(s: "a\\b\\c", [b"a", b"b", b"c"]);
-        t!(s: ".", [b"."]);
-        // since this is really a wrapper around str_components, those tests suffice
-    }
-
-    #[test]
-    fn test_make_non_verbatim() {
-        macro_rules! t {
-            ($path:expr, $exp:expr) => (
-                {
-                    let path = Path::new($path);
-                    let exp: Option<&str> = $exp;
-                    let exp = exp.map(|s| Path::new(s));
-                    assert_eq!(make_non_verbatim(&path), exp);
-                }
-            )
-        }
-
-        t!(r"\a\b\c", Some(r"\a\b\c"));
-        t!(r"a\b\c", Some(r"a\b\c"));
-        t!(r"C:\a\b\c", Some(r"C:\a\b\c"));
-        t!(r"C:a\b\c", Some(r"C:a\b\c"));
-        t!(r"\\server\share\foo", Some(r"\\server\share\foo"));
-        t!(r"\\.\foo", None);
-        t!(r"\\?\foo", None);
-        t!(r"\\?\C:", None);
-        t!(r"\\?\C:foo", None);
-        t!(r"\\?\C:\", Some(r"C:\"));
-        t!(r"\\?\C:\foo", Some(r"C:\foo"));
-        t!(r"\\?\C:\foo\bar\baz", Some(r"C:\foo\bar\baz"));
-        t!(r"\\?\C:\foo\.\bar\baz", None);
-        t!(r"\\?\C:\foo\bar\..\baz", None);
-        t!(r"\\?\C:\foo\bar\..", None);
-        t!(r"\\?\UNC\server\share\foo", Some(r"\\server\share\foo"));
-        t!(r"\\?\UNC\server\share", Some(r"\\server\share"));
-        t!(r"\\?\UNC\server", None);
-        t!(r"\\?\UNC\server\", None);
-    }
-}
index 2398485afefb7ab481eaa38a0c18bd59ab941691..d2dc33451200f5f866973f03939eecf2523613c5 100644 (file)
@@ -56,7 +56,7 @@
 #[doc(no_inline)] pub use vec::Vec;
 
 // NB: remove when path reform lands
-#[doc(no_inline)] pub use path::{Path, GenericPath};
+#[doc(no_inline)] pub use old_path::{Path, GenericPath};
 // NB: remove when I/O reform lands
 #[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude};
 // NB: remove when range syntax lands
index 4b45d5501c2351a2797c5d3f7c9ee86a913c1618..797b9332f17dc4cfa134e8f1ab48e02bf7cb1e58 100644 (file)
@@ -20,7 +20,7 @@ mod imp {
     use self::OsRngInner::*;
 
     use old_io::{IoResult, File};
-    use path::Path;
+    use old_path::Path;
     use rand::Rng;
     use rand::reader::ReaderRng;
     use result::Result::Ok;
index ae01586c7039effc671a3f1250f142b48238e26e..6f6b4c58717482522246ca8864b86d6855540871 100644 (file)
@@ -16,7 +16,7 @@
 use sys::{last_error, retry};
 use ffi::CString;
 use num::Int;
-use path::BytesContainer;
+use old_path::BytesContainer;
 use collections;
 
 pub mod backtrace;
index 7e117b10a347c5ed80ffe46edb465a78d2836ff7..20f86227e8eaf291d384ae40a0f34dbb39259e71 100644 (file)
@@ -20,7 +20,7 @@
 use libc::{self, pid_t, c_void, c_int};
 use mem;
 use os;
-use path::BytesContainer;
+use old_path::BytesContainer;
 use ptr;
 use sync::mpsc::{channel, Sender, Receiver};
 use sys::fs::FileDesc;
index 66712b9e3a1e6e6edfbd0bd50a0b3821b46fb555..92e309da34bef34029745a3618743be2d7227e0f 100644 (file)
@@ -32,7 +32,7 @@
 use mem;
 use ops::Drop;
 use option::Option::{Some};
-use path::Path;
+use old_path::Path;
 use ptr;
 use result::Result::{Ok, Err};
 use slice::SliceExt;
index 3ca735f7fdfd347bfba8c86d39b9afe345c35bd5..315c41e779a36c7abfce420642b2cebb1c357a99 100644 (file)
@@ -23,7 +23,7 @@
 use old_io::{IoResult, IoError};
 use old_io;
 use os;
-use path::BytesContainer;
+use old_path::BytesContainer;
 use ptr;
 use str;
 use sync::{StaticMutex, MUTEX_INIT};
index 5c3892e49c0587543e02f334921741b971db5f39..129c1d20bc04c6ecde9bc9bcd8aafe246538688e 100644 (file)
@@ -25,7 +25,7 @@
 use std::fmt;
 use std::mem;
 use std::ops::Deref;
-use std::path::BytesContainer;
+use std::old_path::BytesContainer;
 use std::rc::Rc;
 
 #[allow(non_camel_case_types)]
index fe79165236f8bbfa5b9332cdabd928ba2e1221b9..78c575d33bad0a932285d3389d7377bf35933bbf 100644 (file)
@@ -13,4 +13,4 @@
 pub fn main() {
     let r = 1..2..3;
     //~^ ERROR expected one of `.`, `;`, or an operator, found `..`
-}
\ No newline at end of file
+}
index bbd6ae289cce9452592c158a6e214df246bb9f6c..a3e27fbbe9aa39938935897dd49df88f17858d99 100644 (file)
@@ -13,4 +13,4 @@
 pub fn main() {
     let r = ..1..2;
     //~^ ERROR expected one of `.`, `;`, or an operator, found `..`
-}
\ No newline at end of file
+}
index 6a624e39e326775c93c0bf3d9a2522a3ad8984d4..0f6f0ac6ae7566b76fe5742209ae2876f5d95360 100644 (file)
@@ -149,4 +149,4 @@ fn main() {
     assoc_enum(Enum::Variant2(8i64, 9i32));
 }
 
-fn zzz() { () }
\ No newline at end of file
+fn zzz() { () }