]> git.lizzy.rs Git - rust.git/blob - src/libstd/path.rs
libstd: add example for PathBuf::push
[rust.git] / src / libstd / path.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Cross-platform path manipulation.
12 //!
13 //! This module provides two types, `PathBuf` and `Path` (akin to `String` and
14 //! `str`), for working with paths abstractly. These types are thin wrappers
15 //! around `OsString` and `OsStr` respectively, meaning that they work directly
16 //! on strings according to the local platform's path syntax.
17 //!
18 //! ## Simple usage
19 //!
20 //! Path manipulation includes both parsing components from slices and building
21 //! new owned paths.
22 //!
23 //! To parse a path, you can create a `Path` slice from a `str`
24 //! slice and start asking questions:
25 //!
26 //! ```rust
27 //! use std::path::Path;
28 //!
29 //! let path = Path::new("/tmp/foo/bar.txt");
30 //! let file = path.file_name();
31 //! let extension = path.extension();
32 //! let parent_dir = path.parent();
33 //! ```
34 //!
35 //! To build or modify paths, use `PathBuf`:
36 //!
37 //! ```rust
38 //! use std::path::PathBuf;
39 //!
40 //! let mut path = PathBuf::from("c:\\");
41 //! path.push("windows");
42 //! path.push("system32");
43 //! path.set_extension("dll");
44 //! ```
45 //!
46 //! ## Path components and normalization
47 //!
48 //! The path APIs are built around the notion of "components", which roughly
49 //! correspond to the substrings between path separators (`/` and, on Windows,
50 //! `\`). The APIs for path parsing are largely specified in terms of the path's
51 //! components, so it's important to clearly understand how those are
52 //! determined.
53 //!
54 //! A path can always be reconstructed into an *equivalent* path by
55 //! putting together its components via `push`. Syntactically, the
56 //! paths may differ by the normalization described below.
57 //!
58 //! ### Component types
59 //!
60 //! Components come in several types:
61 //!
62 //! * Normal components are the default: standard references to files or
63 //! directories. The path `a/b` has two normal components, `a` and `b`.
64 //!
65 //! * Current directory components represent the `.` character. For example,
66 //! `./a` has a current directory component and a normal component `a`.
67 //!
68 //! * The root directory component represents a separator that designates
69 //!   starting from root. For example, `/a/b` has a root directory component
70 //!   followed by normal components `a` and `b`.
71 //!
72 //! On Windows, an additional component type comes into play:
73 //!
74 //! * Prefix components, of which there is a large variety. For example, `C:`
75 //! and `\\server\share` are prefixes. The path `C:windows` has a prefix
76 //! component `C:` and a normal component `windows`; the path `C:\windows` has a
77 //! prefix component `C:`, a root directory component, and a normal component
78 //! `windows`.
79 //!
80 //! ### Normalization
81 //!
82 //! Aside from splitting on the separator(s), there is a small amount of
83 //! "normalization":
84 //!
85 //! * Repeated separators are ignored: `a/b` and `a//b` both have components `a`
86 //!   and `b`.
87 //!
88 //! * Occurrences of `.` are normalized away, *except* if they are at
89 //! the beginning of the path (in which case they are often meaningful
90 //! in terms of path searching). So, for example, `a/./b`, `a/b/`,
91 //! `/a/b/.` and `a/b` all have components `a` and `b`, but `./a/b`
92 //! has a leading current directory component.
93 //!
94 //! No other normalization takes place by default. In particular,
95 //! `a/c` and `a/b/../c` are distinct, to account for the possibility
96 //! that `b` is a symbolic link (so its parent isn't `a`). Further
97 //! normalization is possible to build on top of the components APIs,
98 //! and will be included in this library in the near future.
99
100 #![stable(feature = "rust1", since = "1.0.0")]
101
102 use ascii::*;
103 use borrow::{Borrow, IntoCow, ToOwned, Cow};
104 use cmp;
105 use fmt;
106 use fs;
107 use hash::{Hash, Hasher};
108 use io;
109 use iter;
110 use mem;
111 use ops::{self, Deref};
112 use string::String;
113 use vec::Vec;
114
115 use ffi::{OsStr, OsString};
116
117 use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
118
119 ////////////////////////////////////////////////////////////////////////////////
120 // GENERAL NOTES
121 ////////////////////////////////////////////////////////////////////////////////
122 //
123 // Parsing in this module is done by directly transmuting OsStr to [u8] slices,
124 // taking advantage of the fact that OsStr always encodes ASCII characters
125 // as-is.  Eventually, this transmutation should be replaced by direct uses of
126 // OsStr APIs for parsing, but it will take a while for those to become
127 // available.
128
129 ////////////////////////////////////////////////////////////////////////////////
130 // Platform-specific definitions
131 ////////////////////////////////////////////////////////////////////////////////
132
133 // The following modules give the most basic tools for parsing paths on various
134 // platforms. The bulk of the code is devoted to parsing prefixes on Windows.
135
136 #[cfg(unix)]
137 mod platform {
138     use super::Prefix;
139     use ffi::OsStr;
140
141     #[inline]
142     pub fn is_sep_byte(b: u8) -> bool {
143         b == b'/'
144     }
145
146     #[inline]
147     pub fn is_verbatim_sep(b: u8) -> bool {
148         b == b'/'
149     }
150
151     pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
152         None
153     }
154
155     pub const MAIN_SEP_STR: &'static str = "/";
156     pub const MAIN_SEP: char = '/';
157 }
158
159 #[cfg(windows)]
160 mod platform {
161     use ascii::*;
162
163     use super::{os_str_as_u8_slice, u8_slice_as_os_str, Prefix};
164     use ffi::OsStr;
165
166     #[inline]
167     pub fn is_sep_byte(b: u8) -> bool {
168         b == b'/' || b == b'\\'
169     }
170
171     #[inline]
172     pub fn is_verbatim_sep(b: u8) -> bool {
173         b == b'\\'
174     }
175
176     pub fn parse_prefix<'a>(path: &'a OsStr) -> Option<Prefix> {
177         use super::Prefix::*;
178         unsafe {
179             // The unsafety here stems from converting between &OsStr and &[u8]
180             // and back. This is safe to do because (1) we only look at ASCII
181             // contents of the encoding and (2) new &OsStr values are produced
182             // only from ASCII-bounded slices of existing &OsStr values.
183             let mut path = os_str_as_u8_slice(path);
184
185             if path.starts_with(br"\\") {
186                 // \\
187                 path = &path[2..];
188                 if path.starts_with(br"?\") {
189                     // \\?\
190                     path = &path[2..];
191                     if path.starts_with(br"UNC\") {
192                         // \\?\UNC\server\share
193                         path = &path[4..];
194                         let (server, share) = match parse_two_comps(path, is_verbatim_sep) {
195                             Some((server, share)) =>
196                                 (u8_slice_as_os_str(server), u8_slice_as_os_str(share)),
197                             None => (u8_slice_as_os_str(path), u8_slice_as_os_str(&[])),
198                         };
199                         return Some(VerbatimUNC(server, share));
200                     } else {
201                         // \\?\path
202                         let idx = path.iter().position(|&b| b == b'\\');
203                         if idx == Some(2) && path[1] == b':' {
204                             let c = path[0];
205                             if c.is_ascii() && (c as char).is_alphabetic() {
206                                 // \\?\C:\ path
207                                 return Some(VerbatimDisk(c.to_ascii_uppercase()));
208                             }
209                         }
210                         let slice = &path[..idx.unwrap_or(path.len())];
211                         return Some(Verbatim(u8_slice_as_os_str(slice)));
212                     }
213                 } else if path.starts_with(b".\\") {
214                     // \\.\path
215                     path = &path[2..];
216                     let pos = path.iter().position(|&b| b == b'\\');
217                     let slice = &path[..pos.unwrap_or(path.len())];
218                     return Some(DeviceNS(u8_slice_as_os_str(slice)));
219                 }
220                 match parse_two_comps(path, is_sep_byte) {
221                     Some((server, share)) if !server.is_empty() && !share.is_empty() => {
222                         // \\server\share
223                         return Some(UNC(u8_slice_as_os_str(server), u8_slice_as_os_str(share)));
224                     }
225                     _ => (),
226                 }
227             } else if path.len() > 1 && path[1] == b':' {
228                 // C:
229                 let c = path[0];
230                 if c.is_ascii() && (c as char).is_alphabetic() {
231                     return Some(Disk(c.to_ascii_uppercase()));
232                 }
233             }
234             return None;
235         }
236
237         fn parse_two_comps(mut path: &[u8], f: fn(u8) -> bool) -> Option<(&[u8], &[u8])> {
238             let first = match path.iter().position(|x| f(*x)) {
239                 None => return None,
240                 Some(x) => &path[..x],
241             };
242             path = &path[(first.len() + 1)..];
243             let idx = path.iter().position(|x| f(*x));
244             let second = &path[..idx.unwrap_or(path.len())];
245             Some((first, second))
246         }
247     }
248
249     pub const MAIN_SEP_STR: &'static str = "\\";
250     pub const MAIN_SEP: char = '\\';
251 }
252
253 ////////////////////////////////////////////////////////////////////////////////
254 // Windows Prefixes
255 ////////////////////////////////////////////////////////////////////////////////
256
257 /// Path prefixes (Windows only).
258 ///
259 /// Windows uses a variety of path styles, including references to drive
260 /// volumes (like `C:`), network shared folders (like `\\server\share`) and
261 /// others. In addition, some path prefixes are "verbatim", in which case
262 /// `/` is *not* treated as a separator and essentially no normalization is
263 /// performed.
264 #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
265 #[stable(feature = "rust1", since = "1.0.0")]
266 pub enum Prefix<'a> {
267     /// Prefix `\\?\`, together with the given component immediately following it.
268     #[stable(feature = "rust1", since = "1.0.0")]
269     Verbatim(&'a OsStr),
270
271     /// Prefix `\\?\UNC\`, with the "server" and "share" components following it.
272     #[stable(feature = "rust1", since = "1.0.0")]
273     VerbatimUNC(&'a OsStr, &'a OsStr),
274
275     /// Prefix like `\\?\C:\`, for the given drive letter
276     #[stable(feature = "rust1", since = "1.0.0")]
277     VerbatimDisk(u8),
278
279     /// Prefix `\\.\`, together with the given component immediately following it.
280     #[stable(feature = "rust1", since = "1.0.0")]
281     DeviceNS(&'a OsStr),
282
283     /// Prefix `\\server\share`, with the given "server" and "share" components.
284     #[stable(feature = "rust1", since = "1.0.0")]
285     UNC(&'a OsStr, &'a OsStr),
286
287     /// Prefix `C:` for the given disk drive.
288     #[stable(feature = "rust1", since = "1.0.0")]
289     Disk(u8),
290 }
291
292 impl<'a> Prefix<'a> {
293     #[inline]
294     fn len(&self) -> usize {
295         use self::Prefix::*;
296         fn os_str_len(s: &OsStr) -> usize {
297             os_str_as_u8_slice(s).len()
298         }
299         match *self {
300             Verbatim(x) => 4 + os_str_len(x),
301             VerbatimUNC(x, y) => {
302                 8 + os_str_len(x) +
303                 if os_str_len(y) > 0 {
304                     1 + os_str_len(y)
305                 } else {
306                     0
307                 }
308             },
309             VerbatimDisk(_) => 6,
310             UNC(x, y) => {
311                 2 + os_str_len(x) +
312                 if os_str_len(y) > 0 {
313                     1 + os_str_len(y)
314                 } else {
315                     0
316                 }
317             },
318             DeviceNS(x) => 4 + os_str_len(x),
319             Disk(_) => 2,
320         }
321
322     }
323
324     /// Determines if the prefix is verbatim, i.e. begins with `\\?\`.
325     #[inline]
326     #[stable(feature = "rust1", since = "1.0.0")]
327     pub fn is_verbatim(&self) -> bool {
328         use self::Prefix::*;
329         match *self {
330             Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(_, _) => true,
331             _ => false,
332         }
333     }
334
335     #[inline]
336     fn is_drive(&self) -> bool {
337         match *self {
338             Prefix::Disk(_) => true,
339             _ => false,
340         }
341     }
342
343     #[inline]
344     fn has_implicit_root(&self) -> bool {
345         !self.is_drive()
346     }
347 }
348
349 ////////////////////////////////////////////////////////////////////////////////
350 // Exposed parsing helpers
351 ////////////////////////////////////////////////////////////////////////////////
352
353 /// Determines whether the character is one of the permitted path
354 /// separators for the current platform.
355 ///
356 /// # Examples
357 ///
358 /// ```
359 /// use std::path;
360 ///
361 /// assert!(path::is_separator('/'));
362 /// assert!(!path::is_separator('❤'));
363 /// ```
364 #[stable(feature = "rust1", since = "1.0.0")]
365 pub fn is_separator(c: char) -> bool {
366     c.is_ascii() && is_sep_byte(c as u8)
367 }
368
369 /// The primary separator for the current platform
370 #[stable(feature = "rust1", since = "1.0.0")]
371 pub const MAIN_SEPARATOR: char = platform::MAIN_SEP;
372
373 ////////////////////////////////////////////////////////////////////////////////
374 // Misc helpers
375 ////////////////////////////////////////////////////////////////////////////////
376
377 // Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
378 // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
379 // `iter` after having exhausted `prefix`.
380 fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>
381     where I: Iterator<Item = A> + Clone,
382           J: Iterator<Item = A>,
383           A: PartialEq
384 {
385     loop {
386         let mut iter_next = iter.clone();
387         match (iter_next.next(), prefix.next()) {
388             (Some(x), Some(y)) => {
389                 if x != y {
390                     return None;
391                 }
392             }
393             (Some(_), None) => return Some(iter),
394             (None, None) => return Some(iter),
395             (None, Some(_)) => return None,
396         }
397         iter = iter_next;
398     }
399 }
400
401 // See note at the top of this module to understand why these are used:
402 fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
403     unsafe { mem::transmute(s) }
404 }
405 unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
406     mem::transmute(s)
407 }
408
409 ////////////////////////////////////////////////////////////////////////////////
410 // Cross-platform, iterator-independent parsing
411 ////////////////////////////////////////////////////////////////////////////////
412
413 /// Says whether the first byte after the prefix is a separator.
414 fn has_physical_root(s: &[u8], prefix: Option<Prefix>) -> bool {
415     let path = if let Some(p) = prefix {
416         &s[p.len()..]
417     } else {
418         s
419     };
420     !path.is_empty() && is_sep_byte(path[0])
421 }
422
423 // basic workhorse for splitting stem and extension
424 fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
425     unsafe {
426         if os_str_as_u8_slice(file) == b".." {
427             return (Some(file), None);
428         }
429
430         // The unsafety here stems from converting between &OsStr and &[u8]
431         // and back. This is safe to do because (1) we only look at ASCII
432         // contents of the encoding and (2) new &OsStr values are produced
433         // only from ASCII-bounded slices of existing &OsStr values.
434
435         let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
436         let after = iter.next();
437         let before = iter.next();
438         if before == Some(b"") {
439             (Some(file), None)
440         } else {
441             (before.map(|s| u8_slice_as_os_str(s)),
442              after.map(|s| u8_slice_as_os_str(s)))
443         }
444     }
445 }
446
447 ////////////////////////////////////////////////////////////////////////////////
448 // The core iterators
449 ////////////////////////////////////////////////////////////////////////////////
450
451 /// Component parsing works by a double-ended state machine; the cursors at the
452 /// front and back of the path each keep track of what parts of the path have
453 /// been consumed so far.
454 ///
455 /// Going front to back, a path is made up of a prefix, a starting
456 /// directory component, and a body (of normal components)
457 #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
458 enum State {
459     Prefix = 0,         // c:
460     StartDir = 1,       // / or . or nothing
461     Body = 2,           // foo/bar/baz
462     Done = 3,
463 }
464
465 /// A Windows path prefix, e.g. `C:` or `\server\share`.
466 ///
467 /// Does not occur on Unix.
468 #[stable(feature = "rust1", since = "1.0.0")]
469 #[derive(Copy, Clone, Eq, Debug)]
470 pub struct PrefixComponent<'a> {
471     /// The prefix as an unparsed `OsStr` slice.
472     raw: &'a OsStr,
473
474     /// The parsed prefix data.
475     parsed: Prefix<'a>,
476 }
477
478 impl<'a> PrefixComponent<'a> {
479     /// The parsed prefix data.
480     #[stable(feature = "rust1", since = "1.0.0")]
481     pub fn kind(&self) -> Prefix<'a> {
482         self.parsed
483     }
484
485     /// The raw `OsStr` slice for this prefix.
486     #[stable(feature = "rust1", since = "1.0.0")]
487     pub fn as_os_str(&self) -> &'a OsStr {
488         self.raw
489     }
490 }
491
492 #[stable(feature = "rust1", since = "1.0.0")]
493 impl<'a> cmp::PartialEq for PrefixComponent<'a> {
494     fn eq(&self, other: &PrefixComponent<'a>) -> bool {
495         cmp::PartialEq::eq(&self.parsed, &other.parsed)
496     }
497 }
498
499 #[stable(feature = "rust1", since = "1.0.0")]
500 impl<'a> cmp::PartialOrd for PrefixComponent<'a> {
501     fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> {
502         cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed)
503     }
504 }
505
506 #[stable(feature = "rust1", since = "1.0.0")]
507 impl<'a> cmp::Ord for PrefixComponent<'a> {
508     fn cmp(&self, other: &PrefixComponent<'a>) -> cmp::Ordering {
509         cmp::Ord::cmp(&self.parsed, &other.parsed)
510     }
511 }
512
513 #[stable(feature = "rust1", since = "1.0.0")]
514 impl<'a> Hash for PrefixComponent<'a> {
515     fn hash<H: Hasher>(&self, h: &mut H) {
516         self.parsed.hash(h);
517     }
518 }
519
520 /// A single component of a path.
521 ///
522 /// See the module documentation for an in-depth explanation of components and
523 /// their role in the API.
524 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
525 #[stable(feature = "rust1", since = "1.0.0")]
526 pub enum Component<'a> {
527     /// A Windows path prefix, e.g. `C:` or `\server\share`.
528     ///
529     /// Does not occur on Unix.
530     #[stable(feature = "rust1", since = "1.0.0")]
531     Prefix(PrefixComponent<'a>),
532
533     /// The root directory component, appears after any prefix and before anything else
534     #[stable(feature = "rust1", since = "1.0.0")]
535     RootDir,
536
537     /// A reference to the current directory, i.e. `.`
538     #[stable(feature = "rust1", since = "1.0.0")]
539     CurDir,
540
541     /// A reference to the parent directory, i.e. `..`
542     #[stable(feature = "rust1", since = "1.0.0")]
543     ParentDir,
544
545     /// A normal component, i.e. `a` and `b` in `a/b`
546     #[stable(feature = "rust1", since = "1.0.0")]
547     Normal(&'a OsStr),
548 }
549
550 impl<'a> Component<'a> {
551     /// Extracts the underlying `OsStr` slice
552     #[stable(feature = "rust1", since = "1.0.0")]
553     pub fn as_os_str(self) -> &'a OsStr {
554         match self {
555             Component::Prefix(p) => p.as_os_str(),
556             Component::RootDir => OsStr::new(MAIN_SEP_STR),
557             Component::CurDir => OsStr::new("."),
558             Component::ParentDir => OsStr::new(".."),
559             Component::Normal(path) => path,
560         }
561     }
562 }
563
564 #[stable(feature = "rust1", since = "1.0.0")]
565 impl<'a> AsRef<OsStr> for Component<'a> {
566     fn as_ref(&self) -> &OsStr {
567         self.as_os_str()
568     }
569 }
570
571 /// The core iterator giving the components of a path.
572 ///
573 /// See the module documentation for an in-depth explanation of components and
574 /// their role in the API.
575 ///
576 /// # Examples
577 ///
578 /// ```
579 /// use std::path::Path;
580 ///
581 /// let path = Path::new("/tmp/foo/bar.txt");
582 ///
583 /// for component in path.components() {
584 ///     println!("{:?}", component);
585 /// }
586 /// ```
587 #[derive(Clone)]
588 #[stable(feature = "rust1", since = "1.0.0")]
589 pub struct Components<'a> {
590     // The path left to parse components from
591     path: &'a [u8],
592
593     // The prefix as it was originally parsed, if any
594     prefix: Option<Prefix<'a>>,
595
596     // true if path *physically* has a root separator; for most Windows
597     // prefixes, it may have a "logical" rootseparator for the purposes of
598     // normalization, e.g.  \\server\share == \\server\share\.
599     has_physical_root: bool,
600
601     // The iterator is double-ended, and these two states keep track of what has
602     // been produced from either end
603     front: State,
604     back: State,
605 }
606
607 /// An iterator over the components of a path, as `OsStr` slices.
608 #[derive(Clone)]
609 #[stable(feature = "rust1", since = "1.0.0")]
610 pub struct Iter<'a> {
611     inner: Components<'a>,
612 }
613
614 impl<'a> Components<'a> {
615     // how long is the prefix, if any?
616     #[inline]
617     fn prefix_len(&self) -> usize {
618         self.prefix.as_ref().map(Prefix::len).unwrap_or(0)
619     }
620
621     #[inline]
622     fn prefix_verbatim(&self) -> bool {
623         self.prefix.as_ref().map(Prefix::is_verbatim).unwrap_or(false)
624     }
625
626     /// how much of the prefix is left from the point of view of iteration?
627     #[inline]
628     fn prefix_remaining(&self) -> usize {
629         if self.front == State::Prefix {
630             self.prefix_len()
631         } else {
632             0
633         }
634     }
635
636     // Given the iteration so far, how much of the pre-State::Body path is left?
637     #[inline]
638     fn len_before_body(&self) -> usize {
639         let root = if self.front <= State::StartDir && self.has_physical_root {
640             1
641         } else {
642             0
643         };
644         let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() {
645             1
646         } else {
647             0
648         };
649         self.prefix_remaining() + root + cur_dir
650     }
651
652     // is the iteration complete?
653     #[inline]
654     fn finished(&self) -> bool {
655         self.front == State::Done || self.back == State::Done || self.front > self.back
656     }
657
658     #[inline]
659     fn is_sep_byte(&self, b: u8) -> bool {
660         if self.prefix_verbatim() {
661             is_verbatim_sep(b)
662         } else {
663             is_sep_byte(b)
664         }
665     }
666
667     /// Extracts a slice corresponding to the portion of the path remaining for iteration.
668     ///
669     /// # Examples
670     ///
671     /// ```
672     /// use std::path::Path;
673     ///
674     /// let mut components = Path::new("/tmp/foo/bar.txt").components();
675     /// components.next();
676     /// components.next();
677     ///
678     /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());
679     /// ```
680     #[stable(feature = "rust1", since = "1.0.0")]
681     pub fn as_path(&self) -> &'a Path {
682         let mut comps = self.clone();
683         if comps.front == State::Body {
684             comps.trim_left();
685         }
686         if comps.back == State::Body {
687             comps.trim_right();
688         }
689         unsafe { Path::from_u8_slice(comps.path) }
690     }
691
692     /// Is the *original* path rooted?
693     fn has_root(&self) -> bool {
694         if self.has_physical_root {
695             return true;
696         }
697         if let Some(p) = self.prefix {
698             if p.has_implicit_root() {
699                 return true;
700             }
701         }
702         false
703     }
704
705     /// Should the normalized path include a leading . ?
706     fn include_cur_dir(&self) -> bool {
707         if self.has_root() {
708             return false;
709         }
710         let mut iter = self.path[self.prefix_len()..].iter();
711         match (iter.next(), iter.next()) {
712             (Some(&b'.'), None) => true,
713             (Some(&b'.'), Some(&b)) => self.is_sep_byte(b),
714             _ => false,
715         }
716     }
717
718     // parse a given byte sequence into the corresponding path component
719     fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
720         match comp {
721             b"." if self.prefix_verbatim() => Some(Component::CurDir),
722             b"." => None, // . components are normalized away, except at
723                           // the beginning of a path, which is treated
724                           // separately via `include_cur_dir`
725             b".." => Some(Component::ParentDir),
726             b"" => None,
727             _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })),
728         }
729     }
730
731     // parse a component from the left, saying how many bytes to consume to
732     // remove the component
733     fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {
734         debug_assert!(self.front == State::Body);
735         let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) {
736             None => (0, self.path),
737             Some(i) => (1, &self.path[..i]),
738         };
739         (comp.len() + extra, self.parse_single_component(comp))
740     }
741
742     // parse a component from the right, saying how many bytes to consume to
743     // remove the component
744     fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {
745         debug_assert!(self.back == State::Body);
746         let start = self.len_before_body();
747         let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) {
748             None => (0, &self.path[start..]),
749             Some(i) => (1, &self.path[start + i + 1..]),
750         };
751         (comp.len() + extra, self.parse_single_component(comp))
752     }
753
754     // trim away repeated separators (i.e. empty components) on the left
755     fn trim_left(&mut self) {
756         while !self.path.is_empty() {
757             let (size, comp) = self.parse_next_component();
758             if comp.is_some() {
759                 return;
760             } else {
761                 self.path = &self.path[size..];
762             }
763         }
764     }
765
766     // trim away repeated separators (i.e. empty components) on the right
767     fn trim_right(&mut self) {
768         while self.path.len() > self.len_before_body() {
769             let (size, comp) = self.parse_next_component_back();
770             if comp.is_some() {
771                 return;
772             } else {
773                 self.path = &self.path[..self.path.len() - size];
774             }
775         }
776     }
777
778     /// Examine the next component without consuming it.
779     #[unstable(feature = "path_components_peek", issue = "27727")]
780     pub fn peek(&self) -> Option<Component<'a>> {
781         self.clone().next()
782     }
783 }
784
785 #[stable(feature = "rust1", since = "1.0.0")]
786 impl<'a> AsRef<Path> for Components<'a> {
787     fn as_ref(&self) -> &Path {
788         self.as_path()
789     }
790 }
791
792 #[stable(feature = "rust1", since = "1.0.0")]
793 impl<'a> AsRef<OsStr> for Components<'a> {
794     fn as_ref(&self) -> &OsStr {
795         self.as_path().as_os_str()
796     }
797 }
798
799 impl<'a> Iter<'a> {
800     /// Extracts a slice corresponding to the portion of the path remaining for iteration.
801     #[stable(feature = "rust1", since = "1.0.0")]
802     pub fn as_path(&self) -> &'a Path {
803         self.inner.as_path()
804     }
805 }
806
807 #[stable(feature = "rust1", since = "1.0.0")]
808 impl<'a> AsRef<Path> for Iter<'a> {
809     fn as_ref(&self) -> &Path {
810         self.as_path()
811     }
812 }
813
814 #[stable(feature = "rust1", since = "1.0.0")]
815 impl<'a> AsRef<OsStr> for Iter<'a> {
816     fn as_ref(&self) -> &OsStr {
817         self.as_path().as_os_str()
818     }
819 }
820
821 #[stable(feature = "rust1", since = "1.0.0")]
822 impl<'a> Iterator for Iter<'a> {
823     type Item = &'a OsStr;
824
825     fn next(&mut self) -> Option<&'a OsStr> {
826         self.inner.next().map(Component::as_os_str)
827     }
828 }
829
830 #[stable(feature = "rust1", since = "1.0.0")]
831 impl<'a> DoubleEndedIterator for Iter<'a> {
832     fn next_back(&mut self) -> Option<&'a OsStr> {
833         self.inner.next_back().map(Component::as_os_str)
834     }
835 }
836
837 #[stable(feature = "rust1", since = "1.0.0")]
838 impl<'a> Iterator for Components<'a> {
839     type Item = Component<'a>;
840
841     fn next(&mut self) -> Option<Component<'a>> {
842         while !self.finished() {
843             match self.front {
844                 State::Prefix if self.prefix_len() > 0 => {
845                     self.front = State::StartDir;
846                     debug_assert!(self.prefix_len() <= self.path.len());
847                     let raw = &self.path[..self.prefix_len()];
848                     self.path = &self.path[self.prefix_len()..];
849                     return Some(Component::Prefix(PrefixComponent {
850                         raw: unsafe { u8_slice_as_os_str(raw) },
851                         parsed: self.prefix.unwrap(),
852                     }));
853                 }
854                 State::Prefix => {
855                     self.front = State::StartDir;
856                 }
857                 State::StartDir => {
858                     self.front = State::Body;
859                     if self.has_physical_root {
860                         debug_assert!(!self.path.is_empty());
861                         self.path = &self.path[1..];
862                         return Some(Component::RootDir);
863                     } else if let Some(p) = self.prefix {
864                         if p.has_implicit_root() && !p.is_verbatim() {
865                             return Some(Component::RootDir);
866                         }
867                     } else if self.include_cur_dir() {
868                         debug_assert!(!self.path.is_empty());
869                         self.path = &self.path[1..];
870                         return Some(Component::CurDir);
871                     }
872                 }
873                 State::Body if !self.path.is_empty() => {
874                     let (size, comp) = self.parse_next_component();
875                     self.path = &self.path[size..];
876                     if comp.is_some() {
877                         return comp;
878                     }
879                 }
880                 State::Body => {
881                     self.front = State::Done;
882                 }
883                 State::Done => unreachable!(),
884             }
885         }
886         None
887     }
888 }
889
890 #[stable(feature = "rust1", since = "1.0.0")]
891 impl<'a> DoubleEndedIterator for Components<'a> {
892     fn next_back(&mut self) -> Option<Component<'a>> {
893         while !self.finished() {
894             match self.back {
895                 State::Body if self.path.len() > self.len_before_body() => {
896                     let (size, comp) = self.parse_next_component_back();
897                     self.path = &self.path[..self.path.len() - size];
898                     if comp.is_some() {
899                         return comp;
900                     }
901                 }
902                 State::Body => {
903                     self.back = State::StartDir;
904                 }
905                 State::StartDir => {
906                     self.back = State::Prefix;
907                     if self.has_physical_root {
908                         self.path = &self.path[..self.path.len() - 1];
909                         return Some(Component::RootDir);
910                     } else if let Some(p) = self.prefix {
911                         if p.has_implicit_root() && !p.is_verbatim() {
912                             return Some(Component::RootDir);
913                         }
914                     } else if self.include_cur_dir() {
915                         self.path = &self.path[..self.path.len() - 1];
916                         return Some(Component::CurDir);
917                     }
918                 }
919                 State::Prefix if self.prefix_len() > 0 => {
920                     self.back = State::Done;
921                     return Some(Component::Prefix(PrefixComponent {
922                         raw: unsafe { u8_slice_as_os_str(self.path) },
923                         parsed: self.prefix.unwrap(),
924                     }));
925                 }
926                 State::Prefix => {
927                     self.back = State::Done;
928                     return None;
929                 }
930                 State::Done => unreachable!(),
931             }
932         }
933         None
934     }
935 }
936
937 #[stable(feature = "rust1", since = "1.0.0")]
938 impl<'a> cmp::PartialEq for Components<'a> {
939     fn eq(&self, other: &Components<'a>) -> bool {
940         Iterator::eq(self.clone(), other.clone())
941     }
942 }
943
944 #[stable(feature = "rust1", since = "1.0.0")]
945 impl<'a> cmp::Eq for Components<'a> {}
946
947 #[stable(feature = "rust1", since = "1.0.0")]
948 impl<'a> cmp::PartialOrd for Components<'a> {
949     fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
950         Iterator::partial_cmp(self.clone(), other.clone())
951     }
952 }
953
954 #[stable(feature = "rust1", since = "1.0.0")]
955 impl<'a> cmp::Ord for Components<'a> {
956     fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
957         Iterator::cmp(self.clone(), other.clone())
958     }
959 }
960
961 ////////////////////////////////////////////////////////////////////////////////
962 // Basic types and traits
963 ////////////////////////////////////////////////////////////////////////////////
964
965 /// An owned, mutable path (akin to `String`).
966 ///
967 /// This type provides methods like `push` and `set_extension` that mutate the
968 /// path in place. It also implements `Deref` to `Path`, meaning that all
969 /// methods on `Path` slices are available on `PathBuf` values as well.
970 ///
971 /// More details about the overall approach can be found in
972 /// the module documentation.
973 ///
974 /// # Examples
975 ///
976 /// ```
977 /// use std::path::PathBuf;
978 ///
979 /// let mut path = PathBuf::from("c:\\");
980 /// path.push("windows");
981 /// path.push("system32");
982 /// path.set_extension("dll");
983 /// ```
984 #[derive(Clone)]
985 #[stable(feature = "rust1", since = "1.0.0")]
986 pub struct PathBuf {
987     inner: OsString,
988 }
989
990 impl PathBuf {
991     fn as_mut_vec(&mut self) -> &mut Vec<u8> {
992         unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
993     }
994
995     /// Allocates an empty `PathBuf`.
996     #[stable(feature = "rust1", since = "1.0.0")]
997     pub fn new() -> PathBuf {
998         PathBuf { inner: OsString::new() }
999     }
1000
1001     /// Coerces to a `Path` slice.
1002     #[stable(feature = "rust1", since = "1.0.0")]
1003     pub fn as_path(&self) -> &Path {
1004         self
1005     }
1006
1007     /// Extends `self` with `path`.
1008     ///
1009     /// If `path` is absolute, it replaces the current path.
1010     ///
1011     /// On Windows:
1012     ///
1013     /// * if `path` has a root but no prefix (e.g. `\windows`), it
1014     ///   replaces everything except for the prefix (if any) of `self`.
1015     /// * if `path` has a prefix but no root, it replaces `self`.
1016     ///
1017     /// # Examples
1018     ///
1019     /// ```
1020     /// use std::path::PathBuf;
1021     ///
1022     /// let mut path = PathBuf::new();
1023     /// path.push("/tmp");
1024     /// path.push("file.bk");
1025     /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
1026     ///
1027     /// // Pushing an absolute path replaces the current path
1028     /// path.push("/etc/passwd");
1029     /// assert_eq!(path, PathBuf::from("/etc/passwd"));
1030     /// ```
1031     #[stable(feature = "rust1", since = "1.0.0")]
1032     pub fn push<P: AsRef<Path>>(&mut self, path: P) {
1033         self._push(path.as_ref())
1034     }
1035
1036     fn _push(&mut self, path: &Path) {
1037         // in general, a separator is needed if the rightmost byte is not a separator
1038         let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
1039
1040         // in the special case of `C:` on Windows, do *not* add a separator
1041         {
1042             let comps = self.components();
1043             if comps.prefix_len() > 0 && comps.prefix_len() == comps.path.len() &&
1044                comps.prefix.unwrap().is_drive() {
1045                 need_sep = false
1046             }
1047         }
1048
1049         // absolute `path` replaces `self`
1050         if path.is_absolute() || path.prefix().is_some() {
1051             self.as_mut_vec().truncate(0);
1052
1053         // `path` has a root but no prefix, e.g. `\windows` (Windows only)
1054         } else if path.has_root() {
1055             let prefix_len = self.components().prefix_remaining();
1056             self.as_mut_vec().truncate(prefix_len);
1057
1058         // `path` is a pure relative path
1059         } else if need_sep {
1060             self.inner.push(MAIN_SEP_STR);
1061         }
1062
1063         self.inner.push(path);
1064     }
1065
1066     /// Truncate `self` to `self.parent()`.
1067     ///
1068     /// Returns false and does nothing if `self.file_name()` is `None`.
1069     /// Otherwise, returns `true`.
1070     #[stable(feature = "rust1", since = "1.0.0")]
1071     pub fn pop(&mut self) -> bool {
1072         match self.parent().map(|p| p.as_u8_slice().len()) {
1073             Some(len) => {
1074                 self.as_mut_vec().truncate(len);
1075                 true
1076             }
1077             None => false,
1078         }
1079     }
1080
1081     /// Updates `self.file_name()` to `file_name`.
1082     ///
1083     /// If `self.file_name()` was `None`, this is equivalent to pushing
1084     /// `file_name`.
1085     ///
1086     /// # Examples
1087     ///
1088     /// ```
1089     /// use std::path::PathBuf;
1090     ///
1091     /// let mut buf = PathBuf::from("/");
1092     /// assert!(buf.file_name() == None);
1093     /// buf.set_file_name("bar");
1094     /// assert!(buf == PathBuf::from("/bar"));
1095     /// assert!(buf.file_name().is_some());
1096     /// buf.set_file_name("baz.txt");
1097     /// assert!(buf == PathBuf::from("/baz.txt"));
1098     /// ```
1099     #[stable(feature = "rust1", since = "1.0.0")]
1100     pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
1101         self._set_file_name(file_name.as_ref())
1102     }
1103
1104     fn _set_file_name(&mut self, file_name: &OsStr) {
1105         if self.file_name().is_some() {
1106             let popped = self.pop();
1107             debug_assert!(popped);
1108         }
1109         self.push(file_name);
1110     }
1111
1112     /// Updates `self.extension()` to `extension`.
1113     ///
1114     /// If `self.file_name()` is `None`, does nothing and returns `false`.
1115     ///
1116     /// Otherwise, returns `true`; if `self.extension()` is `None`, the extension
1117     /// is added; otherwise it is replaced.
1118     #[stable(feature = "rust1", since = "1.0.0")]
1119     pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
1120         self._set_extension(extension.as_ref())
1121     }
1122
1123     fn _set_extension(&mut self, extension: &OsStr) -> bool {
1124         if self.file_name().is_none() {
1125             return false;
1126         }
1127
1128         let mut stem = match self.file_stem() {
1129             Some(stem) => stem.to_os_string(),
1130             None => OsString::new(),
1131         };
1132
1133         if !os_str_as_u8_slice(extension).is_empty() {
1134             stem.push(".");
1135             stem.push(extension);
1136         }
1137         self.set_file_name(&stem);
1138
1139         true
1140     }
1141
1142     /// Consumes the `PathBuf`, yielding its internal `OsString` storage.
1143     #[stable(feature = "rust1", since = "1.0.0")]
1144     pub fn into_os_string(self) -> OsString {
1145         self.inner
1146     }
1147 }
1148
1149 #[stable(feature = "rust1", since = "1.0.0")]
1150 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
1151     fn from(s: &'a T) -> PathBuf {
1152         PathBuf::from(s.as_ref().to_os_string())
1153     }
1154 }
1155
1156 #[stable(feature = "rust1", since = "1.0.0")]
1157 impl From<OsString> for PathBuf {
1158     fn from(s: OsString) -> PathBuf {
1159         PathBuf { inner: s }
1160     }
1161 }
1162
1163 #[stable(feature = "rust1", since = "1.0.0")]
1164 impl From<String> for PathBuf {
1165     fn from(s: String) -> PathBuf {
1166         PathBuf::from(OsString::from(s))
1167     }
1168 }
1169
1170 #[stable(feature = "rust1", since = "1.0.0")]
1171 impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
1172     fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
1173         let mut buf = PathBuf::new();
1174         buf.extend(iter);
1175         buf
1176     }
1177 }
1178
1179 #[stable(feature = "rust1", since = "1.0.0")]
1180 impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
1181     fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
1182         for p in iter {
1183             self.push(p.as_ref())
1184         }
1185     }
1186 }
1187
1188 #[stable(feature = "rust1", since = "1.0.0")]
1189 impl fmt::Debug for PathBuf {
1190     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1191         fmt::Debug::fmt(&**self, formatter)
1192     }
1193 }
1194
1195 #[stable(feature = "rust1", since = "1.0.0")]
1196 impl ops::Deref for PathBuf {
1197     type Target = Path;
1198
1199     fn deref(&self) -> &Path {
1200         Path::new(&self.inner)
1201     }
1202 }
1203
1204 #[stable(feature = "rust1", since = "1.0.0")]
1205 impl Borrow<Path> for PathBuf {
1206     fn borrow(&self) -> &Path {
1207         self.deref()
1208     }
1209 }
1210
1211 #[stable(feature = "rust1", since = "1.0.0")]
1212 impl IntoCow<'static, Path> for PathBuf {
1213     fn into_cow(self) -> Cow<'static, Path> {
1214         Cow::Owned(self)
1215     }
1216 }
1217
1218 #[stable(feature = "rust1", since = "1.0.0")]
1219 impl<'a> IntoCow<'a, Path> for &'a Path {
1220     fn into_cow(self) -> Cow<'a, Path> {
1221         Cow::Borrowed(self)
1222     }
1223 }
1224
1225 #[stable(feature = "cow_from_path", since = "1.6.0")]
1226 impl<'a> From<&'a Path> for Cow<'a, Path> {
1227     #[inline]
1228     fn from(s: &'a Path) -> Cow<'a, Path> {
1229         Cow::Borrowed(s)
1230     }
1231 }
1232
1233 #[stable(feature = "cow_from_path", since = "1.6.0")]
1234 impl<'a> From<PathBuf> for Cow<'a, Path> {
1235     #[inline]
1236     fn from(s: PathBuf) -> Cow<'a, Path> {
1237         Cow::Owned(s)
1238     }
1239 }
1240
1241 #[stable(feature = "rust1", since = "1.0.0")]
1242 impl ToOwned for Path {
1243     type Owned = PathBuf;
1244     fn to_owned(&self) -> PathBuf {
1245         self.to_path_buf()
1246     }
1247 }
1248
1249 #[stable(feature = "rust1", since = "1.0.0")]
1250 impl cmp::PartialEq for PathBuf {
1251     fn eq(&self, other: &PathBuf) -> bool {
1252         self.components() == other.components()
1253     }
1254 }
1255
1256 #[stable(feature = "rust1", since = "1.0.0")]
1257 impl Hash for PathBuf {
1258     fn hash<H: Hasher>(&self, h: &mut H) {
1259         self.as_path().hash(h)
1260     }
1261 }
1262
1263 #[stable(feature = "rust1", since = "1.0.0")]
1264 impl cmp::Eq for PathBuf {}
1265
1266 #[stable(feature = "rust1", since = "1.0.0")]
1267 impl cmp::PartialOrd for PathBuf {
1268     fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
1269         self.components().partial_cmp(other.components())
1270     }
1271 }
1272
1273 #[stable(feature = "rust1", since = "1.0.0")]
1274 impl cmp::Ord for PathBuf {
1275     fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
1276         self.components().cmp(other.components())
1277     }
1278 }
1279
1280 #[stable(feature = "rust1", since = "1.0.0")]
1281 impl AsRef<OsStr> for PathBuf {
1282     fn as_ref(&self) -> &OsStr {
1283         &self.inner[..]
1284     }
1285 }
1286
1287 #[stable(feature = "rust1", since = "1.0.0")]
1288 impl Into<OsString> for PathBuf {
1289     fn into(self) -> OsString {
1290         self.inner
1291     }
1292 }
1293
1294 /// A slice of a path (akin to `str`).
1295 ///
1296 /// This type supports a number of operations for inspecting a path, including
1297 /// breaking the path into its components (separated by `/` or `\`, depending on
1298 /// the platform), extracting the file name, determining whether the path is
1299 /// absolute, and so on. More details about the overall approach can be found in
1300 /// the module documentation.
1301 ///
1302 /// This is an *unsized* type, meaning that it must always be used behind a
1303 /// pointer like `&` or `Box`.
1304 ///
1305 /// # Examples
1306 ///
1307 /// ```
1308 /// use std::path::Path;
1309 ///
1310 /// let path = Path::new("/tmp/foo/bar.txt");
1311 /// let file = path.file_name();
1312 /// let extension = path.extension();
1313 /// let parent_dir = path.parent();
1314 /// ```
1315 ///
1316 #[stable(feature = "rust1", since = "1.0.0")]
1317 pub struct Path {
1318     inner: OsStr,
1319 }
1320
1321 impl Path {
1322     // The following (private!) function allows construction of a path from a u8
1323     // slice, which is only safe when it is known to follow the OsStr encoding.
1324     unsafe fn from_u8_slice(s: &[u8]) -> &Path {
1325         Path::new(u8_slice_as_os_str(s))
1326     }
1327     // The following (private!) function reveals the byte encoding used for OsStr.
1328     fn as_u8_slice(&self) -> &[u8] {
1329         os_str_as_u8_slice(&self.inner)
1330     }
1331
1332     /// Directly wrap a string slice as a `Path` slice.
1333     ///
1334     /// This is a cost-free conversion.
1335     ///
1336     /// # Examples
1337     ///
1338     /// ```
1339     /// use std::path::Path;
1340     ///
1341     /// Path::new("foo.txt");
1342     /// ```
1343     ///
1344     /// You can create `Path`s from `String`s, or even other `Path`s:
1345     ///
1346     /// ```
1347     /// use std::path::Path;
1348     ///
1349     /// let string = String::from("foo.txt");
1350     /// let from_string = Path::new(&string);
1351     /// let from_path = Path::new(&from_string);
1352     /// assert_eq!(from_string, from_path);
1353     /// ```
1354     #[stable(feature = "rust1", since = "1.0.0")]
1355     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
1356         unsafe { mem::transmute(s.as_ref()) }
1357     }
1358
1359     /// Yields the underlying `OsStr` slice.
1360     ///
1361     /// # Examples
1362     ///
1363     /// ```
1364     /// use std::path::Path;
1365     ///
1366     /// let os_str = Path::new("foo.txt").as_os_str();
1367     /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
1368     /// ```
1369     #[stable(feature = "rust1", since = "1.0.0")]
1370     pub fn as_os_str(&self) -> &OsStr {
1371         &self.inner
1372     }
1373
1374     /// Yields a `&str` slice if the `Path` is valid unicode.
1375     ///
1376     /// This conversion may entail doing a check for UTF-8 validity.
1377     ///
1378     /// # Examples
1379     ///
1380     /// ```
1381     /// use std::path::Path;
1382     ///
1383     /// let path_str = Path::new("foo.txt").to_str();
1384     /// assert_eq!(path_str, Some("foo.txt"));
1385     /// ```
1386     #[stable(feature = "rust1", since = "1.0.0")]
1387     pub fn to_str(&self) -> Option<&str> {
1388         self.inner.to_str()
1389     }
1390
1391     /// Converts a `Path` to a `Cow<str>`.
1392     ///
1393     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
1394     ///
1395     /// # Examples
1396     ///
1397     /// ```
1398     /// use std::path::Path;
1399     ///
1400     /// let path_str = Path::new("foo.txt").to_string_lossy();
1401     /// assert_eq!(path_str, "foo.txt");
1402     /// ```
1403     #[stable(feature = "rust1", since = "1.0.0")]
1404     pub fn to_string_lossy(&self) -> Cow<str> {
1405         self.inner.to_string_lossy()
1406     }
1407
1408     /// Converts a `Path` to an owned `PathBuf`.
1409     ///
1410     /// # Examples
1411     ///
1412     /// ```
1413     /// use std::path::Path;
1414     ///
1415     /// let path_buf = Path::new("foo.txt").to_path_buf();
1416     /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
1417     /// ```
1418     #[stable(feature = "rust1", since = "1.0.0")]
1419     pub fn to_path_buf(&self) -> PathBuf {
1420         PathBuf::from(self.inner.to_os_string())
1421     }
1422
1423     /// A path is *absolute* if it is independent of the current directory.
1424     ///
1425     /// * On Unix, a path is absolute if it starts with the root, so
1426     /// `is_absolute` and `has_root` are equivalent.
1427     ///
1428     /// * On Windows, a path is absolute if it has a prefix and starts with the
1429     /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not. In
1430     /// other words, `path.is_absolute() == path.prefix().is_some() && path.has_root()`.
1431     ///
1432     /// # Examples
1433     ///
1434     /// ```
1435     /// use std::path::Path;
1436     ///
1437     /// assert!(!Path::new("foo.txt").is_absolute());
1438     /// ```
1439     #[stable(feature = "rust1", since = "1.0.0")]
1440     pub fn is_absolute(&self) -> bool {
1441         self.has_root() && (cfg!(unix) || self.prefix().is_some())
1442     }
1443
1444     /// A path is *relative* if it is not absolute.
1445     ///
1446     /// # Examples
1447     ///
1448     /// ```
1449     /// use std::path::Path;
1450     ///
1451     /// assert!(Path::new("foo.txt").is_relative());
1452     /// ```
1453     #[stable(feature = "rust1", since = "1.0.0")]
1454     pub fn is_relative(&self) -> bool {
1455         !self.is_absolute()
1456     }
1457
1458     /// Returns the *prefix* of a path, if any.
1459     ///
1460     /// Prefixes are relevant only for Windows paths, and consist of volumes
1461     /// like `C:`, UNC prefixes like `\\server`, and others described in more
1462     /// detail in `std::os::windows::PathExt`.
1463     #[unstable(feature = "path_prefix",
1464                reason = "uncertain whether to expose this convenience",
1465                issue = "27722")]
1466     pub fn prefix(&self) -> Option<Prefix> {
1467         self.components().prefix
1468     }
1469
1470     /// A path has a root if the body of the path begins with the directory separator.
1471     ///
1472     /// * On Unix, a path has a root if it begins with `/`.
1473     ///
1474     /// * On Windows, a path has a root if it:
1475     ///     * has no prefix and begins with a separator, e.g. `\\windows`
1476     ///     * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows`
1477     ///     * has any non-disk prefix, e.g. `\\server\share`
1478     ///
1479     /// # Examples
1480     ///
1481     /// ```
1482     /// use std::path::Path;
1483     ///
1484     /// assert!(Path::new("/etc/passwd").has_root());
1485     /// ```
1486     #[stable(feature = "rust1", since = "1.0.0")]
1487     pub fn has_root(&self) -> bool {
1488         self.components().has_root()
1489     }
1490
1491     /// The path without its final component, if any.
1492     ///
1493     /// Returns `None` if the path terminates in a root or prefix.
1494     ///
1495     /// # Examples
1496     ///
1497     /// ```
1498     /// use std::path::Path;
1499     ///
1500     /// let path = Path::new("/foo/bar");
1501     /// let parent = path.parent().unwrap();
1502     /// assert_eq!(parent, Path::new("/foo"));
1503     ///
1504     /// let grand_parent = parent.parent().unwrap();
1505     /// assert_eq!(grand_parent, Path::new("/"));
1506     /// assert_eq!(grand_parent.parent(), None);
1507     /// ```
1508     #[stable(feature = "rust1", since = "1.0.0")]
1509     pub fn parent(&self) -> Option<&Path> {
1510         let mut comps = self.components();
1511         let comp = comps.next_back();
1512         comp.and_then(|p| {
1513             match p {
1514                 Component::Normal(_) |
1515                 Component::CurDir |
1516                 Component::ParentDir => Some(comps.as_path()),
1517                 _ => None,
1518             }
1519         })
1520     }
1521
1522     /// The final component of the path, if it is a normal file.
1523     ///
1524     /// If the path terminates in `.`, `..`, or consists solely of a root of
1525     /// prefix, `file_name` will return `None`.
1526     ///
1527     /// # Examples
1528     ///
1529     /// ```
1530     /// use std::path::Path;
1531     /// use std::ffi::OsStr;
1532     ///
1533     /// let path = Path::new("foo.txt");
1534     /// let os_str = OsStr::new("foo.txt");
1535     ///
1536     /// assert_eq!(Some(os_str), path.file_name());
1537     /// ```
1538     #[stable(feature = "rust1", since = "1.0.0")]
1539     pub fn file_name(&self) -> Option<&OsStr> {
1540         self.components().next_back().and_then(|p| {
1541             match p {
1542                 Component::Normal(p) => Some(p.as_ref()),
1543                 _ => None,
1544             }
1545         })
1546     }
1547
1548     /// Returns a path that, when joined onto `base`, yields `self`.
1549     ///
1550     /// If `base` is not a prefix of `self` (i.e. `starts_with`
1551     /// returns false), then `relative_from` returns `None`.
1552     #[unstable(feature = "path_relative_from", reason = "see #23284",
1553                issue = "23284")]
1554     pub fn relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path> {
1555         self._relative_from(base.as_ref())
1556     }
1557
1558     fn _relative_from<'a>(&'a self, base: &'a Path) -> Option<&'a Path> {
1559         iter_after(self.components(), base.components()).map(|c| c.as_path())
1560     }
1561
1562     /// Determines whether `base` is a prefix of `self`.
1563     ///
1564     /// Only considers whole path components to match.
1565     ///
1566     /// # Examples
1567     ///
1568     /// ```
1569     /// use std::path::Path;
1570     ///
1571     /// let path = Path::new("/etc/passwd");
1572     ///
1573     /// assert!(path.starts_with("/etc"));
1574     ///
1575     /// assert!(!path.starts_with("/e"));
1576     /// ```
1577     #[stable(feature = "rust1", since = "1.0.0")]
1578     pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
1579         self._starts_with(base.as_ref())
1580     }
1581
1582     fn _starts_with(&self, base: &Path) -> bool {
1583         iter_after(self.components(), base.components()).is_some()
1584     }
1585
1586     /// Determines whether `child` is a suffix of `self`.
1587     ///
1588     /// Only considers whole path components to match.
1589     ///
1590     /// # Examples
1591     ///
1592     /// ```
1593     /// use std::path::Path;
1594     ///
1595     /// let path = Path::new("/etc/passwd");
1596     ///
1597     /// assert!(path.ends_with("passwd"));
1598     /// ```
1599     #[stable(feature = "rust1", since = "1.0.0")]
1600     pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
1601         self._ends_with(child.as_ref())
1602     }
1603
1604     fn _ends_with(&self, child: &Path) -> bool {
1605         iter_after(self.components().rev(), child.components().rev()).is_some()
1606     }
1607
1608     /// Extracts the stem (non-extension) portion of `self.file_name()`.
1609     ///
1610     /// The stem is:
1611     ///
1612     /// * None, if there is no file name;
1613     /// * The entire file name if there is no embedded `.`;
1614     /// * The entire file name if the file name begins with `.` and has no other `.`s within;
1615     /// * Otherwise, the portion of the file name before the final `.`
1616     ///
1617     /// # Examples
1618     ///
1619     /// ```
1620     /// use std::path::Path;
1621     ///
1622     /// let path = Path::new("foo.rs");
1623     ///
1624     /// assert_eq!("foo", path.file_stem().unwrap());
1625     /// ```
1626     #[stable(feature = "rust1", since = "1.0.0")]
1627     pub fn file_stem(&self) -> Option<&OsStr> {
1628         self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
1629     }
1630
1631     /// Extracts the extension of `self.file_name()`, if possible.
1632     ///
1633     /// The extension is:
1634     ///
1635     /// * None, if there is no file name;
1636     /// * None, if there is no embedded `.`;
1637     /// * None, if the file name begins with `.` and has no other `.`s within;
1638     /// * Otherwise, the portion of the file name after the final `.`
1639     ///
1640     /// # Examples
1641     ///
1642     /// ```
1643     /// use std::path::Path;
1644     ///
1645     /// let path = Path::new("foo.rs");
1646     ///
1647     /// assert_eq!("rs", path.extension().unwrap());
1648     /// ```
1649     #[stable(feature = "rust1", since = "1.0.0")]
1650     pub fn extension(&self) -> Option<&OsStr> {
1651         self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
1652     }
1653
1654     /// Creates an owned `PathBuf` with `path` adjoined to `self`.
1655     ///
1656     /// See `PathBuf::push` for more details on what it means to adjoin a path.
1657     ///
1658     /// # Examples
1659     ///
1660     /// ```
1661     /// use std::path::{Path, PathBuf};
1662     ///
1663     /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
1664     /// ```
1665     #[stable(feature = "rust1", since = "1.0.0")]
1666     pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
1667         self._join(path.as_ref())
1668     }
1669
1670     fn _join(&self, path: &Path) -> PathBuf {
1671         let mut buf = self.to_path_buf();
1672         buf.push(path);
1673         buf
1674     }
1675
1676     /// Creates an owned `PathBuf` like `self` but with the given file name.
1677     ///
1678     /// See `PathBuf::set_file_name` for more details.
1679     ///
1680     /// # Examples
1681     ///
1682     /// ```
1683     /// use std::path::{Path, PathBuf};
1684     ///
1685     /// let path = Path::new("/tmp/foo.txt");
1686     /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
1687     /// ```
1688     #[stable(feature = "rust1", since = "1.0.0")]
1689     pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
1690         self._with_file_name(file_name.as_ref())
1691     }
1692
1693     fn _with_file_name(&self, file_name: &OsStr) -> PathBuf {
1694         let mut buf = self.to_path_buf();
1695         buf.set_file_name(file_name);
1696         buf
1697     }
1698
1699     /// Creates an owned `PathBuf` like `self` but with the given extension.
1700     ///
1701     /// See `PathBuf::set_extension` for more details.
1702     ///
1703     /// # Examples
1704     ///
1705     /// ```
1706     /// use std::path::{Path, PathBuf};
1707     ///
1708     /// let path = Path::new("foo.rs");
1709     /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
1710     /// ```
1711     #[stable(feature = "rust1", since = "1.0.0")]
1712     pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
1713         self._with_extension(extension.as_ref())
1714     }
1715
1716     fn _with_extension(&self, extension: &OsStr) -> PathBuf {
1717         let mut buf = self.to_path_buf();
1718         buf.set_extension(extension);
1719         buf
1720     }
1721
1722     /// Produce an iterator over the components of the path.
1723     ///
1724     /// # Examples
1725     ///
1726     /// ```
1727     /// use std::path::{Path, Component};
1728     /// use std::ffi::OsStr;
1729     ///
1730     /// let mut components = Path::new("/tmp/foo.txt").components();
1731     ///
1732     /// assert_eq!(components.next(), Some(Component::RootDir));
1733     /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
1734     /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
1735     /// assert_eq!(components.next(), None)
1736     /// ```
1737     #[stable(feature = "rust1", since = "1.0.0")]
1738     pub fn components(&self) -> Components {
1739         let prefix = parse_prefix(self.as_os_str());
1740         Components {
1741             path: self.as_u8_slice(),
1742             prefix: prefix,
1743             has_physical_root: has_physical_root(self.as_u8_slice(), prefix),
1744             front: State::Prefix,
1745             back: State::Body,
1746         }
1747     }
1748
1749     /// Produce an iterator over the path's components viewed as `OsStr` slices.
1750     ///
1751     /// # Examples
1752     ///
1753     /// ```
1754     /// use std::path::{self, Path};
1755     /// use std::ffi::OsStr;
1756     ///
1757     /// let mut it = Path::new("/tmp/foo.txt").iter();
1758     /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
1759     /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
1760     /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
1761     /// assert_eq!(it.next(), None)
1762     /// ```
1763     #[stable(feature = "rust1", since = "1.0.0")]
1764     pub fn iter(&self) -> Iter {
1765         Iter { inner: self.components() }
1766     }
1767
1768     /// Returns an object that implements `Display` for safely printing paths
1769     /// that may contain non-Unicode data.
1770     ///
1771     /// # Examples
1772     ///
1773     /// ```
1774     /// use std::path::Path;
1775     ///
1776     /// let path = Path::new("/tmp/foo.rs");
1777     ///
1778     /// println!("{}", path.display());
1779     /// ```
1780     #[stable(feature = "rust1", since = "1.0.0")]
1781     pub fn display(&self) -> Display {
1782         Display { path: self }
1783     }
1784
1785
1786     /// Gets information on the file, directory, etc at this path.
1787     ///
1788     /// Consult the `fs::metadata` documentation for more info.
1789     ///
1790     /// This call preserves identical runtime/error semantics with
1791     /// `fs::metadata`.
1792     #[stable(feature = "path_ext", since = "1.5.0")]
1793     pub fn metadata(&self) -> io::Result<fs::Metadata> {
1794         fs::metadata(self)
1795     }
1796
1797     /// Gets information on the file, directory, etc at this path.
1798     ///
1799     /// Consult the `fs::symlink_metadata` documentation for more info.
1800     ///
1801     /// This call preserves identical runtime/error semantics with
1802     /// `fs::symlink_metadata`.
1803     #[stable(feature = "path_ext", since = "1.5.0")]
1804     pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
1805         fs::symlink_metadata(self)
1806     }
1807
1808     /// Returns the canonical form of a path, normalizing all components and
1809     /// eliminate all symlinks.
1810     ///
1811     /// This call preserves identical runtime/error semantics with
1812     /// `fs::canonicalize`.
1813     #[stable(feature = "path_ext", since = "1.5.0")]
1814     pub fn canonicalize(&self) -> io::Result<PathBuf> {
1815         fs::canonicalize(self)
1816     }
1817
1818     /// Reads the symlink at this path.
1819     ///
1820     /// For more information see `fs::read_link`.
1821     #[stable(feature = "path_ext", since = "1.5.0")]
1822     pub fn read_link(&self) -> io::Result<PathBuf> {
1823         fs::read_link(self)
1824     }
1825
1826     /// Reads the directory at this path.
1827     ///
1828     /// For more information see `fs::read_dir`.
1829     #[stable(feature = "path_ext", since = "1.5.0")]
1830     pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
1831         fs::read_dir(self)
1832     }
1833
1834     /// Boolean value indicator whether the underlying file exists on the local
1835     /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
1836     #[stable(feature = "path_ext", since = "1.5.0")]
1837     pub fn exists(&self) -> bool {
1838         fs::metadata(self).is_ok()
1839     }
1840
1841     /// Whether the underlying implementation (be it a file path, or something
1842     /// else) points at a "regular file" on the FS. Will return false for paths
1843     /// to non-existent locations or directories or other non-regular files
1844     /// (named pipes, etc). Follows links when making this determination.
1845     #[stable(feature = "path_ext", since = "1.5.0")]
1846     pub fn is_file(&self) -> bool {
1847         fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
1848     }
1849
1850     /// Whether the underlying implementation (be it a file path, or something
1851     /// else) is pointing at a directory in the underlying FS. Will return
1852     /// false for paths to non-existent locations or if the item is not a
1853     /// directory (eg files, named pipes, etc). Follows links when making this
1854     /// determination.
1855     #[stable(feature = "path_ext", since = "1.5.0")]
1856     pub fn is_dir(&self) -> bool {
1857         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
1858     }
1859 }
1860
1861 #[stable(feature = "rust1", since = "1.0.0")]
1862 impl AsRef<OsStr> for Path {
1863     fn as_ref(&self) -> &OsStr {
1864         &self.inner
1865     }
1866 }
1867
1868 #[stable(feature = "rust1", since = "1.0.0")]
1869 impl fmt::Debug for Path {
1870     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1871         self.inner.fmt(formatter)
1872     }
1873 }
1874
1875 /// Helper struct for safely printing paths with `format!()` and `{}`
1876 #[stable(feature = "rust1", since = "1.0.0")]
1877 pub struct Display<'a> {
1878     path: &'a Path,
1879 }
1880
1881 #[stable(feature = "rust1", since = "1.0.0")]
1882 impl<'a> fmt::Debug for Display<'a> {
1883     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1884         fmt::Debug::fmt(&self.path.to_string_lossy(), f)
1885     }
1886 }
1887
1888 #[stable(feature = "rust1", since = "1.0.0")]
1889 impl<'a> fmt::Display for Display<'a> {
1890     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1891         fmt::Display::fmt(&self.path.to_string_lossy(), f)
1892     }
1893 }
1894
1895 #[stable(feature = "rust1", since = "1.0.0")]
1896 impl cmp::PartialEq for Path {
1897     fn eq(&self, other: &Path) -> bool {
1898         self.components().eq(other.components())
1899     }
1900 }
1901
1902 #[stable(feature = "rust1", since = "1.0.0")]
1903 impl Hash for Path {
1904     fn hash<H: Hasher>(&self, h: &mut H) {
1905         for component in self.components() {
1906             component.hash(h);
1907         }
1908     }
1909 }
1910
1911 #[stable(feature = "rust1", since = "1.0.0")]
1912 impl cmp::Eq for Path {}
1913
1914 #[stable(feature = "rust1", since = "1.0.0")]
1915 impl cmp::PartialOrd for Path {
1916     fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
1917         self.components().partial_cmp(other.components())
1918     }
1919 }
1920
1921 #[stable(feature = "rust1", since = "1.0.0")]
1922 impl cmp::Ord for Path {
1923     fn cmp(&self, other: &Path) -> cmp::Ordering {
1924         self.components().cmp(other.components())
1925     }
1926 }
1927
1928 #[stable(feature = "rust1", since = "1.0.0")]
1929 impl AsRef<Path> for Path {
1930     fn as_ref(&self) -> &Path {
1931         self
1932     }
1933 }
1934
1935 #[stable(feature = "rust1", since = "1.0.0")]
1936 impl AsRef<Path> for OsStr {
1937     fn as_ref(&self) -> &Path {
1938         Path::new(self)
1939     }
1940 }
1941
1942 #[stable(feature = "rust1", since = "1.0.0")]
1943 impl AsRef<Path> for OsString {
1944     fn as_ref(&self) -> &Path {
1945         Path::new(self)
1946     }
1947 }
1948
1949 #[stable(feature = "rust1", since = "1.0.0")]
1950 impl AsRef<Path> for str {
1951     fn as_ref(&self) -> &Path {
1952         Path::new(self)
1953     }
1954 }
1955
1956 #[stable(feature = "rust1", since = "1.0.0")]
1957 impl AsRef<Path> for String {
1958     fn as_ref(&self) -> &Path {
1959         Path::new(self)
1960     }
1961 }
1962
1963 #[stable(feature = "rust1", since = "1.0.0")]
1964 impl AsRef<Path> for PathBuf {
1965     fn as_ref(&self) -> &Path {
1966         self
1967     }
1968 }
1969
1970 #[stable(feature = "path_into_iter", since = "1.6.0")]
1971 impl<'a> IntoIterator for &'a PathBuf {
1972     type Item = &'a OsStr;
1973     type IntoIter = Iter<'a>;
1974     fn into_iter(self) -> Iter<'a> { self.iter() }
1975 }
1976
1977 #[stable(feature = "path_into_iter", since = "1.6.0")]
1978 impl<'a> IntoIterator for &'a Path {
1979     type Item = &'a OsStr;
1980     type IntoIter = Iter<'a>;
1981     fn into_iter(self) -> Iter<'a> { self.iter() }
1982 }
1983
1984 macro_rules! impl_eq {
1985     ($lhs:ty, $rhs: ty) => {
1986         #[stable(feature = "partialeq_path", since = "1.6.0")]
1987         impl<'a, 'b> PartialEq<$rhs> for $lhs {
1988             #[inline]
1989             fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other) }
1990         }
1991
1992         #[stable(feature = "partialeq_path", since = "1.6.0")]
1993         impl<'a, 'b> PartialEq<$lhs> for $rhs {
1994             #[inline]
1995             fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) }
1996         }
1997
1998     }
1999 }
2000
2001 impl_eq!(PathBuf, Path);
2002 impl_eq!(PathBuf, &'a Path);
2003 impl_eq!(Cow<'a, Path>, Path);
2004 impl_eq!(Cow<'a, Path>, &'b Path);
2005 impl_eq!(Cow<'a, Path>, PathBuf);
2006
2007 #[cfg(test)]
2008 mod tests {
2009     use super::*;
2010     use string::{ToString, String};
2011     use vec::Vec;
2012
2013     macro_rules! t(
2014         ($path:expr, iter: $iter:expr) => (
2015             {
2016                 let path = Path::new($path);
2017
2018                 // Forward iteration
2019                 let comps = path.iter()
2020                     .map(|p| p.to_string_lossy().into_owned())
2021                     .collect::<Vec<String>>();
2022                 let exp: &[&str] = &$iter;
2023                 let exps = exp.iter().map(|s| s.to_string()).collect::<Vec<String>>();
2024                 assert!(comps == exps, "iter: Expected {:?}, found {:?}",
2025                         exps, comps);
2026
2027                 // Reverse iteration
2028                 let comps = Path::new($path).iter().rev()
2029                     .map(|p| p.to_string_lossy().into_owned())
2030                     .collect::<Vec<String>>();
2031                 let exps = exps.into_iter().rev().collect::<Vec<String>>();
2032                 assert!(comps == exps, "iter().rev(): Expected {:?}, found {:?}",
2033                         exps, comps);
2034             }
2035         );
2036
2037         ($path:expr, has_root: $has_root:expr, is_absolute: $is_absolute:expr) => (
2038             {
2039                 let path = Path::new($path);
2040
2041                 let act_root = path.has_root();
2042                 assert!(act_root == $has_root, "has_root: Expected {:?}, found {:?}",
2043                         $has_root, act_root);
2044
2045                 let act_abs = path.is_absolute();
2046                 assert!(act_abs == $is_absolute, "is_absolute: Expected {:?}, found {:?}",
2047                         $is_absolute, act_abs);
2048             }
2049         );
2050
2051         ($path:expr, parent: $parent:expr, file_name: $file:expr) => (
2052             {
2053                 let path = Path::new($path);
2054
2055                 let parent = path.parent().map(|p| p.to_str().unwrap());
2056                 let exp_parent: Option<&str> = $parent;
2057                 assert!(parent == exp_parent, "parent: Expected {:?}, found {:?}",
2058                         exp_parent, parent);
2059
2060                 let file = path.file_name().map(|p| p.to_str().unwrap());
2061                 let exp_file: Option<&str> = $file;
2062                 assert!(file == exp_file, "file_name: Expected {:?}, found {:?}",
2063                         exp_file, file);
2064             }
2065         );
2066
2067         ($path:expr, file_stem: $file_stem:expr, extension: $extension:expr) => (
2068             {
2069                 let path = Path::new($path);
2070
2071                 let stem = path.file_stem().map(|p| p.to_str().unwrap());
2072                 let exp_stem: Option<&str> = $file_stem;
2073                 assert!(stem == exp_stem, "file_stem: Expected {:?}, found {:?}",
2074                         exp_stem, stem);
2075
2076                 let ext = path.extension().map(|p| p.to_str().unwrap());
2077                 let exp_ext: Option<&str> = $extension;
2078                 assert!(ext == exp_ext, "extension: Expected {:?}, found {:?}",
2079                         exp_ext, ext);
2080             }
2081         );
2082
2083         ($path:expr, iter: $iter:expr,
2084                      has_root: $has_root:expr, is_absolute: $is_absolute:expr,
2085                      parent: $parent:expr, file_name: $file:expr,
2086                      file_stem: $file_stem:expr, extension: $extension:expr) => (
2087             {
2088                 t!($path, iter: $iter);
2089                 t!($path, has_root: $has_root, is_absolute: $is_absolute);
2090                 t!($path, parent: $parent, file_name: $file);
2091                 t!($path, file_stem: $file_stem, extension: $extension);
2092             }
2093         );
2094     );
2095
2096     #[test]
2097     fn into_cow() {
2098         use borrow::{Cow, IntoCow};
2099
2100         let static_path = Path::new("/home/foo");
2101         let static_cow_path: Cow<'static, Path> = static_path.into_cow();
2102         let pathbuf = PathBuf::from("/home/foo");
2103
2104         {
2105             let path: &Path = &pathbuf;
2106             let borrowed_cow_path: Cow<Path> = path.into_cow();
2107
2108             assert_eq!(static_cow_path, borrowed_cow_path);
2109         }
2110
2111         let owned_cow_path: Cow<'static, Path> = pathbuf.into_cow();
2112
2113         assert_eq!(static_cow_path, owned_cow_path);
2114     }
2115
2116     #[test]
2117     fn into() {
2118         use borrow::Cow;
2119
2120         let static_path = Path::new("/home/foo");
2121         let static_cow_path: Cow<'static, Path> = static_path.into();
2122         let pathbuf = PathBuf::from("/home/foo");
2123
2124         {
2125             let path: &Path = &pathbuf;
2126             let borrowed_cow_path: Cow<Path> = path.into();
2127
2128             assert_eq!(static_cow_path, borrowed_cow_path);
2129         }
2130
2131         let owned_cow_path: Cow<'static, Path> = pathbuf.into();
2132
2133         assert_eq!(static_cow_path, owned_cow_path);
2134     }
2135
2136     #[test]
2137     #[cfg(unix)]
2138     pub fn test_decompositions_unix() {
2139         t!("",
2140            iter: [],
2141            has_root: false,
2142            is_absolute: false,
2143            parent: None,
2144            file_name: None,
2145            file_stem: None,
2146            extension: None
2147            );
2148
2149         t!("foo",
2150            iter: ["foo"],
2151            has_root: false,
2152            is_absolute: false,
2153            parent: Some(""),
2154            file_name: Some("foo"),
2155            file_stem: Some("foo"),
2156            extension: None
2157            );
2158
2159         t!("/",
2160            iter: ["/"],
2161            has_root: true,
2162            is_absolute: true,
2163            parent: None,
2164            file_name: None,
2165            file_stem: None,
2166            extension: None
2167            );
2168
2169         t!("/foo",
2170            iter: ["/", "foo"],
2171            has_root: true,
2172            is_absolute: true,
2173            parent: Some("/"),
2174            file_name: Some("foo"),
2175            file_stem: Some("foo"),
2176            extension: None
2177            );
2178
2179         t!("foo/",
2180            iter: ["foo"],
2181            has_root: false,
2182            is_absolute: false,
2183            parent: Some(""),
2184            file_name: Some("foo"),
2185            file_stem: Some("foo"),
2186            extension: None
2187            );
2188
2189         t!("/foo/",
2190            iter: ["/", "foo"],
2191            has_root: true,
2192            is_absolute: true,
2193            parent: Some("/"),
2194            file_name: Some("foo"),
2195            file_stem: Some("foo"),
2196            extension: None
2197            );
2198
2199         t!("foo/bar",
2200            iter: ["foo", "bar"],
2201            has_root: false,
2202            is_absolute: false,
2203            parent: Some("foo"),
2204            file_name: Some("bar"),
2205            file_stem: Some("bar"),
2206            extension: None
2207            );
2208
2209         t!("/foo/bar",
2210            iter: ["/", "foo", "bar"],
2211            has_root: true,
2212            is_absolute: true,
2213            parent: Some("/foo"),
2214            file_name: Some("bar"),
2215            file_stem: Some("bar"),
2216            extension: None
2217            );
2218
2219         t!("///foo///",
2220            iter: ["/", "foo"],
2221            has_root: true,
2222            is_absolute: true,
2223            parent: Some("/"),
2224            file_name: Some("foo"),
2225            file_stem: Some("foo"),
2226            extension: None
2227            );
2228
2229         t!("///foo///bar",
2230            iter: ["/", "foo", "bar"],
2231            has_root: true,
2232            is_absolute: true,
2233            parent: Some("///foo"),
2234            file_name: Some("bar"),
2235            file_stem: Some("bar"),
2236            extension: None
2237            );
2238
2239         t!("./.",
2240            iter: ["."],
2241            has_root: false,
2242            is_absolute: false,
2243            parent: Some(""),
2244            file_name: None,
2245            file_stem: None,
2246            extension: None
2247            );
2248
2249         t!("/..",
2250            iter: ["/", ".."],
2251            has_root: true,
2252            is_absolute: true,
2253            parent: Some("/"),
2254            file_name: None,
2255            file_stem: None,
2256            extension: None
2257            );
2258
2259         t!("../",
2260            iter: [".."],
2261            has_root: false,
2262            is_absolute: false,
2263            parent: Some(""),
2264            file_name: None,
2265            file_stem: None,
2266            extension: None
2267            );
2268
2269         t!("foo/.",
2270            iter: ["foo"],
2271            has_root: false,
2272            is_absolute: false,
2273            parent: Some(""),
2274            file_name: Some("foo"),
2275            file_stem: Some("foo"),
2276            extension: None
2277            );
2278
2279         t!("foo/..",
2280            iter: ["foo", ".."],
2281            has_root: false,
2282            is_absolute: false,
2283            parent: Some("foo"),
2284            file_name: None,
2285            file_stem: None,
2286            extension: None
2287            );
2288
2289         t!("foo/./",
2290            iter: ["foo"],
2291            has_root: false,
2292            is_absolute: false,
2293            parent: Some(""),
2294            file_name: Some("foo"),
2295            file_stem: Some("foo"),
2296            extension: None
2297            );
2298
2299         t!("foo/./bar",
2300            iter: ["foo", "bar"],
2301            has_root: false,
2302            is_absolute: false,
2303            parent: Some("foo"),
2304            file_name: Some("bar"),
2305            file_stem: Some("bar"),
2306            extension: None
2307            );
2308
2309         t!("foo/../",
2310            iter: ["foo", ".."],
2311            has_root: false,
2312            is_absolute: false,
2313            parent: Some("foo"),
2314            file_name: None,
2315            file_stem: None,
2316            extension: None
2317            );
2318
2319         t!("foo/../bar",
2320            iter: ["foo", "..", "bar"],
2321            has_root: false,
2322            is_absolute: false,
2323            parent: Some("foo/.."),
2324            file_name: Some("bar"),
2325            file_stem: Some("bar"),
2326            extension: None
2327            );
2328
2329         t!("./a",
2330            iter: [".", "a"],
2331            has_root: false,
2332            is_absolute: false,
2333            parent: Some("."),
2334            file_name: Some("a"),
2335            file_stem: Some("a"),
2336            extension: None
2337            );
2338
2339         t!(".",
2340            iter: ["."],
2341            has_root: false,
2342            is_absolute: false,
2343            parent: Some(""),
2344            file_name: None,
2345            file_stem: None,
2346            extension: None
2347            );
2348
2349         t!("./",
2350            iter: ["."],
2351            has_root: false,
2352            is_absolute: false,
2353            parent: Some(""),
2354            file_name: None,
2355            file_stem: None,
2356            extension: None
2357            );
2358
2359         t!("a/b",
2360            iter: ["a", "b"],
2361            has_root: false,
2362            is_absolute: false,
2363            parent: Some("a"),
2364            file_name: Some("b"),
2365            file_stem: Some("b"),
2366            extension: None
2367            );
2368
2369         t!("a//b",
2370            iter: ["a", "b"],
2371            has_root: false,
2372            is_absolute: false,
2373            parent: Some("a"),
2374            file_name: Some("b"),
2375            file_stem: Some("b"),
2376            extension: None
2377            );
2378
2379         t!("a/./b",
2380            iter: ["a", "b"],
2381            has_root: false,
2382            is_absolute: false,
2383            parent: Some("a"),
2384            file_name: Some("b"),
2385            file_stem: Some("b"),
2386            extension: None
2387            );
2388
2389         t!("a/b/c",
2390            iter: ["a", "b", "c"],
2391            has_root: false,
2392            is_absolute: false,
2393            parent: Some("a/b"),
2394            file_name: Some("c"),
2395            file_stem: Some("c"),
2396            extension: None
2397            );
2398
2399         t!(".foo",
2400            iter: [".foo"],
2401            has_root: false,
2402            is_absolute: false,
2403            parent: Some(""),
2404            file_name: Some(".foo"),
2405            file_stem: Some(".foo"),
2406            extension: None
2407            );
2408     }
2409
2410     #[test]
2411     #[cfg(windows)]
2412     pub fn test_decompositions_windows() {
2413         t!("",
2414            iter: [],
2415            has_root: false,
2416            is_absolute: false,
2417            parent: None,
2418            file_name: None,
2419            file_stem: None,
2420            extension: None
2421            );
2422
2423         t!("foo",
2424            iter: ["foo"],
2425            has_root: false,
2426            is_absolute: false,
2427            parent: Some(""),
2428            file_name: Some("foo"),
2429            file_stem: Some("foo"),
2430            extension: None
2431            );
2432
2433         t!("/",
2434            iter: ["\\"],
2435            has_root: true,
2436            is_absolute: false,
2437            parent: None,
2438            file_name: None,
2439            file_stem: None,
2440            extension: None
2441            );
2442
2443         t!("\\",
2444            iter: ["\\"],
2445            has_root: true,
2446            is_absolute: false,
2447            parent: None,
2448            file_name: None,
2449            file_stem: None,
2450            extension: None
2451            );
2452
2453         t!("c:",
2454            iter: ["c:"],
2455            has_root: false,
2456            is_absolute: false,
2457            parent: None,
2458            file_name: None,
2459            file_stem: None,
2460            extension: None
2461            );
2462
2463         t!("c:\\",
2464            iter: ["c:", "\\"],
2465            has_root: true,
2466            is_absolute: true,
2467            parent: None,
2468            file_name: None,
2469            file_stem: None,
2470            extension: None
2471            );
2472
2473         t!("c:/",
2474            iter: ["c:", "\\"],
2475            has_root: true,
2476            is_absolute: true,
2477            parent: None,
2478            file_name: None,
2479            file_stem: None,
2480            extension: None
2481            );
2482
2483         t!("/foo",
2484            iter: ["\\", "foo"],
2485            has_root: true,
2486            is_absolute: false,
2487            parent: Some("/"),
2488            file_name: Some("foo"),
2489            file_stem: Some("foo"),
2490            extension: None
2491            );
2492
2493         t!("foo/",
2494            iter: ["foo"],
2495            has_root: false,
2496            is_absolute: false,
2497            parent: Some(""),
2498            file_name: Some("foo"),
2499            file_stem: Some("foo"),
2500            extension: None
2501            );
2502
2503         t!("/foo/",
2504            iter: ["\\", "foo"],
2505            has_root: true,
2506            is_absolute: false,
2507            parent: Some("/"),
2508            file_name: Some("foo"),
2509            file_stem: Some("foo"),
2510            extension: None
2511            );
2512
2513         t!("foo/bar",
2514            iter: ["foo", "bar"],
2515            has_root: false,
2516            is_absolute: false,
2517            parent: Some("foo"),
2518            file_name: Some("bar"),
2519            file_stem: Some("bar"),
2520            extension: None
2521            );
2522
2523         t!("/foo/bar",
2524            iter: ["\\", "foo", "bar"],
2525            has_root: true,
2526            is_absolute: false,
2527            parent: Some("/foo"),
2528            file_name: Some("bar"),
2529            file_stem: Some("bar"),
2530            extension: None
2531            );
2532
2533         t!("///foo///",
2534            iter: ["\\", "foo"],
2535            has_root: true,
2536            is_absolute: false,
2537            parent: Some("/"),
2538            file_name: Some("foo"),
2539            file_stem: Some("foo"),
2540            extension: None
2541            );
2542
2543         t!("///foo///bar",
2544            iter: ["\\", "foo", "bar"],
2545            has_root: true,
2546            is_absolute: false,
2547            parent: Some("///foo"),
2548            file_name: Some("bar"),
2549            file_stem: Some("bar"),
2550            extension: None
2551            );
2552
2553         t!("./.",
2554            iter: ["."],
2555            has_root: false,
2556            is_absolute: false,
2557            parent: Some(""),
2558            file_name: None,
2559            file_stem: None,
2560            extension: None
2561            );
2562
2563         t!("/..",
2564            iter: ["\\", ".."],
2565            has_root: true,
2566            is_absolute: false,
2567            parent: Some("/"),
2568            file_name: None,
2569            file_stem: None,
2570            extension: None
2571            );
2572
2573         t!("../",
2574            iter: [".."],
2575            has_root: false,
2576            is_absolute: false,
2577            parent: Some(""),
2578            file_name: None,
2579            file_stem: None,
2580            extension: None
2581            );
2582
2583         t!("foo/.",
2584            iter: ["foo"],
2585            has_root: false,
2586            is_absolute: false,
2587            parent: Some(""),
2588            file_name: Some("foo"),
2589            file_stem: Some("foo"),
2590            extension: None
2591            );
2592
2593         t!("foo/..",
2594            iter: ["foo", ".."],
2595            has_root: false,
2596            is_absolute: false,
2597            parent: Some("foo"),
2598            file_name: None,
2599            file_stem: None,
2600            extension: None
2601            );
2602
2603         t!("foo/./",
2604            iter: ["foo"],
2605            has_root: false,
2606            is_absolute: false,
2607            parent: Some(""),
2608            file_name: Some("foo"),
2609            file_stem: Some("foo"),
2610            extension: None
2611            );
2612
2613         t!("foo/./bar",
2614            iter: ["foo", "bar"],
2615            has_root: false,
2616            is_absolute: false,
2617            parent: Some("foo"),
2618            file_name: Some("bar"),
2619            file_stem: Some("bar"),
2620            extension: None
2621            );
2622
2623         t!("foo/../",
2624            iter: ["foo", ".."],
2625            has_root: false,
2626            is_absolute: false,
2627            parent: Some("foo"),
2628            file_name: None,
2629            file_stem: None,
2630            extension: None
2631            );
2632
2633         t!("foo/../bar",
2634            iter: ["foo", "..", "bar"],
2635            has_root: false,
2636            is_absolute: false,
2637            parent: Some("foo/.."),
2638            file_name: Some("bar"),
2639            file_stem: Some("bar"),
2640            extension: None
2641            );
2642
2643         t!("./a",
2644            iter: [".", "a"],
2645            has_root: false,
2646            is_absolute: false,
2647            parent: Some("."),
2648            file_name: Some("a"),
2649            file_stem: Some("a"),
2650            extension: None
2651            );
2652
2653         t!(".",
2654            iter: ["."],
2655            has_root: false,
2656            is_absolute: false,
2657            parent: Some(""),
2658            file_name: None,
2659            file_stem: None,
2660            extension: None
2661            );
2662
2663         t!("./",
2664            iter: ["."],
2665            has_root: false,
2666            is_absolute: false,
2667            parent: Some(""),
2668            file_name: None,
2669            file_stem: None,
2670            extension: None
2671            );
2672
2673         t!("a/b",
2674            iter: ["a", "b"],
2675            has_root: false,
2676            is_absolute: false,
2677            parent: Some("a"),
2678            file_name: Some("b"),
2679            file_stem: Some("b"),
2680            extension: None
2681            );
2682
2683         t!("a//b",
2684            iter: ["a", "b"],
2685            has_root: false,
2686            is_absolute: false,
2687            parent: Some("a"),
2688            file_name: Some("b"),
2689            file_stem: Some("b"),
2690            extension: None
2691            );
2692
2693         t!("a/./b",
2694            iter: ["a", "b"],
2695            has_root: false,
2696            is_absolute: false,
2697            parent: Some("a"),
2698            file_name: Some("b"),
2699            file_stem: Some("b"),
2700            extension: None
2701            );
2702
2703         t!("a/b/c",
2704            iter: ["a", "b", "c"],
2705            has_root: false,
2706            is_absolute: false,
2707            parent: Some("a/b"),
2708            file_name: Some("c"),
2709            file_stem: Some("c"),
2710            extension: None);
2711
2712         t!("a\\b\\c",
2713            iter: ["a", "b", "c"],
2714            has_root: false,
2715            is_absolute: false,
2716            parent: Some("a\\b"),
2717            file_name: Some("c"),
2718            file_stem: Some("c"),
2719            extension: None
2720            );
2721
2722         t!("\\a",
2723            iter: ["\\", "a"],
2724            has_root: true,
2725            is_absolute: false,
2726            parent: Some("\\"),
2727            file_name: Some("a"),
2728            file_stem: Some("a"),
2729            extension: None
2730            );
2731
2732         t!("c:\\foo.txt",
2733            iter: ["c:", "\\", "foo.txt"],
2734            has_root: true,
2735            is_absolute: true,
2736            parent: Some("c:\\"),
2737            file_name: Some("foo.txt"),
2738            file_stem: Some("foo"),
2739            extension: Some("txt")
2740            );
2741
2742         t!("\\\\server\\share\\foo.txt",
2743            iter: ["\\\\server\\share", "\\", "foo.txt"],
2744            has_root: true,
2745            is_absolute: true,
2746            parent: Some("\\\\server\\share\\"),
2747            file_name: Some("foo.txt"),
2748            file_stem: Some("foo"),
2749            extension: Some("txt")
2750            );
2751
2752         t!("\\\\server\\share",
2753            iter: ["\\\\server\\share", "\\"],
2754            has_root: true,
2755            is_absolute: true,
2756            parent: None,
2757            file_name: None,
2758            file_stem: None,
2759            extension: None
2760            );
2761
2762         t!("\\\\server",
2763            iter: ["\\", "server"],
2764            has_root: true,
2765            is_absolute: false,
2766            parent: Some("\\"),
2767            file_name: Some("server"),
2768            file_stem: Some("server"),
2769            extension: None
2770            );
2771
2772         t!("\\\\?\\bar\\foo.txt",
2773            iter: ["\\\\?\\bar", "\\", "foo.txt"],
2774            has_root: true,
2775            is_absolute: true,
2776            parent: Some("\\\\?\\bar\\"),
2777            file_name: Some("foo.txt"),
2778            file_stem: Some("foo"),
2779            extension: Some("txt")
2780            );
2781
2782         t!("\\\\?\\bar",
2783            iter: ["\\\\?\\bar"],
2784            has_root: true,
2785            is_absolute: true,
2786            parent: None,
2787            file_name: None,
2788            file_stem: None,
2789            extension: None
2790            );
2791
2792         t!("\\\\?\\",
2793            iter: ["\\\\?\\"],
2794            has_root: true,
2795            is_absolute: true,
2796            parent: None,
2797            file_name: None,
2798            file_stem: None,
2799            extension: None
2800            );
2801
2802         t!("\\\\?\\UNC\\server\\share\\foo.txt",
2803            iter: ["\\\\?\\UNC\\server\\share", "\\", "foo.txt"],
2804            has_root: true,
2805            is_absolute: true,
2806            parent: Some("\\\\?\\UNC\\server\\share\\"),
2807            file_name: Some("foo.txt"),
2808            file_stem: Some("foo"),
2809            extension: Some("txt")
2810            );
2811
2812         t!("\\\\?\\UNC\\server",
2813            iter: ["\\\\?\\UNC\\server"],
2814            has_root: true,
2815            is_absolute: true,
2816            parent: None,
2817            file_name: None,
2818            file_stem: None,
2819            extension: None
2820            );
2821
2822         t!("\\\\?\\UNC\\",
2823            iter: ["\\\\?\\UNC\\"],
2824            has_root: true,
2825            is_absolute: true,
2826            parent: None,
2827            file_name: None,
2828            file_stem: None,
2829            extension: None
2830            );
2831
2832         t!("\\\\?\\C:\\foo.txt",
2833            iter: ["\\\\?\\C:", "\\", "foo.txt"],
2834            has_root: true,
2835            is_absolute: true,
2836            parent: Some("\\\\?\\C:\\"),
2837            file_name: Some("foo.txt"),
2838            file_stem: Some("foo"),
2839            extension: Some("txt")
2840            );
2841
2842
2843         t!("\\\\?\\C:\\",
2844            iter: ["\\\\?\\C:", "\\"],
2845            has_root: true,
2846            is_absolute: true,
2847            parent: None,
2848            file_name: None,
2849            file_stem: None,
2850            extension: None
2851            );
2852
2853
2854         t!("\\\\?\\C:",
2855            iter: ["\\\\?\\C:"],
2856            has_root: true,
2857            is_absolute: true,
2858            parent: None,
2859            file_name: None,
2860            file_stem: None,
2861            extension: None
2862            );
2863
2864
2865         t!("\\\\?\\foo/bar",
2866            iter: ["\\\\?\\foo/bar"],
2867            has_root: true,
2868            is_absolute: true,
2869            parent: None,
2870            file_name: None,
2871            file_stem: None,
2872            extension: None
2873            );
2874
2875
2876         t!("\\\\?\\C:/foo",
2877            iter: ["\\\\?\\C:/foo"],
2878            has_root: true,
2879            is_absolute: true,
2880            parent: None,
2881            file_name: None,
2882            file_stem: None,
2883            extension: None
2884            );
2885
2886
2887         t!("\\\\.\\foo\\bar",
2888            iter: ["\\\\.\\foo", "\\", "bar"],
2889            has_root: true,
2890            is_absolute: true,
2891            parent: Some("\\\\.\\foo\\"),
2892            file_name: Some("bar"),
2893            file_stem: Some("bar"),
2894            extension: None
2895            );
2896
2897
2898         t!("\\\\.\\foo",
2899            iter: ["\\\\.\\foo", "\\"],
2900            has_root: true,
2901            is_absolute: true,
2902            parent: None,
2903            file_name: None,
2904            file_stem: None,
2905            extension: None
2906            );
2907
2908
2909         t!("\\\\.\\foo/bar",
2910            iter: ["\\\\.\\foo/bar", "\\"],
2911            has_root: true,
2912            is_absolute: true,
2913            parent: None,
2914            file_name: None,
2915            file_stem: None,
2916            extension: None
2917            );
2918
2919
2920         t!("\\\\.\\foo\\bar/baz",
2921            iter: ["\\\\.\\foo", "\\", "bar", "baz"],
2922            has_root: true,
2923            is_absolute: true,
2924            parent: Some("\\\\.\\foo\\bar"),
2925            file_name: Some("baz"),
2926            file_stem: Some("baz"),
2927            extension: None
2928            );
2929
2930
2931         t!("\\\\.\\",
2932            iter: ["\\\\.\\", "\\"],
2933            has_root: true,
2934            is_absolute: true,
2935            parent: None,
2936            file_name: None,
2937            file_stem: None,
2938            extension: None
2939            );
2940
2941         t!("\\\\?\\a\\b\\",
2942            iter: ["\\\\?\\a", "\\", "b"],
2943            has_root: true,
2944            is_absolute: true,
2945            parent: Some("\\\\?\\a\\"),
2946            file_name: Some("b"),
2947            file_stem: Some("b"),
2948            extension: None
2949            );
2950     }
2951
2952     #[test]
2953     pub fn test_stem_ext() {
2954         t!("foo",
2955            file_stem: Some("foo"),
2956            extension: None
2957            );
2958
2959         t!("foo.",
2960            file_stem: Some("foo"),
2961            extension: Some("")
2962            );
2963
2964         t!(".foo",
2965            file_stem: Some(".foo"),
2966            extension: None
2967            );
2968
2969         t!("foo.txt",
2970            file_stem: Some("foo"),
2971            extension: Some("txt")
2972            );
2973
2974         t!("foo.bar.txt",
2975            file_stem: Some("foo.bar"),
2976            extension: Some("txt")
2977            );
2978
2979         t!("foo.bar.",
2980            file_stem: Some("foo.bar"),
2981            extension: Some("")
2982            );
2983
2984         t!(".",
2985            file_stem: None,
2986            extension: None
2987            );
2988
2989         t!("..",
2990            file_stem: None,
2991            extension: None
2992            );
2993
2994         t!("",
2995            file_stem: None,
2996            extension: None
2997            );
2998     }
2999
3000     #[test]
3001     pub fn test_push() {
3002         macro_rules! tp(
3003             ($path:expr, $push:expr, $expected:expr) => ( {
3004                 let mut actual = PathBuf::from($path);
3005                 actual.push($push);
3006                 assert!(actual.to_str() == Some($expected),
3007                         "pushing {:?} onto {:?}: Expected {:?}, got {:?}",
3008                         $push, $path, $expected, actual.to_str().unwrap());
3009             });
3010         );
3011
3012         if cfg!(unix) {
3013             tp!("", "foo", "foo");
3014             tp!("foo", "bar", "foo/bar");
3015             tp!("foo/", "bar", "foo/bar");
3016             tp!("foo//", "bar", "foo//bar");
3017             tp!("foo/.", "bar", "foo/./bar");
3018             tp!("foo./.", "bar", "foo././bar");
3019             tp!("foo", "", "foo/");
3020             tp!("foo", ".", "foo/.");
3021             tp!("foo", "..", "foo/..");
3022             tp!("foo", "/", "/");
3023             tp!("/foo/bar", "/", "/");
3024             tp!("/foo/bar", "/baz", "/baz");
3025             tp!("/foo/bar", "./baz", "/foo/bar/./baz");
3026         } else {
3027             tp!("", "foo", "foo");
3028             tp!("foo", "bar", r"foo\bar");
3029             tp!("foo/", "bar", r"foo/bar");
3030             tp!(r"foo\", "bar", r"foo\bar");
3031             tp!("foo//", "bar", r"foo//bar");
3032             tp!(r"foo\\", "bar", r"foo\\bar");
3033             tp!("foo/.", "bar", r"foo/.\bar");
3034             tp!("foo./.", "bar", r"foo./.\bar");
3035             tp!(r"foo\.", "bar", r"foo\.\bar");
3036             tp!(r"foo.\.", "bar", r"foo.\.\bar");
3037             tp!("foo", "", "foo\\");
3038             tp!("foo", ".", r"foo\.");
3039             tp!("foo", "..", r"foo\..");
3040             tp!("foo", "/", "/");
3041             tp!("foo", r"\", r"\");
3042             tp!("/foo/bar", "/", "/");
3043             tp!(r"\foo\bar", r"\", r"\");
3044             tp!("/foo/bar", "/baz", "/baz");
3045             tp!("/foo/bar", r"\baz", r"\baz");
3046             tp!("/foo/bar", "./baz", r"/foo/bar\./baz");
3047             tp!("/foo/bar", r".\baz", r"/foo/bar\.\baz");
3048
3049             tp!("c:\\", "windows", "c:\\windows");
3050             tp!("c:", "windows", "c:windows");
3051
3052             tp!("a\\b\\c", "d", "a\\b\\c\\d");
3053             tp!("\\a\\b\\c", "d", "\\a\\b\\c\\d");
3054             tp!("a\\b", "c\\d", "a\\b\\c\\d");
3055             tp!("a\\b", "\\c\\d", "\\c\\d");
3056             tp!("a\\b", ".", "a\\b\\.");
3057             tp!("a\\b", "..\\c", "a\\b\\..\\c");
3058             tp!("a\\b", "C:a.txt", "C:a.txt");
3059             tp!("a\\b", "C:\\a.txt", "C:\\a.txt");
3060             tp!("C:\\a", "C:\\b.txt", "C:\\b.txt");
3061             tp!("C:\\a\\b\\c", "C:d", "C:d");
3062             tp!("C:a\\b\\c", "C:d", "C:d");
3063             tp!("C:", r"a\b\c", r"C:a\b\c");
3064             tp!("C:", r"..\a", r"C:..\a");
3065             tp!("\\\\server\\share\\foo",
3066                 "bar",
3067                 "\\\\server\\share\\foo\\bar");
3068             tp!("\\\\server\\share\\foo", "C:baz", "C:baz");
3069             tp!("\\\\?\\C:\\a\\b", "C:c\\d", "C:c\\d");
3070             tp!("\\\\?\\C:a\\b", "C:c\\d", "C:c\\d");
3071             tp!("\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d");
3072             tp!("\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz");
3073             tp!("\\\\?\\UNC\\server\\share\\foo",
3074                 "bar",
3075                 "\\\\?\\UNC\\server\\share\\foo\\bar");
3076             tp!("\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a");
3077             tp!("\\\\?\\UNC\\server\\share", "C:a", "C:a");
3078
3079             // Note: modified from old path API
3080             tp!("\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\foo");
3081
3082             tp!("C:\\a",
3083                 "\\\\?\\UNC\\server\\share",
3084                 "\\\\?\\UNC\\server\\share");
3085             tp!("\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz");
3086             tp!("\\\\.\\foo\\bar", "C:a", "C:a");
3087             // again, not sure about the following, but I'm assuming \\.\ should be verbatim
3088             tp!("\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar");
3089
3090             tp!("\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
3091         }
3092     }
3093
3094     #[test]
3095     pub fn test_pop() {
3096         macro_rules! tp(
3097             ($path:expr, $expected:expr, $output:expr) => ( {
3098                 let mut actual = PathBuf::from($path);
3099                 let output = actual.pop();
3100                 assert!(actual.to_str() == Some($expected) && output == $output,
3101                         "popping from {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
3102                         $path, $expected, $output,
3103                         actual.to_str().unwrap(), output);
3104             });
3105         );
3106
3107         tp!("", "", false);
3108         tp!("/", "/", false);
3109         tp!("foo", "", true);
3110         tp!(".", "", true);
3111         tp!("/foo", "/", true);
3112         tp!("/foo/bar", "/foo", true);
3113         tp!("foo/bar", "foo", true);
3114         tp!("foo/.", "", true);
3115         tp!("foo//bar", "foo", true);
3116
3117         if cfg!(windows) {
3118             tp!("a\\b\\c", "a\\b", true);
3119             tp!("\\a", "\\", true);
3120             tp!("\\", "\\", false);
3121
3122             tp!("C:\\a\\b", "C:\\a", true);
3123             tp!("C:\\a", "C:\\", true);
3124             tp!("C:\\", "C:\\", false);
3125             tp!("C:a\\b", "C:a", true);
3126             tp!("C:a", "C:", true);
3127             tp!("C:", "C:", false);
3128             tp!("\\\\server\\share\\a\\b", "\\\\server\\share\\a", true);
3129             tp!("\\\\server\\share\\a", "\\\\server\\share\\", true);
3130             tp!("\\\\server\\share", "\\\\server\\share", false);
3131             tp!("\\\\?\\a\\b\\c", "\\\\?\\a\\b", true);
3132             tp!("\\\\?\\a\\b", "\\\\?\\a\\", true);
3133             tp!("\\\\?\\a", "\\\\?\\a", false);
3134             tp!("\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true);
3135             tp!("\\\\?\\C:\\a", "\\\\?\\C:\\", true);
3136             tp!("\\\\?\\C:\\", "\\\\?\\C:\\", false);
3137             tp!("\\\\?\\UNC\\server\\share\\a\\b",
3138                 "\\\\?\\UNC\\server\\share\\a",
3139                 true);
3140             tp!("\\\\?\\UNC\\server\\share\\a",
3141                 "\\\\?\\UNC\\server\\share\\",
3142                 true);
3143             tp!("\\\\?\\UNC\\server\\share",
3144                 "\\\\?\\UNC\\server\\share",
3145                 false);
3146             tp!("\\\\.\\a\\b\\c", "\\\\.\\a\\b", true);
3147             tp!("\\\\.\\a\\b", "\\\\.\\a\\", true);
3148             tp!("\\\\.\\a", "\\\\.\\a", false);
3149
3150             tp!("\\\\?\\a\\b\\", "\\\\?\\a\\", true);
3151         }
3152     }
3153
3154     #[test]
3155     pub fn test_set_file_name() {
3156         macro_rules! tfn(
3157                 ($path:expr, $file:expr, $expected:expr) => ( {
3158                 let mut p = PathBuf::from($path);
3159                 p.set_file_name($file);
3160                 assert!(p.to_str() == Some($expected),
3161                         "setting file name of {:?} to {:?}: Expected {:?}, got {:?}",
3162                         $path, $file, $expected,
3163                         p.to_str().unwrap());
3164             });
3165         );
3166
3167         tfn!("foo", "foo", "foo");
3168         tfn!("foo", "bar", "bar");
3169         tfn!("foo", "", "");
3170         tfn!("", "foo", "foo");
3171         if cfg!(unix) {
3172             tfn!(".", "foo", "./foo");
3173             tfn!("foo/", "bar", "bar");
3174             tfn!("foo/.", "bar", "bar");
3175             tfn!("..", "foo", "../foo");
3176             tfn!("foo/..", "bar", "foo/../bar");
3177             tfn!("/", "foo", "/foo");
3178         } else {
3179             tfn!(".", "foo", r".\foo");
3180             tfn!(r"foo\", "bar", r"bar");
3181             tfn!(r"foo\.", "bar", r"bar");
3182             tfn!("..", "foo", r"..\foo");
3183             tfn!(r"foo\..", "bar", r"foo\..\bar");
3184             tfn!(r"\", "foo", r"\foo");
3185         }
3186     }
3187
3188     #[test]
3189     pub fn test_set_extension() {
3190         macro_rules! tfe(
3191                 ($path:expr, $ext:expr, $expected:expr, $output:expr) => ( {
3192                 let mut p = PathBuf::from($path);
3193                 let output = p.set_extension($ext);
3194                 assert!(p.to_str() == Some($expected) && output == $output,
3195                         "setting extension of {:?} to {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
3196                         $path, $ext, $expected, $output,
3197                         p.to_str().unwrap(), output);
3198             });
3199         );
3200
3201         tfe!("foo", "txt", "foo.txt", true);
3202         tfe!("foo.bar", "txt", "foo.txt", true);
3203         tfe!("foo.bar.baz", "txt", "foo.bar.txt", true);
3204         tfe!(".test", "txt", ".test.txt", true);
3205         tfe!("foo.txt", "", "foo", true);
3206         tfe!("foo", "", "foo", true);
3207         tfe!("", "foo", "", false);
3208         tfe!(".", "foo", ".", false);
3209         tfe!("foo/", "bar", "foo.bar", true);
3210         tfe!("foo/.", "bar", "foo.bar", true);
3211         tfe!("..", "foo", "..", false);
3212         tfe!("foo/..", "bar", "foo/..", false);
3213         tfe!("/", "foo", "/", false);
3214     }
3215
3216     #[test]
3217     fn test_eq_recievers() {
3218         use borrow::Cow;
3219
3220         let borrowed: &Path = Path::new("foo/bar");
3221         let mut owned: PathBuf = PathBuf::new();
3222         owned.push("foo");
3223         owned.push("bar");
3224         let borrowed_cow: Cow<Path> = borrowed.into();
3225         let owned_cow: Cow<Path> = owned.clone().into();
3226
3227         macro_rules! t {
3228             ($($current:expr),+) => {
3229                 $(
3230                     assert_eq!($current, borrowed);
3231                     assert_eq!($current, owned);
3232                     assert_eq!($current, borrowed_cow);
3233                     assert_eq!($current, owned_cow);
3234                 )+
3235             }
3236         }
3237
3238         t!(borrowed, owned, borrowed_cow, owned_cow);
3239     }
3240
3241     #[test]
3242     pub fn test_compare() {
3243         use hash::{Hash, Hasher, SipHasher};
3244
3245         fn hash<T: Hash>(t: T) -> u64 {
3246             let mut s = SipHasher::new_with_keys(0, 0);
3247             t.hash(&mut s);
3248             s.finish()
3249         }
3250
3251         macro_rules! tc(
3252             ($path1:expr, $path2:expr, eq: $eq:expr,
3253              starts_with: $starts_with:expr, ends_with: $ends_with:expr,
3254              relative_from: $relative_from:expr) => ({
3255                  let path1 = Path::new($path1);
3256                  let path2 = Path::new($path2);
3257
3258                  let eq = path1 == path2;
3259                  assert!(eq == $eq, "{:?} == {:?}, expected {:?}, got {:?}",
3260                          $path1, $path2, $eq, eq);
3261                  assert!($eq == (hash(path1) == hash(path2)),
3262                          "{:?} == {:?}, expected {:?}, got {} and {}",
3263                          $path1, $path2, $eq, hash(path1), hash(path2));
3264
3265                  let starts_with = path1.starts_with(path2);
3266                  assert!(starts_with == $starts_with,
3267                          "{:?}.starts_with({:?}), expected {:?}, got {:?}", $path1, $path2,
3268                          $starts_with, starts_with);
3269
3270                  let ends_with = path1.ends_with(path2);
3271                  assert!(ends_with == $ends_with,
3272                          "{:?}.ends_with({:?}), expected {:?}, got {:?}", $path1, $path2,
3273                          $ends_with, ends_with);
3274
3275                  let relative_from = path1.relative_from(path2).map(|p| p.to_str().unwrap());
3276                  let exp: Option<&str> = $relative_from;
3277                  assert!(relative_from == exp,
3278                          "{:?}.relative_from({:?}), expected {:?}, got {:?}", $path1, $path2,
3279                          exp, relative_from);
3280             });
3281         );
3282
3283         tc!("", "",
3284             eq: true,
3285             starts_with: true,
3286             ends_with: true,
3287             relative_from: Some("")
3288             );
3289
3290         tc!("foo", "",
3291             eq: false,
3292             starts_with: true,
3293             ends_with: true,
3294             relative_from: Some("foo")
3295             );
3296
3297         tc!("", "foo",
3298             eq: false,
3299             starts_with: false,
3300             ends_with: false,
3301             relative_from: None
3302             );
3303
3304         tc!("foo", "foo",
3305             eq: true,
3306             starts_with: true,
3307             ends_with: true,
3308             relative_from: Some("")
3309             );
3310
3311         tc!("foo/", "foo",
3312             eq: true,
3313             starts_with: true,
3314             ends_with: true,
3315             relative_from: Some("")
3316             );
3317
3318         tc!("foo/bar", "foo",
3319             eq: false,
3320             starts_with: true,
3321             ends_with: false,
3322             relative_from: Some("bar")
3323             );
3324
3325         tc!("foo/bar/baz", "foo/bar",
3326             eq: false,
3327             starts_with: true,
3328             ends_with: false,
3329             relative_from: Some("baz")
3330             );
3331
3332         tc!("foo/bar", "foo/bar/baz",
3333             eq: false,
3334             starts_with: false,
3335             ends_with: false,
3336             relative_from: None
3337             );
3338
3339         tc!("./foo/bar/", ".",
3340             eq: false,
3341             starts_with: true,
3342             ends_with: false,
3343             relative_from: Some("foo/bar")
3344             );
3345
3346         if cfg!(windows) {
3347             tc!(r"C:\src\rust\cargo-test\test\Cargo.toml",
3348                 r"c:\src\rust\cargo-test\test",
3349                 eq: false,
3350                 starts_with: true,
3351                 ends_with: false,
3352                 relative_from: Some("Cargo.toml")
3353                 );
3354
3355             tc!(r"c:\foo", r"C:\foo",
3356                 eq: true,
3357                 starts_with: true,
3358                 ends_with: true,
3359                 relative_from: Some("")
3360                 );
3361         }
3362     }
3363 }