]> git.lizzy.rs Git - rust.git/blob - src/libstd/path.rs
Auto merge of #30595 - steveklabnik:remove_learn_rust, r=gankro
[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     #[rustc_deprecated(reason = "use peekable() instead",
781                        since = "1.6.0")]
782     pub fn peek(&self) -> Option<Component<'a>> {
783         self.clone().next()
784     }
785 }
786
787 #[stable(feature = "rust1", since = "1.0.0")]
788 impl<'a> AsRef<Path> for Components<'a> {
789     fn as_ref(&self) -> &Path {
790         self.as_path()
791     }
792 }
793
794 #[stable(feature = "rust1", since = "1.0.0")]
795 impl<'a> AsRef<OsStr> for Components<'a> {
796     fn as_ref(&self) -> &OsStr {
797         self.as_path().as_os_str()
798     }
799 }
800
801 impl<'a> Iter<'a> {
802     /// Extracts a slice corresponding to the portion of the path remaining for iteration.
803     #[stable(feature = "rust1", since = "1.0.0")]
804     pub fn as_path(&self) -> &'a Path {
805         self.inner.as_path()
806     }
807 }
808
809 #[stable(feature = "rust1", since = "1.0.0")]
810 impl<'a> AsRef<Path> for Iter<'a> {
811     fn as_ref(&self) -> &Path {
812         self.as_path()
813     }
814 }
815
816 #[stable(feature = "rust1", since = "1.0.0")]
817 impl<'a> AsRef<OsStr> for Iter<'a> {
818     fn as_ref(&self) -> &OsStr {
819         self.as_path().as_os_str()
820     }
821 }
822
823 #[stable(feature = "rust1", since = "1.0.0")]
824 impl<'a> Iterator for Iter<'a> {
825     type Item = &'a OsStr;
826
827     fn next(&mut self) -> Option<&'a OsStr> {
828         self.inner.next().map(Component::as_os_str)
829     }
830 }
831
832 #[stable(feature = "rust1", since = "1.0.0")]
833 impl<'a> DoubleEndedIterator for Iter<'a> {
834     fn next_back(&mut self) -> Option<&'a OsStr> {
835         self.inner.next_back().map(Component::as_os_str)
836     }
837 }
838
839 #[stable(feature = "rust1", since = "1.0.0")]
840 impl<'a> Iterator for Components<'a> {
841     type Item = Component<'a>;
842
843     fn next(&mut self) -> Option<Component<'a>> {
844         while !self.finished() {
845             match self.front {
846                 State::Prefix if self.prefix_len() > 0 => {
847                     self.front = State::StartDir;
848                     debug_assert!(self.prefix_len() <= self.path.len());
849                     let raw = &self.path[..self.prefix_len()];
850                     self.path = &self.path[self.prefix_len()..];
851                     return Some(Component::Prefix(PrefixComponent {
852                         raw: unsafe { u8_slice_as_os_str(raw) },
853                         parsed: self.prefix.unwrap(),
854                     }));
855                 }
856                 State::Prefix => {
857                     self.front = State::StartDir;
858                 }
859                 State::StartDir => {
860                     self.front = State::Body;
861                     if self.has_physical_root {
862                         debug_assert!(!self.path.is_empty());
863                         self.path = &self.path[1..];
864                         return Some(Component::RootDir);
865                     } else if let Some(p) = self.prefix {
866                         if p.has_implicit_root() && !p.is_verbatim() {
867                             return Some(Component::RootDir);
868                         }
869                     } else if self.include_cur_dir() {
870                         debug_assert!(!self.path.is_empty());
871                         self.path = &self.path[1..];
872                         return Some(Component::CurDir);
873                     }
874                 }
875                 State::Body if !self.path.is_empty() => {
876                     let (size, comp) = self.parse_next_component();
877                     self.path = &self.path[size..];
878                     if comp.is_some() {
879                         return comp;
880                     }
881                 }
882                 State::Body => {
883                     self.front = State::Done;
884                 }
885                 State::Done => unreachable!(),
886             }
887         }
888         None
889     }
890 }
891
892 #[stable(feature = "rust1", since = "1.0.0")]
893 impl<'a> DoubleEndedIterator for Components<'a> {
894     fn next_back(&mut self) -> Option<Component<'a>> {
895         while !self.finished() {
896             match self.back {
897                 State::Body if self.path.len() > self.len_before_body() => {
898                     let (size, comp) = self.parse_next_component_back();
899                     self.path = &self.path[..self.path.len() - size];
900                     if comp.is_some() {
901                         return comp;
902                     }
903                 }
904                 State::Body => {
905                     self.back = State::StartDir;
906                 }
907                 State::StartDir => {
908                     self.back = State::Prefix;
909                     if self.has_physical_root {
910                         self.path = &self.path[..self.path.len() - 1];
911                         return Some(Component::RootDir);
912                     } else if let Some(p) = self.prefix {
913                         if p.has_implicit_root() && !p.is_verbatim() {
914                             return Some(Component::RootDir);
915                         }
916                     } else if self.include_cur_dir() {
917                         self.path = &self.path[..self.path.len() - 1];
918                         return Some(Component::CurDir);
919                     }
920                 }
921                 State::Prefix if self.prefix_len() > 0 => {
922                     self.back = State::Done;
923                     return Some(Component::Prefix(PrefixComponent {
924                         raw: unsafe { u8_slice_as_os_str(self.path) },
925                         parsed: self.prefix.unwrap(),
926                     }));
927                 }
928                 State::Prefix => {
929                     self.back = State::Done;
930                     return None;
931                 }
932                 State::Done => unreachable!(),
933             }
934         }
935         None
936     }
937 }
938
939 #[stable(feature = "rust1", since = "1.0.0")]
940 impl<'a> cmp::PartialEq for Components<'a> {
941     fn eq(&self, other: &Components<'a>) -> bool {
942         Iterator::eq(self.clone(), other.clone())
943     }
944 }
945
946 #[stable(feature = "rust1", since = "1.0.0")]
947 impl<'a> cmp::Eq for Components<'a> {}
948
949 #[stable(feature = "rust1", since = "1.0.0")]
950 impl<'a> cmp::PartialOrd for Components<'a> {
951     fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
952         Iterator::partial_cmp(self.clone(), other.clone())
953     }
954 }
955
956 #[stable(feature = "rust1", since = "1.0.0")]
957 impl<'a> cmp::Ord for Components<'a> {
958     fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
959         Iterator::cmp(self.clone(), other.clone())
960     }
961 }
962
963 ////////////////////////////////////////////////////////////////////////////////
964 // Basic types and traits
965 ////////////////////////////////////////////////////////////////////////////////
966
967 /// An owned, mutable path (akin to `String`).
968 ///
969 /// This type provides methods like `push` and `set_extension` that mutate the
970 /// path in place. It also implements `Deref` to `Path`, meaning that all
971 /// methods on `Path` slices are available on `PathBuf` values as well.
972 ///
973 /// More details about the overall approach can be found in
974 /// the module documentation.
975 ///
976 /// # Examples
977 ///
978 /// ```
979 /// use std::path::PathBuf;
980 ///
981 /// let mut path = PathBuf::from("c:\\");
982 /// path.push("windows");
983 /// path.push("system32");
984 /// path.set_extension("dll");
985 /// ```
986 #[derive(Clone)]
987 #[stable(feature = "rust1", since = "1.0.0")]
988 pub struct PathBuf {
989     inner: OsString,
990 }
991
992 impl PathBuf {
993     fn as_mut_vec(&mut self) -> &mut Vec<u8> {
994         unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
995     }
996
997     /// Allocates an empty `PathBuf`.
998     #[stable(feature = "rust1", since = "1.0.0")]
999     pub fn new() -> PathBuf {
1000         PathBuf { inner: OsString::new() }
1001     }
1002
1003     /// Coerces to a `Path` slice.
1004     #[stable(feature = "rust1", since = "1.0.0")]
1005     pub fn as_path(&self) -> &Path {
1006         self
1007     }
1008
1009     /// Extends `self` with `path`.
1010     ///
1011     /// If `path` is absolute, it replaces the current path.
1012     ///
1013     /// On Windows:
1014     ///
1015     /// * if `path` has a root but no prefix (e.g. `\windows`), it
1016     ///   replaces everything except for the prefix (if any) of `self`.
1017     /// * if `path` has a prefix but no root, it replaces `self`.
1018     ///
1019     /// # Examples
1020     ///
1021     /// ```
1022     /// use std::path::PathBuf;
1023     ///
1024     /// let mut path = PathBuf::new();
1025     /// path.push("/tmp");
1026     /// path.push("file.bk");
1027     /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
1028     ///
1029     /// // Pushing an absolute path replaces the current path
1030     /// path.push("/etc/passwd");
1031     /// assert_eq!(path, PathBuf::from("/etc/passwd"));
1032     /// ```
1033     #[stable(feature = "rust1", since = "1.0.0")]
1034     pub fn push<P: AsRef<Path>>(&mut self, path: P) {
1035         self._push(path.as_ref())
1036     }
1037
1038     fn _push(&mut self, path: &Path) {
1039         // in general, a separator is needed if the rightmost byte is not a separator
1040         let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
1041
1042         // in the special case of `C:` on Windows, do *not* add a separator
1043         {
1044             let comps = self.components();
1045             if comps.prefix_len() > 0 && comps.prefix_len() == comps.path.len() &&
1046                comps.prefix.unwrap().is_drive() {
1047                 need_sep = false
1048             }
1049         }
1050
1051         // absolute `path` replaces `self`
1052         if path.is_absolute() || path.prefix().is_some() {
1053             self.as_mut_vec().truncate(0);
1054
1055         // `path` has a root but no prefix, e.g. `\windows` (Windows only)
1056         } else if path.has_root() {
1057             let prefix_len = self.components().prefix_remaining();
1058             self.as_mut_vec().truncate(prefix_len);
1059
1060         // `path` is a pure relative path
1061         } else if need_sep {
1062             self.inner.push(MAIN_SEP_STR);
1063         }
1064
1065         self.inner.push(path);
1066     }
1067
1068     /// Truncate `self` to `self.parent()`.
1069     ///
1070     /// Returns false and does nothing if `self.file_name()` is `None`.
1071     /// Otherwise, returns `true`.
1072     #[stable(feature = "rust1", since = "1.0.0")]
1073     pub fn pop(&mut self) -> bool {
1074         match self.parent().map(|p| p.as_u8_slice().len()) {
1075             Some(len) => {
1076                 self.as_mut_vec().truncate(len);
1077                 true
1078             }
1079             None => false,
1080         }
1081     }
1082
1083     /// Updates `self.file_name()` to `file_name`.
1084     ///
1085     /// If `self.file_name()` was `None`, this is equivalent to pushing
1086     /// `file_name`.
1087     ///
1088     /// # Examples
1089     ///
1090     /// ```
1091     /// use std::path::PathBuf;
1092     ///
1093     /// let mut buf = PathBuf::from("/");
1094     /// assert!(buf.file_name() == None);
1095     /// buf.set_file_name("bar");
1096     /// assert!(buf == PathBuf::from("/bar"));
1097     /// assert!(buf.file_name().is_some());
1098     /// buf.set_file_name("baz.txt");
1099     /// assert!(buf == PathBuf::from("/baz.txt"));
1100     /// ```
1101     #[stable(feature = "rust1", since = "1.0.0")]
1102     pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
1103         self._set_file_name(file_name.as_ref())
1104     }
1105
1106     fn _set_file_name(&mut self, file_name: &OsStr) {
1107         if self.file_name().is_some() {
1108             let popped = self.pop();
1109             debug_assert!(popped);
1110         }
1111         self.push(file_name);
1112     }
1113
1114     /// Updates `self.extension()` to `extension`.
1115     ///
1116     /// If `self.file_name()` is `None`, does nothing and returns `false`.
1117     ///
1118     /// Otherwise, returns `true`; if `self.extension()` is `None`, the extension
1119     /// is added; otherwise it is replaced.
1120     #[stable(feature = "rust1", since = "1.0.0")]
1121     pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
1122         self._set_extension(extension.as_ref())
1123     }
1124
1125     fn _set_extension(&mut self, extension: &OsStr) -> bool {
1126         if self.file_name().is_none() {
1127             return false;
1128         }
1129
1130         let mut stem = match self.file_stem() {
1131             Some(stem) => stem.to_os_string(),
1132             None => OsString::new(),
1133         };
1134
1135         if !os_str_as_u8_slice(extension).is_empty() {
1136             stem.push(".");
1137             stem.push(extension);
1138         }
1139         self.set_file_name(&stem);
1140
1141         true
1142     }
1143
1144     /// Consumes the `PathBuf`, yielding its internal `OsString` storage.
1145     #[stable(feature = "rust1", since = "1.0.0")]
1146     pub fn into_os_string(self) -> OsString {
1147         self.inner
1148     }
1149 }
1150
1151 #[stable(feature = "rust1", since = "1.0.0")]
1152 impl<'a, T: ?Sized + AsRef<OsStr>> From<&'a T> for PathBuf {
1153     fn from(s: &'a T) -> PathBuf {
1154         PathBuf::from(s.as_ref().to_os_string())
1155     }
1156 }
1157
1158 #[stable(feature = "rust1", since = "1.0.0")]
1159 impl From<OsString> for PathBuf {
1160     fn from(s: OsString) -> PathBuf {
1161         PathBuf { inner: s }
1162     }
1163 }
1164
1165 #[stable(feature = "rust1", since = "1.0.0")]
1166 impl From<String> for PathBuf {
1167     fn from(s: String) -> PathBuf {
1168         PathBuf::from(OsString::from(s))
1169     }
1170 }
1171
1172 #[stable(feature = "rust1", since = "1.0.0")]
1173 impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
1174     fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
1175         let mut buf = PathBuf::new();
1176         buf.extend(iter);
1177         buf
1178     }
1179 }
1180
1181 #[stable(feature = "rust1", since = "1.0.0")]
1182 impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
1183     fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
1184         for p in iter {
1185             self.push(p.as_ref())
1186         }
1187     }
1188 }
1189
1190 #[stable(feature = "rust1", since = "1.0.0")]
1191 impl fmt::Debug for PathBuf {
1192     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1193         fmt::Debug::fmt(&**self, formatter)
1194     }
1195 }
1196
1197 #[stable(feature = "rust1", since = "1.0.0")]
1198 impl ops::Deref for PathBuf {
1199     type Target = Path;
1200
1201     fn deref(&self) -> &Path {
1202         Path::new(&self.inner)
1203     }
1204 }
1205
1206 #[stable(feature = "rust1", since = "1.0.0")]
1207 impl Borrow<Path> for PathBuf {
1208     fn borrow(&self) -> &Path {
1209         self.deref()
1210     }
1211 }
1212
1213 #[stable(feature = "rust1", since = "1.0.0")]
1214 impl IntoCow<'static, Path> for PathBuf {
1215     fn into_cow(self) -> Cow<'static, Path> {
1216         Cow::Owned(self)
1217     }
1218 }
1219
1220 #[stable(feature = "rust1", since = "1.0.0")]
1221 impl<'a> IntoCow<'a, Path> for &'a Path {
1222     fn into_cow(self) -> Cow<'a, Path> {
1223         Cow::Borrowed(self)
1224     }
1225 }
1226
1227 #[stable(feature = "cow_from_path", since = "1.6.0")]
1228 impl<'a> From<&'a Path> for Cow<'a, Path> {
1229     #[inline]
1230     fn from(s: &'a Path) -> Cow<'a, Path> {
1231         Cow::Borrowed(s)
1232     }
1233 }
1234
1235 #[stable(feature = "cow_from_path", since = "1.6.0")]
1236 impl<'a> From<PathBuf> for Cow<'a, Path> {
1237     #[inline]
1238     fn from(s: PathBuf) -> Cow<'a, Path> {
1239         Cow::Owned(s)
1240     }
1241 }
1242
1243 #[stable(feature = "rust1", since = "1.0.0")]
1244 impl ToOwned for Path {
1245     type Owned = PathBuf;
1246     fn to_owned(&self) -> PathBuf {
1247         self.to_path_buf()
1248     }
1249 }
1250
1251 #[stable(feature = "rust1", since = "1.0.0")]
1252 impl cmp::PartialEq for PathBuf {
1253     fn eq(&self, other: &PathBuf) -> bool {
1254         self.components() == other.components()
1255     }
1256 }
1257
1258 #[stable(feature = "rust1", since = "1.0.0")]
1259 impl Hash for PathBuf {
1260     fn hash<H: Hasher>(&self, h: &mut H) {
1261         self.as_path().hash(h)
1262     }
1263 }
1264
1265 #[stable(feature = "rust1", since = "1.0.0")]
1266 impl cmp::Eq for PathBuf {}
1267
1268 #[stable(feature = "rust1", since = "1.0.0")]
1269 impl cmp::PartialOrd for PathBuf {
1270     fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
1271         self.components().partial_cmp(other.components())
1272     }
1273 }
1274
1275 #[stable(feature = "rust1", since = "1.0.0")]
1276 impl cmp::Ord for PathBuf {
1277     fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
1278         self.components().cmp(other.components())
1279     }
1280 }
1281
1282 #[stable(feature = "rust1", since = "1.0.0")]
1283 impl AsRef<OsStr> for PathBuf {
1284     fn as_ref(&self) -> &OsStr {
1285         &self.inner[..]
1286     }
1287 }
1288
1289 #[stable(feature = "rust1", since = "1.0.0")]
1290 impl Into<OsString> for PathBuf {
1291     fn into(self) -> OsString {
1292         self.inner
1293     }
1294 }
1295
1296 /// A slice of a path (akin to `str`).
1297 ///
1298 /// This type supports a number of operations for inspecting a path, including
1299 /// breaking the path into its components (separated by `/` or `\`, depending on
1300 /// the platform), extracting the file name, determining whether the path is
1301 /// absolute, and so on. More details about the overall approach can be found in
1302 /// the module documentation.
1303 ///
1304 /// This is an *unsized* type, meaning that it must always be used behind a
1305 /// pointer like `&` or `Box`.
1306 ///
1307 /// # Examples
1308 ///
1309 /// ```
1310 /// use std::path::Path;
1311 ///
1312 /// let path = Path::new("/tmp/foo/bar.txt");
1313 /// let file = path.file_name();
1314 /// let extension = path.extension();
1315 /// let parent_dir = path.parent();
1316 /// ```
1317 ///
1318 #[stable(feature = "rust1", since = "1.0.0")]
1319 pub struct Path {
1320     inner: OsStr,
1321 }
1322
1323 impl Path {
1324     // The following (private!) function allows construction of a path from a u8
1325     // slice, which is only safe when it is known to follow the OsStr encoding.
1326     unsafe fn from_u8_slice(s: &[u8]) -> &Path {
1327         Path::new(u8_slice_as_os_str(s))
1328     }
1329     // The following (private!) function reveals the byte encoding used for OsStr.
1330     fn as_u8_slice(&self) -> &[u8] {
1331         os_str_as_u8_slice(&self.inner)
1332     }
1333
1334     /// Directly wrap a string slice as a `Path` slice.
1335     ///
1336     /// This is a cost-free conversion.
1337     ///
1338     /// # Examples
1339     ///
1340     /// ```
1341     /// use std::path::Path;
1342     ///
1343     /// Path::new("foo.txt");
1344     /// ```
1345     ///
1346     /// You can create `Path`s from `String`s, or even other `Path`s:
1347     ///
1348     /// ```
1349     /// use std::path::Path;
1350     ///
1351     /// let string = String::from("foo.txt");
1352     /// let from_string = Path::new(&string);
1353     /// let from_path = Path::new(&from_string);
1354     /// assert_eq!(from_string, from_path);
1355     /// ```
1356     #[stable(feature = "rust1", since = "1.0.0")]
1357     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
1358         unsafe { mem::transmute(s.as_ref()) }
1359     }
1360
1361     /// Yields the underlying `OsStr` slice.
1362     ///
1363     /// # Examples
1364     ///
1365     /// ```
1366     /// use std::path::Path;
1367     ///
1368     /// let os_str = Path::new("foo.txt").as_os_str();
1369     /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
1370     /// ```
1371     #[stable(feature = "rust1", since = "1.0.0")]
1372     pub fn as_os_str(&self) -> &OsStr {
1373         &self.inner
1374     }
1375
1376     /// Yields a `&str` slice if the `Path` is valid unicode.
1377     ///
1378     /// This conversion may entail doing a check for UTF-8 validity.
1379     ///
1380     /// # Examples
1381     ///
1382     /// ```
1383     /// use std::path::Path;
1384     ///
1385     /// let path_str = Path::new("foo.txt").to_str();
1386     /// assert_eq!(path_str, Some("foo.txt"));
1387     /// ```
1388     #[stable(feature = "rust1", since = "1.0.0")]
1389     pub fn to_str(&self) -> Option<&str> {
1390         self.inner.to_str()
1391     }
1392
1393     /// Converts a `Path` to a `Cow<str>`.
1394     ///
1395     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
1396     ///
1397     /// # Examples
1398     ///
1399     /// ```
1400     /// use std::path::Path;
1401     ///
1402     /// let path_str = Path::new("foo.txt").to_string_lossy();
1403     /// assert_eq!(path_str, "foo.txt");
1404     /// ```
1405     #[stable(feature = "rust1", since = "1.0.0")]
1406     pub fn to_string_lossy(&self) -> Cow<str> {
1407         self.inner.to_string_lossy()
1408     }
1409
1410     /// Converts a `Path` to an owned `PathBuf`.
1411     ///
1412     /// # Examples
1413     ///
1414     /// ```
1415     /// use std::path::Path;
1416     ///
1417     /// let path_buf = Path::new("foo.txt").to_path_buf();
1418     /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
1419     /// ```
1420     #[stable(feature = "rust1", since = "1.0.0")]
1421     pub fn to_path_buf(&self) -> PathBuf {
1422         PathBuf::from(self.inner.to_os_string())
1423     }
1424
1425     /// A path is *absolute* if it is independent of the current directory.
1426     ///
1427     /// * On Unix, a path is absolute if it starts with the root, so
1428     /// `is_absolute` and `has_root` are equivalent.
1429     ///
1430     /// * On Windows, a path is absolute if it has a prefix and starts with the
1431     /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not. In
1432     /// other words, `path.is_absolute() == path.prefix().is_some() && path.has_root()`.
1433     ///
1434     /// # Examples
1435     ///
1436     /// ```
1437     /// use std::path::Path;
1438     ///
1439     /// assert!(!Path::new("foo.txt").is_absolute());
1440     /// ```
1441     #[stable(feature = "rust1", since = "1.0.0")]
1442     pub fn is_absolute(&self) -> bool {
1443         self.has_root() && (cfg!(unix) || self.prefix().is_some())
1444     }
1445
1446     /// A path is *relative* if it is not absolute.
1447     ///
1448     /// # Examples
1449     ///
1450     /// ```
1451     /// use std::path::Path;
1452     ///
1453     /// assert!(Path::new("foo.txt").is_relative());
1454     /// ```
1455     #[stable(feature = "rust1", since = "1.0.0")]
1456     pub fn is_relative(&self) -> bool {
1457         !self.is_absolute()
1458     }
1459
1460     /// Returns the *prefix* of a path, if any.
1461     ///
1462     /// Prefixes are relevant only for Windows paths, and consist of volumes
1463     /// like `C:`, UNC prefixes like `\\server`, and others described in more
1464     /// detail in `std::os::windows::PathExt`.
1465     #[unstable(feature = "path_prefix",
1466                reason = "uncertain whether to expose this convenience",
1467                issue = "27722")]
1468     pub fn prefix(&self) -> Option<Prefix> {
1469         self.components().prefix
1470     }
1471
1472     /// A path has a root if the body of the path begins with the directory separator.
1473     ///
1474     /// * On Unix, a path has a root if it begins with `/`.
1475     ///
1476     /// * On Windows, a path has a root if it:
1477     ///     * has no prefix and begins with a separator, e.g. `\\windows`
1478     ///     * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows`
1479     ///     * has any non-disk prefix, e.g. `\\server\share`
1480     ///
1481     /// # Examples
1482     ///
1483     /// ```
1484     /// use std::path::Path;
1485     ///
1486     /// assert!(Path::new("/etc/passwd").has_root());
1487     /// ```
1488     #[stable(feature = "rust1", since = "1.0.0")]
1489     pub fn has_root(&self) -> bool {
1490         self.components().has_root()
1491     }
1492
1493     /// The path without its final component, if any.
1494     ///
1495     /// Returns `None` if the path terminates in a root or prefix.
1496     ///
1497     /// # Examples
1498     ///
1499     /// ```
1500     /// use std::path::Path;
1501     ///
1502     /// let path = Path::new("/foo/bar");
1503     /// let parent = path.parent().unwrap();
1504     /// assert_eq!(parent, Path::new("/foo"));
1505     ///
1506     /// let grand_parent = parent.parent().unwrap();
1507     /// assert_eq!(grand_parent, Path::new("/"));
1508     /// assert_eq!(grand_parent.parent(), None);
1509     /// ```
1510     #[stable(feature = "rust1", since = "1.0.0")]
1511     pub fn parent(&self) -> Option<&Path> {
1512         let mut comps = self.components();
1513         let comp = comps.next_back();
1514         comp.and_then(|p| {
1515             match p {
1516                 Component::Normal(_) |
1517                 Component::CurDir |
1518                 Component::ParentDir => Some(comps.as_path()),
1519                 _ => None,
1520             }
1521         })
1522     }
1523
1524     /// The final component of the path, if it is a normal file.
1525     ///
1526     /// If the path terminates in `.`, `..`, or consists solely of a root of
1527     /// prefix, `file_name` will return `None`.
1528     ///
1529     /// # Examples
1530     ///
1531     /// ```
1532     /// use std::path::Path;
1533     /// use std::ffi::OsStr;
1534     ///
1535     /// let path = Path::new("foo.txt");
1536     /// let os_str = OsStr::new("foo.txt");
1537     ///
1538     /// assert_eq!(Some(os_str), path.file_name());
1539     /// ```
1540     #[stable(feature = "rust1", since = "1.0.0")]
1541     pub fn file_name(&self) -> Option<&OsStr> {
1542         self.components().next_back().and_then(|p| {
1543             match p {
1544                 Component::Normal(p) => Some(p.as_ref()),
1545                 _ => None,
1546             }
1547         })
1548     }
1549
1550     /// Returns a path that, when joined onto `base`, yields `self`.
1551     ///
1552     /// If `base` is not a prefix of `self` (i.e. `starts_with`
1553     /// returns false), then `relative_from` returns `None`.
1554     #[unstable(feature = "path_relative_from", reason = "see #23284",
1555                issue = "23284")]
1556     pub fn relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path> {
1557         self._relative_from(base.as_ref())
1558     }
1559
1560     fn _relative_from<'a>(&'a self, base: &'a Path) -> Option<&'a Path> {
1561         iter_after(self.components(), base.components()).map(|c| c.as_path())
1562     }
1563
1564     /// Determines whether `base` is a prefix of `self`.
1565     ///
1566     /// Only considers whole path components to match.
1567     ///
1568     /// # Examples
1569     ///
1570     /// ```
1571     /// use std::path::Path;
1572     ///
1573     /// let path = Path::new("/etc/passwd");
1574     ///
1575     /// assert!(path.starts_with("/etc"));
1576     ///
1577     /// assert!(!path.starts_with("/e"));
1578     /// ```
1579     #[stable(feature = "rust1", since = "1.0.0")]
1580     pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
1581         self._starts_with(base.as_ref())
1582     }
1583
1584     fn _starts_with(&self, base: &Path) -> bool {
1585         iter_after(self.components(), base.components()).is_some()
1586     }
1587
1588     /// Determines whether `child` is a suffix of `self`.
1589     ///
1590     /// Only considers whole path components to match.
1591     ///
1592     /// # Examples
1593     ///
1594     /// ```
1595     /// use std::path::Path;
1596     ///
1597     /// let path = Path::new("/etc/passwd");
1598     ///
1599     /// assert!(path.ends_with("passwd"));
1600     /// ```
1601     #[stable(feature = "rust1", since = "1.0.0")]
1602     pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
1603         self._ends_with(child.as_ref())
1604     }
1605
1606     fn _ends_with(&self, child: &Path) -> bool {
1607         iter_after(self.components().rev(), child.components().rev()).is_some()
1608     }
1609
1610     /// Extracts the stem (non-extension) portion of `self.file_name()`.
1611     ///
1612     /// The stem is:
1613     ///
1614     /// * None, if there is no file name;
1615     /// * The entire file name if there is no embedded `.`;
1616     /// * The entire file name if the file name begins with `.` and has no other `.`s within;
1617     /// * Otherwise, the portion of the file name before the final `.`
1618     ///
1619     /// # Examples
1620     ///
1621     /// ```
1622     /// use std::path::Path;
1623     ///
1624     /// let path = Path::new("foo.rs");
1625     ///
1626     /// assert_eq!("foo", path.file_stem().unwrap());
1627     /// ```
1628     #[stable(feature = "rust1", since = "1.0.0")]
1629     pub fn file_stem(&self) -> Option<&OsStr> {
1630         self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
1631     }
1632
1633     /// Extracts the extension of `self.file_name()`, if possible.
1634     ///
1635     /// The extension is:
1636     ///
1637     /// * None, if there is no file name;
1638     /// * None, if there is no embedded `.`;
1639     /// * None, if the file name begins with `.` and has no other `.`s within;
1640     /// * Otherwise, the portion of the file name after the final `.`
1641     ///
1642     /// # Examples
1643     ///
1644     /// ```
1645     /// use std::path::Path;
1646     ///
1647     /// let path = Path::new("foo.rs");
1648     ///
1649     /// assert_eq!("rs", path.extension().unwrap());
1650     /// ```
1651     #[stable(feature = "rust1", since = "1.0.0")]
1652     pub fn extension(&self) -> Option<&OsStr> {
1653         self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
1654     }
1655
1656     /// Creates an owned `PathBuf` with `path` adjoined to `self`.
1657     ///
1658     /// See `PathBuf::push` for more details on what it means to adjoin a path.
1659     ///
1660     /// # Examples
1661     ///
1662     /// ```
1663     /// use std::path::{Path, PathBuf};
1664     ///
1665     /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
1666     /// ```
1667     #[stable(feature = "rust1", since = "1.0.0")]
1668     pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
1669         self._join(path.as_ref())
1670     }
1671
1672     fn _join(&self, path: &Path) -> PathBuf {
1673         let mut buf = self.to_path_buf();
1674         buf.push(path);
1675         buf
1676     }
1677
1678     /// Creates an owned `PathBuf` like `self` but with the given file name.
1679     ///
1680     /// See `PathBuf::set_file_name` for more details.
1681     ///
1682     /// # Examples
1683     ///
1684     /// ```
1685     /// use std::path::{Path, PathBuf};
1686     ///
1687     /// let path = Path::new("/tmp/foo.txt");
1688     /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
1689     /// ```
1690     #[stable(feature = "rust1", since = "1.0.0")]
1691     pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
1692         self._with_file_name(file_name.as_ref())
1693     }
1694
1695     fn _with_file_name(&self, file_name: &OsStr) -> PathBuf {
1696         let mut buf = self.to_path_buf();
1697         buf.set_file_name(file_name);
1698         buf
1699     }
1700
1701     /// Creates an owned `PathBuf` like `self` but with the given extension.
1702     ///
1703     /// See `PathBuf::set_extension` for more details.
1704     ///
1705     /// # Examples
1706     ///
1707     /// ```
1708     /// use std::path::{Path, PathBuf};
1709     ///
1710     /// let path = Path::new("foo.rs");
1711     /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
1712     /// ```
1713     #[stable(feature = "rust1", since = "1.0.0")]
1714     pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
1715         self._with_extension(extension.as_ref())
1716     }
1717
1718     fn _with_extension(&self, extension: &OsStr) -> PathBuf {
1719         let mut buf = self.to_path_buf();
1720         buf.set_extension(extension);
1721         buf
1722     }
1723
1724     /// Produce an iterator over the components of the path.
1725     ///
1726     /// # Examples
1727     ///
1728     /// ```
1729     /// use std::path::{Path, Component};
1730     /// use std::ffi::OsStr;
1731     ///
1732     /// let mut components = Path::new("/tmp/foo.txt").components();
1733     ///
1734     /// assert_eq!(components.next(), Some(Component::RootDir));
1735     /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
1736     /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
1737     /// assert_eq!(components.next(), None)
1738     /// ```
1739     #[stable(feature = "rust1", since = "1.0.0")]
1740     pub fn components(&self) -> Components {
1741         let prefix = parse_prefix(self.as_os_str());
1742         Components {
1743             path: self.as_u8_slice(),
1744             prefix: prefix,
1745             has_physical_root: has_physical_root(self.as_u8_slice(), prefix),
1746             front: State::Prefix,
1747             back: State::Body,
1748         }
1749     }
1750
1751     /// Produce an iterator over the path's components viewed as `OsStr` slices.
1752     ///
1753     /// # Examples
1754     ///
1755     /// ```
1756     /// use std::path::{self, Path};
1757     /// use std::ffi::OsStr;
1758     ///
1759     /// let mut it = Path::new("/tmp/foo.txt").iter();
1760     /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
1761     /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
1762     /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
1763     /// assert_eq!(it.next(), None)
1764     /// ```
1765     #[stable(feature = "rust1", since = "1.0.0")]
1766     pub fn iter(&self) -> Iter {
1767         Iter { inner: self.components() }
1768     }
1769
1770     /// Returns an object that implements `Display` for safely printing paths
1771     /// that may contain non-Unicode data.
1772     ///
1773     /// # Examples
1774     ///
1775     /// ```
1776     /// use std::path::Path;
1777     ///
1778     /// let path = Path::new("/tmp/foo.rs");
1779     ///
1780     /// println!("{}", path.display());
1781     /// ```
1782     #[stable(feature = "rust1", since = "1.0.0")]
1783     pub fn display(&self) -> Display {
1784         Display { path: self }
1785     }
1786
1787
1788     /// Gets information on the file, directory, etc at this path.
1789     ///
1790     /// Consult the `fs::metadata` documentation for more info.
1791     ///
1792     /// This call preserves identical runtime/error semantics with
1793     /// `fs::metadata`.
1794     #[stable(feature = "path_ext", since = "1.5.0")]
1795     pub fn metadata(&self) -> io::Result<fs::Metadata> {
1796         fs::metadata(self)
1797     }
1798
1799     /// Gets information on the file, directory, etc at this path.
1800     ///
1801     /// Consult the `fs::symlink_metadata` documentation for more info.
1802     ///
1803     /// This call preserves identical runtime/error semantics with
1804     /// `fs::symlink_metadata`.
1805     #[stable(feature = "path_ext", since = "1.5.0")]
1806     pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
1807         fs::symlink_metadata(self)
1808     }
1809
1810     /// Returns the canonical form of a path, normalizing all components and
1811     /// eliminate all symlinks.
1812     ///
1813     /// This call preserves identical runtime/error semantics with
1814     /// `fs::canonicalize`.
1815     #[stable(feature = "path_ext", since = "1.5.0")]
1816     pub fn canonicalize(&self) -> io::Result<PathBuf> {
1817         fs::canonicalize(self)
1818     }
1819
1820     /// Reads the symlink at this path.
1821     ///
1822     /// For more information see `fs::read_link`.
1823     #[stable(feature = "path_ext", since = "1.5.0")]
1824     pub fn read_link(&self) -> io::Result<PathBuf> {
1825         fs::read_link(self)
1826     }
1827
1828     /// Reads the directory at this path.
1829     ///
1830     /// For more information see `fs::read_dir`.
1831     #[stable(feature = "path_ext", since = "1.5.0")]
1832     pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
1833         fs::read_dir(self)
1834     }
1835
1836     /// Boolean value indicator whether the underlying file exists on the local
1837     /// filesystem. Returns false in exactly the cases where `fs::metadata`
1838     /// fails.
1839     #[stable(feature = "path_ext", since = "1.5.0")]
1840     pub fn exists(&self) -> bool {
1841         fs::metadata(self).is_ok()
1842     }
1843
1844     /// Whether the underlying implementation (be it a file path, or something
1845     /// else) points at a "regular file" on the FS. Will return false for paths
1846     /// to non-existent locations or directories or other non-regular files
1847     /// (named pipes, etc). Follows links when making this determination.
1848     #[stable(feature = "path_ext", since = "1.5.0")]
1849     pub fn is_file(&self) -> bool {
1850         fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
1851     }
1852
1853     /// Whether the underlying implementation (be it a file path, or something
1854     /// else) is pointing at a directory in the underlying FS. Will return
1855     /// false for paths to non-existent locations or if the item is not a
1856     /// directory (eg files, named pipes, etc). Follows links when making this
1857     /// determination.
1858     #[stable(feature = "path_ext", since = "1.5.0")]
1859     pub fn is_dir(&self) -> bool {
1860         fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
1861     }
1862 }
1863
1864 #[stable(feature = "rust1", since = "1.0.0")]
1865 impl AsRef<OsStr> for Path {
1866     fn as_ref(&self) -> &OsStr {
1867         &self.inner
1868     }
1869 }
1870
1871 #[stable(feature = "rust1", since = "1.0.0")]
1872 impl fmt::Debug for Path {
1873     fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1874         self.inner.fmt(formatter)
1875     }
1876 }
1877
1878 /// Helper struct for safely printing paths with `format!()` and `{}`
1879 #[stable(feature = "rust1", since = "1.0.0")]
1880 pub struct Display<'a> {
1881     path: &'a Path,
1882 }
1883
1884 #[stable(feature = "rust1", since = "1.0.0")]
1885 impl<'a> fmt::Debug for Display<'a> {
1886     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1887         fmt::Debug::fmt(&self.path.to_string_lossy(), f)
1888     }
1889 }
1890
1891 #[stable(feature = "rust1", since = "1.0.0")]
1892 impl<'a> fmt::Display for Display<'a> {
1893     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1894         fmt::Display::fmt(&self.path.to_string_lossy(), f)
1895     }
1896 }
1897
1898 #[stable(feature = "rust1", since = "1.0.0")]
1899 impl cmp::PartialEq for Path {
1900     fn eq(&self, other: &Path) -> bool {
1901         self.components().eq(other.components())
1902     }
1903 }
1904
1905 #[stable(feature = "rust1", since = "1.0.0")]
1906 impl Hash for Path {
1907     fn hash<H: Hasher>(&self, h: &mut H) {
1908         for component in self.components() {
1909             component.hash(h);
1910         }
1911     }
1912 }
1913
1914 #[stable(feature = "rust1", since = "1.0.0")]
1915 impl cmp::Eq for Path {}
1916
1917 #[stable(feature = "rust1", since = "1.0.0")]
1918 impl cmp::PartialOrd for Path {
1919     fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
1920         self.components().partial_cmp(other.components())
1921     }
1922 }
1923
1924 #[stable(feature = "rust1", since = "1.0.0")]
1925 impl cmp::Ord for Path {
1926     fn cmp(&self, other: &Path) -> cmp::Ordering {
1927         self.components().cmp(other.components())
1928     }
1929 }
1930
1931 #[stable(feature = "rust1", since = "1.0.0")]
1932 impl AsRef<Path> for Path {
1933     fn as_ref(&self) -> &Path {
1934         self
1935     }
1936 }
1937
1938 #[stable(feature = "rust1", since = "1.0.0")]
1939 impl AsRef<Path> for OsStr {
1940     fn as_ref(&self) -> &Path {
1941         Path::new(self)
1942     }
1943 }
1944
1945 #[stable(feature = "rust1", since = "1.0.0")]
1946 impl AsRef<Path> for OsString {
1947     fn as_ref(&self) -> &Path {
1948         Path::new(self)
1949     }
1950 }
1951
1952 #[stable(feature = "rust1", since = "1.0.0")]
1953 impl AsRef<Path> for str {
1954     fn as_ref(&self) -> &Path {
1955         Path::new(self)
1956     }
1957 }
1958
1959 #[stable(feature = "rust1", since = "1.0.0")]
1960 impl AsRef<Path> for String {
1961     fn as_ref(&self) -> &Path {
1962         Path::new(self)
1963     }
1964 }
1965
1966 #[stable(feature = "rust1", since = "1.0.0")]
1967 impl AsRef<Path> for PathBuf {
1968     fn as_ref(&self) -> &Path {
1969         self
1970     }
1971 }
1972
1973 #[stable(feature = "path_into_iter", since = "1.6.0")]
1974 impl<'a> IntoIterator for &'a PathBuf {
1975     type Item = &'a OsStr;
1976     type IntoIter = Iter<'a>;
1977     fn into_iter(self) -> Iter<'a> { self.iter() }
1978 }
1979
1980 #[stable(feature = "path_into_iter", since = "1.6.0")]
1981 impl<'a> IntoIterator for &'a Path {
1982     type Item = &'a OsStr;
1983     type IntoIter = Iter<'a>;
1984     fn into_iter(self) -> Iter<'a> { self.iter() }
1985 }
1986
1987 macro_rules! impl_eq {
1988     ($lhs:ty, $rhs: ty) => {
1989         #[stable(feature = "partialeq_path", since = "1.6.0")]
1990         impl<'a, 'b> PartialEq<$rhs> for $lhs {
1991             #[inline]
1992             fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other) }
1993         }
1994
1995         #[stable(feature = "partialeq_path", since = "1.6.0")]
1996         impl<'a, 'b> PartialEq<$lhs> for $rhs {
1997             #[inline]
1998             fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) }
1999         }
2000
2001     }
2002 }
2003
2004 impl_eq!(PathBuf, Path);
2005 impl_eq!(PathBuf, &'a Path);
2006 impl_eq!(Cow<'a, Path>, Path);
2007 impl_eq!(Cow<'a, Path>, &'b Path);
2008 impl_eq!(Cow<'a, Path>, PathBuf);
2009
2010 #[cfg(test)]
2011 mod tests {
2012     use super::*;
2013     use string::{ToString, String};
2014     use vec::Vec;
2015
2016     macro_rules! t(
2017         ($path:expr, iter: $iter:expr) => (
2018             {
2019                 let path = Path::new($path);
2020
2021                 // Forward iteration
2022                 let comps = path.iter()
2023                     .map(|p| p.to_string_lossy().into_owned())
2024                     .collect::<Vec<String>>();
2025                 let exp: &[&str] = &$iter;
2026                 let exps = exp.iter().map(|s| s.to_string()).collect::<Vec<String>>();
2027                 assert!(comps == exps, "iter: Expected {:?}, found {:?}",
2028                         exps, comps);
2029
2030                 // Reverse iteration
2031                 let comps = Path::new($path).iter().rev()
2032                     .map(|p| p.to_string_lossy().into_owned())
2033                     .collect::<Vec<String>>();
2034                 let exps = exps.into_iter().rev().collect::<Vec<String>>();
2035                 assert!(comps == exps, "iter().rev(): Expected {:?}, found {:?}",
2036                         exps, comps);
2037             }
2038         );
2039
2040         ($path:expr, has_root: $has_root:expr, is_absolute: $is_absolute:expr) => (
2041             {
2042                 let path = Path::new($path);
2043
2044                 let act_root = path.has_root();
2045                 assert!(act_root == $has_root, "has_root: Expected {:?}, found {:?}",
2046                         $has_root, act_root);
2047
2048                 let act_abs = path.is_absolute();
2049                 assert!(act_abs == $is_absolute, "is_absolute: Expected {:?}, found {:?}",
2050                         $is_absolute, act_abs);
2051             }
2052         );
2053
2054         ($path:expr, parent: $parent:expr, file_name: $file:expr) => (
2055             {
2056                 let path = Path::new($path);
2057
2058                 let parent = path.parent().map(|p| p.to_str().unwrap());
2059                 let exp_parent: Option<&str> = $parent;
2060                 assert!(parent == exp_parent, "parent: Expected {:?}, found {:?}",
2061                         exp_parent, parent);
2062
2063                 let file = path.file_name().map(|p| p.to_str().unwrap());
2064                 let exp_file: Option<&str> = $file;
2065                 assert!(file == exp_file, "file_name: Expected {:?}, found {:?}",
2066                         exp_file, file);
2067             }
2068         );
2069
2070         ($path:expr, file_stem: $file_stem:expr, extension: $extension:expr) => (
2071             {
2072                 let path = Path::new($path);
2073
2074                 let stem = path.file_stem().map(|p| p.to_str().unwrap());
2075                 let exp_stem: Option<&str> = $file_stem;
2076                 assert!(stem == exp_stem, "file_stem: Expected {:?}, found {:?}",
2077                         exp_stem, stem);
2078
2079                 let ext = path.extension().map(|p| p.to_str().unwrap());
2080                 let exp_ext: Option<&str> = $extension;
2081                 assert!(ext == exp_ext, "extension: Expected {:?}, found {:?}",
2082                         exp_ext, ext);
2083             }
2084         );
2085
2086         ($path:expr, iter: $iter:expr,
2087                      has_root: $has_root:expr, is_absolute: $is_absolute:expr,
2088                      parent: $parent:expr, file_name: $file:expr,
2089                      file_stem: $file_stem:expr, extension: $extension:expr) => (
2090             {
2091                 t!($path, iter: $iter);
2092                 t!($path, has_root: $has_root, is_absolute: $is_absolute);
2093                 t!($path, parent: $parent, file_name: $file);
2094                 t!($path, file_stem: $file_stem, extension: $extension);
2095             }
2096         );
2097     );
2098
2099     #[test]
2100     fn into_cow() {
2101         use borrow::{Cow, IntoCow};
2102
2103         let static_path = Path::new("/home/foo");
2104         let static_cow_path: Cow<'static, Path> = static_path.into_cow();
2105         let pathbuf = PathBuf::from("/home/foo");
2106
2107         {
2108             let path: &Path = &pathbuf;
2109             let borrowed_cow_path: Cow<Path> = path.into_cow();
2110
2111             assert_eq!(static_cow_path, borrowed_cow_path);
2112         }
2113
2114         let owned_cow_path: Cow<'static, Path> = pathbuf.into_cow();
2115
2116         assert_eq!(static_cow_path, owned_cow_path);
2117     }
2118
2119     #[test]
2120     fn into() {
2121         use borrow::Cow;
2122
2123         let static_path = Path::new("/home/foo");
2124         let static_cow_path: Cow<'static, Path> = static_path.into();
2125         let pathbuf = PathBuf::from("/home/foo");
2126
2127         {
2128             let path: &Path = &pathbuf;
2129             let borrowed_cow_path: Cow<Path> = path.into();
2130
2131             assert_eq!(static_cow_path, borrowed_cow_path);
2132         }
2133
2134         let owned_cow_path: Cow<'static, Path> = pathbuf.into();
2135
2136         assert_eq!(static_cow_path, owned_cow_path);
2137     }
2138
2139     #[test]
2140     #[cfg(unix)]
2141     pub fn test_decompositions_unix() {
2142         t!("",
2143            iter: [],
2144            has_root: false,
2145            is_absolute: false,
2146            parent: None,
2147            file_name: None,
2148            file_stem: None,
2149            extension: None
2150            );
2151
2152         t!("foo",
2153            iter: ["foo"],
2154            has_root: false,
2155            is_absolute: false,
2156            parent: Some(""),
2157            file_name: Some("foo"),
2158            file_stem: Some("foo"),
2159            extension: None
2160            );
2161
2162         t!("/",
2163            iter: ["/"],
2164            has_root: true,
2165            is_absolute: true,
2166            parent: None,
2167            file_name: None,
2168            file_stem: None,
2169            extension: None
2170            );
2171
2172         t!("/foo",
2173            iter: ["/", "foo"],
2174            has_root: true,
2175            is_absolute: true,
2176            parent: Some("/"),
2177            file_name: Some("foo"),
2178            file_stem: Some("foo"),
2179            extension: None
2180            );
2181
2182         t!("foo/",
2183            iter: ["foo"],
2184            has_root: false,
2185            is_absolute: false,
2186            parent: Some(""),
2187            file_name: Some("foo"),
2188            file_stem: Some("foo"),
2189            extension: None
2190            );
2191
2192         t!("/foo/",
2193            iter: ["/", "foo"],
2194            has_root: true,
2195            is_absolute: true,
2196            parent: Some("/"),
2197            file_name: Some("foo"),
2198            file_stem: Some("foo"),
2199            extension: None
2200            );
2201
2202         t!("foo/bar",
2203            iter: ["foo", "bar"],
2204            has_root: false,
2205            is_absolute: false,
2206            parent: Some("foo"),
2207            file_name: Some("bar"),
2208            file_stem: Some("bar"),
2209            extension: None
2210            );
2211
2212         t!("/foo/bar",
2213            iter: ["/", "foo", "bar"],
2214            has_root: true,
2215            is_absolute: true,
2216            parent: Some("/foo"),
2217            file_name: Some("bar"),
2218            file_stem: Some("bar"),
2219            extension: None
2220            );
2221
2222         t!("///foo///",
2223            iter: ["/", "foo"],
2224            has_root: true,
2225            is_absolute: true,
2226            parent: Some("/"),
2227            file_name: Some("foo"),
2228            file_stem: Some("foo"),
2229            extension: None
2230            );
2231
2232         t!("///foo///bar",
2233            iter: ["/", "foo", "bar"],
2234            has_root: true,
2235            is_absolute: true,
2236            parent: Some("///foo"),
2237            file_name: Some("bar"),
2238            file_stem: Some("bar"),
2239            extension: None
2240            );
2241
2242         t!("./.",
2243            iter: ["."],
2244            has_root: false,
2245            is_absolute: false,
2246            parent: Some(""),
2247            file_name: None,
2248            file_stem: None,
2249            extension: None
2250            );
2251
2252         t!("/..",
2253            iter: ["/", ".."],
2254            has_root: true,
2255            is_absolute: true,
2256            parent: Some("/"),
2257            file_name: None,
2258            file_stem: None,
2259            extension: None
2260            );
2261
2262         t!("../",
2263            iter: [".."],
2264            has_root: false,
2265            is_absolute: false,
2266            parent: Some(""),
2267            file_name: None,
2268            file_stem: None,
2269            extension: None
2270            );
2271
2272         t!("foo/.",
2273            iter: ["foo"],
2274            has_root: false,
2275            is_absolute: false,
2276            parent: Some(""),
2277            file_name: Some("foo"),
2278            file_stem: Some("foo"),
2279            extension: None
2280            );
2281
2282         t!("foo/..",
2283            iter: ["foo", ".."],
2284            has_root: false,
2285            is_absolute: false,
2286            parent: Some("foo"),
2287            file_name: None,
2288            file_stem: None,
2289            extension: None
2290            );
2291
2292         t!("foo/./",
2293            iter: ["foo"],
2294            has_root: false,
2295            is_absolute: false,
2296            parent: Some(""),
2297            file_name: Some("foo"),
2298            file_stem: Some("foo"),
2299            extension: None
2300            );
2301
2302         t!("foo/./bar",
2303            iter: ["foo", "bar"],
2304            has_root: false,
2305            is_absolute: false,
2306            parent: Some("foo"),
2307            file_name: Some("bar"),
2308            file_stem: Some("bar"),
2309            extension: None
2310            );
2311
2312         t!("foo/../",
2313            iter: ["foo", ".."],
2314            has_root: false,
2315            is_absolute: false,
2316            parent: Some("foo"),
2317            file_name: None,
2318            file_stem: None,
2319            extension: None
2320            );
2321
2322         t!("foo/../bar",
2323            iter: ["foo", "..", "bar"],
2324            has_root: false,
2325            is_absolute: false,
2326            parent: Some("foo/.."),
2327            file_name: Some("bar"),
2328            file_stem: Some("bar"),
2329            extension: None
2330            );
2331
2332         t!("./a",
2333            iter: [".", "a"],
2334            has_root: false,
2335            is_absolute: false,
2336            parent: Some("."),
2337            file_name: Some("a"),
2338            file_stem: Some("a"),
2339            extension: None
2340            );
2341
2342         t!(".",
2343            iter: ["."],
2344            has_root: false,
2345            is_absolute: false,
2346            parent: Some(""),
2347            file_name: None,
2348            file_stem: None,
2349            extension: None
2350            );
2351
2352         t!("./",
2353            iter: ["."],
2354            has_root: false,
2355            is_absolute: false,
2356            parent: Some(""),
2357            file_name: None,
2358            file_stem: None,
2359            extension: None
2360            );
2361
2362         t!("a/b",
2363            iter: ["a", "b"],
2364            has_root: false,
2365            is_absolute: false,
2366            parent: Some("a"),
2367            file_name: Some("b"),
2368            file_stem: Some("b"),
2369            extension: None
2370            );
2371
2372         t!("a//b",
2373            iter: ["a", "b"],
2374            has_root: false,
2375            is_absolute: false,
2376            parent: Some("a"),
2377            file_name: Some("b"),
2378            file_stem: Some("b"),
2379            extension: None
2380            );
2381
2382         t!("a/./b",
2383            iter: ["a", "b"],
2384            has_root: false,
2385            is_absolute: false,
2386            parent: Some("a"),
2387            file_name: Some("b"),
2388            file_stem: Some("b"),
2389            extension: None
2390            );
2391
2392         t!("a/b/c",
2393            iter: ["a", "b", "c"],
2394            has_root: false,
2395            is_absolute: false,
2396            parent: Some("a/b"),
2397            file_name: Some("c"),
2398            file_stem: Some("c"),
2399            extension: None
2400            );
2401
2402         t!(".foo",
2403            iter: [".foo"],
2404            has_root: false,
2405            is_absolute: false,
2406            parent: Some(""),
2407            file_name: Some(".foo"),
2408            file_stem: Some(".foo"),
2409            extension: None
2410            );
2411     }
2412
2413     #[test]
2414     #[cfg(windows)]
2415     pub fn test_decompositions_windows() {
2416         t!("",
2417            iter: [],
2418            has_root: false,
2419            is_absolute: false,
2420            parent: None,
2421            file_name: None,
2422            file_stem: None,
2423            extension: None
2424            );
2425
2426         t!("foo",
2427            iter: ["foo"],
2428            has_root: false,
2429            is_absolute: false,
2430            parent: Some(""),
2431            file_name: Some("foo"),
2432            file_stem: Some("foo"),
2433            extension: None
2434            );
2435
2436         t!("/",
2437            iter: ["\\"],
2438            has_root: true,
2439            is_absolute: false,
2440            parent: None,
2441            file_name: None,
2442            file_stem: None,
2443            extension: None
2444            );
2445
2446         t!("\\",
2447            iter: ["\\"],
2448            has_root: true,
2449            is_absolute: false,
2450            parent: None,
2451            file_name: None,
2452            file_stem: None,
2453            extension: None
2454            );
2455
2456         t!("c:",
2457            iter: ["c:"],
2458            has_root: false,
2459            is_absolute: false,
2460            parent: None,
2461            file_name: None,
2462            file_stem: None,
2463            extension: None
2464            );
2465
2466         t!("c:\\",
2467            iter: ["c:", "\\"],
2468            has_root: true,
2469            is_absolute: true,
2470            parent: None,
2471            file_name: None,
2472            file_stem: None,
2473            extension: None
2474            );
2475
2476         t!("c:/",
2477            iter: ["c:", "\\"],
2478            has_root: true,
2479            is_absolute: true,
2480            parent: None,
2481            file_name: None,
2482            file_stem: None,
2483            extension: None
2484            );
2485
2486         t!("/foo",
2487            iter: ["\\", "foo"],
2488            has_root: true,
2489            is_absolute: false,
2490            parent: Some("/"),
2491            file_name: Some("foo"),
2492            file_stem: Some("foo"),
2493            extension: None
2494            );
2495
2496         t!("foo/",
2497            iter: ["foo"],
2498            has_root: false,
2499            is_absolute: false,
2500            parent: Some(""),
2501            file_name: Some("foo"),
2502            file_stem: Some("foo"),
2503            extension: None
2504            );
2505
2506         t!("/foo/",
2507            iter: ["\\", "foo"],
2508            has_root: true,
2509            is_absolute: false,
2510            parent: Some("/"),
2511            file_name: Some("foo"),
2512            file_stem: Some("foo"),
2513            extension: None
2514            );
2515
2516         t!("foo/bar",
2517            iter: ["foo", "bar"],
2518            has_root: false,
2519            is_absolute: false,
2520            parent: Some("foo"),
2521            file_name: Some("bar"),
2522            file_stem: Some("bar"),
2523            extension: None
2524            );
2525
2526         t!("/foo/bar",
2527            iter: ["\\", "foo", "bar"],
2528            has_root: true,
2529            is_absolute: false,
2530            parent: Some("/foo"),
2531            file_name: Some("bar"),
2532            file_stem: Some("bar"),
2533            extension: None
2534            );
2535
2536         t!("///foo///",
2537            iter: ["\\", "foo"],
2538            has_root: true,
2539            is_absolute: false,
2540            parent: Some("/"),
2541            file_name: Some("foo"),
2542            file_stem: Some("foo"),
2543            extension: None
2544            );
2545
2546         t!("///foo///bar",
2547            iter: ["\\", "foo", "bar"],
2548            has_root: true,
2549            is_absolute: false,
2550            parent: Some("///foo"),
2551            file_name: Some("bar"),
2552            file_stem: Some("bar"),
2553            extension: None
2554            );
2555
2556         t!("./.",
2557            iter: ["."],
2558            has_root: false,
2559            is_absolute: false,
2560            parent: Some(""),
2561            file_name: None,
2562            file_stem: None,
2563            extension: None
2564            );
2565
2566         t!("/..",
2567            iter: ["\\", ".."],
2568            has_root: true,
2569            is_absolute: false,
2570            parent: Some("/"),
2571            file_name: None,
2572            file_stem: None,
2573            extension: None
2574            );
2575
2576         t!("../",
2577            iter: [".."],
2578            has_root: false,
2579            is_absolute: false,
2580            parent: Some(""),
2581            file_name: None,
2582            file_stem: None,
2583            extension: None
2584            );
2585
2586         t!("foo/.",
2587            iter: ["foo"],
2588            has_root: false,
2589            is_absolute: false,
2590            parent: Some(""),
2591            file_name: Some("foo"),
2592            file_stem: Some("foo"),
2593            extension: None
2594            );
2595
2596         t!("foo/..",
2597            iter: ["foo", ".."],
2598            has_root: false,
2599            is_absolute: false,
2600            parent: Some("foo"),
2601            file_name: None,
2602            file_stem: None,
2603            extension: None
2604            );
2605
2606         t!("foo/./",
2607            iter: ["foo"],
2608            has_root: false,
2609            is_absolute: false,
2610            parent: Some(""),
2611            file_name: Some("foo"),
2612            file_stem: Some("foo"),
2613            extension: None
2614            );
2615
2616         t!("foo/./bar",
2617            iter: ["foo", "bar"],
2618            has_root: false,
2619            is_absolute: false,
2620            parent: Some("foo"),
2621            file_name: Some("bar"),
2622            file_stem: Some("bar"),
2623            extension: None
2624            );
2625
2626         t!("foo/../",
2627            iter: ["foo", ".."],
2628            has_root: false,
2629            is_absolute: false,
2630            parent: Some("foo"),
2631            file_name: None,
2632            file_stem: None,
2633            extension: None
2634            );
2635
2636         t!("foo/../bar",
2637            iter: ["foo", "..", "bar"],
2638            has_root: false,
2639            is_absolute: false,
2640            parent: Some("foo/.."),
2641            file_name: Some("bar"),
2642            file_stem: Some("bar"),
2643            extension: None
2644            );
2645
2646         t!("./a",
2647            iter: [".", "a"],
2648            has_root: false,
2649            is_absolute: false,
2650            parent: Some("."),
2651            file_name: Some("a"),
2652            file_stem: Some("a"),
2653            extension: None
2654            );
2655
2656         t!(".",
2657            iter: ["."],
2658            has_root: false,
2659            is_absolute: false,
2660            parent: Some(""),
2661            file_name: None,
2662            file_stem: None,
2663            extension: None
2664            );
2665
2666         t!("./",
2667            iter: ["."],
2668            has_root: false,
2669            is_absolute: false,
2670            parent: Some(""),
2671            file_name: None,
2672            file_stem: None,
2673            extension: None
2674            );
2675
2676         t!("a/b",
2677            iter: ["a", "b"],
2678            has_root: false,
2679            is_absolute: false,
2680            parent: Some("a"),
2681            file_name: Some("b"),
2682            file_stem: Some("b"),
2683            extension: None
2684            );
2685
2686         t!("a//b",
2687            iter: ["a", "b"],
2688            has_root: false,
2689            is_absolute: false,
2690            parent: Some("a"),
2691            file_name: Some("b"),
2692            file_stem: Some("b"),
2693            extension: None
2694            );
2695
2696         t!("a/./b",
2697            iter: ["a", "b"],
2698            has_root: false,
2699            is_absolute: false,
2700            parent: Some("a"),
2701            file_name: Some("b"),
2702            file_stem: Some("b"),
2703            extension: None
2704            );
2705
2706         t!("a/b/c",
2707            iter: ["a", "b", "c"],
2708            has_root: false,
2709            is_absolute: false,
2710            parent: Some("a/b"),
2711            file_name: Some("c"),
2712            file_stem: Some("c"),
2713            extension: None);
2714
2715         t!("a\\b\\c",
2716            iter: ["a", "b", "c"],
2717            has_root: false,
2718            is_absolute: false,
2719            parent: Some("a\\b"),
2720            file_name: Some("c"),
2721            file_stem: Some("c"),
2722            extension: None
2723            );
2724
2725         t!("\\a",
2726            iter: ["\\", "a"],
2727            has_root: true,
2728            is_absolute: false,
2729            parent: Some("\\"),
2730            file_name: Some("a"),
2731            file_stem: Some("a"),
2732            extension: None
2733            );
2734
2735         t!("c:\\foo.txt",
2736            iter: ["c:", "\\", "foo.txt"],
2737            has_root: true,
2738            is_absolute: true,
2739            parent: Some("c:\\"),
2740            file_name: Some("foo.txt"),
2741            file_stem: Some("foo"),
2742            extension: Some("txt")
2743            );
2744
2745         t!("\\\\server\\share\\foo.txt",
2746            iter: ["\\\\server\\share", "\\", "foo.txt"],
2747            has_root: true,
2748            is_absolute: true,
2749            parent: Some("\\\\server\\share\\"),
2750            file_name: Some("foo.txt"),
2751            file_stem: Some("foo"),
2752            extension: Some("txt")
2753            );
2754
2755         t!("\\\\server\\share",
2756            iter: ["\\\\server\\share", "\\"],
2757            has_root: true,
2758            is_absolute: true,
2759            parent: None,
2760            file_name: None,
2761            file_stem: None,
2762            extension: None
2763            );
2764
2765         t!("\\\\server",
2766            iter: ["\\", "server"],
2767            has_root: true,
2768            is_absolute: false,
2769            parent: Some("\\"),
2770            file_name: Some("server"),
2771            file_stem: Some("server"),
2772            extension: None
2773            );
2774
2775         t!("\\\\?\\bar\\foo.txt",
2776            iter: ["\\\\?\\bar", "\\", "foo.txt"],
2777            has_root: true,
2778            is_absolute: true,
2779            parent: Some("\\\\?\\bar\\"),
2780            file_name: Some("foo.txt"),
2781            file_stem: Some("foo"),
2782            extension: Some("txt")
2783            );
2784
2785         t!("\\\\?\\bar",
2786            iter: ["\\\\?\\bar"],
2787            has_root: true,
2788            is_absolute: true,
2789            parent: None,
2790            file_name: None,
2791            file_stem: None,
2792            extension: None
2793            );
2794
2795         t!("\\\\?\\",
2796            iter: ["\\\\?\\"],
2797            has_root: true,
2798            is_absolute: true,
2799            parent: None,
2800            file_name: None,
2801            file_stem: None,
2802            extension: None
2803            );
2804
2805         t!("\\\\?\\UNC\\server\\share\\foo.txt",
2806            iter: ["\\\\?\\UNC\\server\\share", "\\", "foo.txt"],
2807            has_root: true,
2808            is_absolute: true,
2809            parent: Some("\\\\?\\UNC\\server\\share\\"),
2810            file_name: Some("foo.txt"),
2811            file_stem: Some("foo"),
2812            extension: Some("txt")
2813            );
2814
2815         t!("\\\\?\\UNC\\server",
2816            iter: ["\\\\?\\UNC\\server"],
2817            has_root: true,
2818            is_absolute: true,
2819            parent: None,
2820            file_name: None,
2821            file_stem: None,
2822            extension: None
2823            );
2824
2825         t!("\\\\?\\UNC\\",
2826            iter: ["\\\\?\\UNC\\"],
2827            has_root: true,
2828            is_absolute: true,
2829            parent: None,
2830            file_name: None,
2831            file_stem: None,
2832            extension: None
2833            );
2834
2835         t!("\\\\?\\C:\\foo.txt",
2836            iter: ["\\\\?\\C:", "\\", "foo.txt"],
2837            has_root: true,
2838            is_absolute: true,
2839            parent: Some("\\\\?\\C:\\"),
2840            file_name: Some("foo.txt"),
2841            file_stem: Some("foo"),
2842            extension: Some("txt")
2843            );
2844
2845
2846         t!("\\\\?\\C:\\",
2847            iter: ["\\\\?\\C:", "\\"],
2848            has_root: true,
2849            is_absolute: true,
2850            parent: None,
2851            file_name: None,
2852            file_stem: None,
2853            extension: None
2854            );
2855
2856
2857         t!("\\\\?\\C:",
2858            iter: ["\\\\?\\C:"],
2859            has_root: true,
2860            is_absolute: true,
2861            parent: None,
2862            file_name: None,
2863            file_stem: None,
2864            extension: None
2865            );
2866
2867
2868         t!("\\\\?\\foo/bar",
2869            iter: ["\\\\?\\foo/bar"],
2870            has_root: true,
2871            is_absolute: true,
2872            parent: None,
2873            file_name: None,
2874            file_stem: None,
2875            extension: None
2876            );
2877
2878
2879         t!("\\\\?\\C:/foo",
2880            iter: ["\\\\?\\C:/foo"],
2881            has_root: true,
2882            is_absolute: true,
2883            parent: None,
2884            file_name: None,
2885            file_stem: None,
2886            extension: None
2887            );
2888
2889
2890         t!("\\\\.\\foo\\bar",
2891            iter: ["\\\\.\\foo", "\\", "bar"],
2892            has_root: true,
2893            is_absolute: true,
2894            parent: Some("\\\\.\\foo\\"),
2895            file_name: Some("bar"),
2896            file_stem: Some("bar"),
2897            extension: None
2898            );
2899
2900
2901         t!("\\\\.\\foo",
2902            iter: ["\\\\.\\foo", "\\"],
2903            has_root: true,
2904            is_absolute: true,
2905            parent: None,
2906            file_name: None,
2907            file_stem: None,
2908            extension: None
2909            );
2910
2911
2912         t!("\\\\.\\foo/bar",
2913            iter: ["\\\\.\\foo/bar", "\\"],
2914            has_root: true,
2915            is_absolute: true,
2916            parent: None,
2917            file_name: None,
2918            file_stem: None,
2919            extension: None
2920            );
2921
2922
2923         t!("\\\\.\\foo\\bar/baz",
2924            iter: ["\\\\.\\foo", "\\", "bar", "baz"],
2925            has_root: true,
2926            is_absolute: true,
2927            parent: Some("\\\\.\\foo\\bar"),
2928            file_name: Some("baz"),
2929            file_stem: Some("baz"),
2930            extension: None
2931            );
2932
2933
2934         t!("\\\\.\\",
2935            iter: ["\\\\.\\", "\\"],
2936            has_root: true,
2937            is_absolute: true,
2938            parent: None,
2939            file_name: None,
2940            file_stem: None,
2941            extension: None
2942            );
2943
2944         t!("\\\\?\\a\\b\\",
2945            iter: ["\\\\?\\a", "\\", "b"],
2946            has_root: true,
2947            is_absolute: true,
2948            parent: Some("\\\\?\\a\\"),
2949            file_name: Some("b"),
2950            file_stem: Some("b"),
2951            extension: None
2952            );
2953     }
2954
2955     #[test]
2956     pub fn test_stem_ext() {
2957         t!("foo",
2958            file_stem: Some("foo"),
2959            extension: None
2960            );
2961
2962         t!("foo.",
2963            file_stem: Some("foo"),
2964            extension: Some("")
2965            );
2966
2967         t!(".foo",
2968            file_stem: Some(".foo"),
2969            extension: None
2970            );
2971
2972         t!("foo.txt",
2973            file_stem: Some("foo"),
2974            extension: Some("txt")
2975            );
2976
2977         t!("foo.bar.txt",
2978            file_stem: Some("foo.bar"),
2979            extension: Some("txt")
2980            );
2981
2982         t!("foo.bar.",
2983            file_stem: Some("foo.bar"),
2984            extension: Some("")
2985            );
2986
2987         t!(".",
2988            file_stem: None,
2989            extension: None
2990            );
2991
2992         t!("..",
2993            file_stem: None,
2994            extension: None
2995            );
2996
2997         t!("",
2998            file_stem: None,
2999            extension: None
3000            );
3001     }
3002
3003     #[test]
3004     pub fn test_push() {
3005         macro_rules! tp(
3006             ($path:expr, $push:expr, $expected:expr) => ( {
3007                 let mut actual = PathBuf::from($path);
3008                 actual.push($push);
3009                 assert!(actual.to_str() == Some($expected),
3010                         "pushing {:?} onto {:?}: Expected {:?}, got {:?}",
3011                         $push, $path, $expected, actual.to_str().unwrap());
3012             });
3013         );
3014
3015         if cfg!(unix) {
3016             tp!("", "foo", "foo");
3017             tp!("foo", "bar", "foo/bar");
3018             tp!("foo/", "bar", "foo/bar");
3019             tp!("foo//", "bar", "foo//bar");
3020             tp!("foo/.", "bar", "foo/./bar");
3021             tp!("foo./.", "bar", "foo././bar");
3022             tp!("foo", "", "foo/");
3023             tp!("foo", ".", "foo/.");
3024             tp!("foo", "..", "foo/..");
3025             tp!("foo", "/", "/");
3026             tp!("/foo/bar", "/", "/");
3027             tp!("/foo/bar", "/baz", "/baz");
3028             tp!("/foo/bar", "./baz", "/foo/bar/./baz");
3029         } else {
3030             tp!("", "foo", "foo");
3031             tp!("foo", "bar", r"foo\bar");
3032             tp!("foo/", "bar", r"foo/bar");
3033             tp!(r"foo\", "bar", r"foo\bar");
3034             tp!("foo//", "bar", r"foo//bar");
3035             tp!(r"foo\\", "bar", r"foo\\bar");
3036             tp!("foo/.", "bar", r"foo/.\bar");
3037             tp!("foo./.", "bar", r"foo./.\bar");
3038             tp!(r"foo\.", "bar", r"foo\.\bar");
3039             tp!(r"foo.\.", "bar", r"foo.\.\bar");
3040             tp!("foo", "", "foo\\");
3041             tp!("foo", ".", r"foo\.");
3042             tp!("foo", "..", r"foo\..");
3043             tp!("foo", "/", "/");
3044             tp!("foo", r"\", r"\");
3045             tp!("/foo/bar", "/", "/");
3046             tp!(r"\foo\bar", r"\", r"\");
3047             tp!("/foo/bar", "/baz", "/baz");
3048             tp!("/foo/bar", r"\baz", r"\baz");
3049             tp!("/foo/bar", "./baz", r"/foo/bar\./baz");
3050             tp!("/foo/bar", r".\baz", r"/foo/bar\.\baz");
3051
3052             tp!("c:\\", "windows", "c:\\windows");
3053             tp!("c:", "windows", "c:windows");
3054
3055             tp!("a\\b\\c", "d", "a\\b\\c\\d");
3056             tp!("\\a\\b\\c", "d", "\\a\\b\\c\\d");
3057             tp!("a\\b", "c\\d", "a\\b\\c\\d");
3058             tp!("a\\b", "\\c\\d", "\\c\\d");
3059             tp!("a\\b", ".", "a\\b\\.");
3060             tp!("a\\b", "..\\c", "a\\b\\..\\c");
3061             tp!("a\\b", "C:a.txt", "C:a.txt");
3062             tp!("a\\b", "C:\\a.txt", "C:\\a.txt");
3063             tp!("C:\\a", "C:\\b.txt", "C:\\b.txt");
3064             tp!("C:\\a\\b\\c", "C:d", "C:d");
3065             tp!("C:a\\b\\c", "C:d", "C:d");
3066             tp!("C:", r"a\b\c", r"C:a\b\c");
3067             tp!("C:", r"..\a", r"C:..\a");
3068             tp!("\\\\server\\share\\foo",
3069                 "bar",
3070                 "\\\\server\\share\\foo\\bar");
3071             tp!("\\\\server\\share\\foo", "C:baz", "C:baz");
3072             tp!("\\\\?\\C:\\a\\b", "C:c\\d", "C:c\\d");
3073             tp!("\\\\?\\C:a\\b", "C:c\\d", "C:c\\d");
3074             tp!("\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d");
3075             tp!("\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz");
3076             tp!("\\\\?\\UNC\\server\\share\\foo",
3077                 "bar",
3078                 "\\\\?\\UNC\\server\\share\\foo\\bar");
3079             tp!("\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a");
3080             tp!("\\\\?\\UNC\\server\\share", "C:a", "C:a");
3081
3082             // Note: modified from old path API
3083             tp!("\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\foo");
3084
3085             tp!("C:\\a",
3086                 "\\\\?\\UNC\\server\\share",
3087                 "\\\\?\\UNC\\server\\share");
3088             tp!("\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz");
3089             tp!("\\\\.\\foo\\bar", "C:a", "C:a");
3090             // again, not sure about the following, but I'm assuming \\.\ should be verbatim
3091             tp!("\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar");
3092
3093             tp!("\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
3094         }
3095     }
3096
3097     #[test]
3098     pub fn test_pop() {
3099         macro_rules! tp(
3100             ($path:expr, $expected:expr, $output:expr) => ( {
3101                 let mut actual = PathBuf::from($path);
3102                 let output = actual.pop();
3103                 assert!(actual.to_str() == Some($expected) && output == $output,
3104                         "popping from {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
3105                         $path, $expected, $output,
3106                         actual.to_str().unwrap(), output);
3107             });
3108         );
3109
3110         tp!("", "", false);
3111         tp!("/", "/", false);
3112         tp!("foo", "", true);
3113         tp!(".", "", true);
3114         tp!("/foo", "/", true);
3115         tp!("/foo/bar", "/foo", true);
3116         tp!("foo/bar", "foo", true);
3117         tp!("foo/.", "", true);
3118         tp!("foo//bar", "foo", true);
3119
3120         if cfg!(windows) {
3121             tp!("a\\b\\c", "a\\b", true);
3122             tp!("\\a", "\\", true);
3123             tp!("\\", "\\", false);
3124
3125             tp!("C:\\a\\b", "C:\\a", true);
3126             tp!("C:\\a", "C:\\", true);
3127             tp!("C:\\", "C:\\", false);
3128             tp!("C:a\\b", "C:a", true);
3129             tp!("C:a", "C:", true);
3130             tp!("C:", "C:", false);
3131             tp!("\\\\server\\share\\a\\b", "\\\\server\\share\\a", true);
3132             tp!("\\\\server\\share\\a", "\\\\server\\share\\", true);
3133             tp!("\\\\server\\share", "\\\\server\\share", false);
3134             tp!("\\\\?\\a\\b\\c", "\\\\?\\a\\b", true);
3135             tp!("\\\\?\\a\\b", "\\\\?\\a\\", true);
3136             tp!("\\\\?\\a", "\\\\?\\a", false);
3137             tp!("\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true);
3138             tp!("\\\\?\\C:\\a", "\\\\?\\C:\\", true);
3139             tp!("\\\\?\\C:\\", "\\\\?\\C:\\", false);
3140             tp!("\\\\?\\UNC\\server\\share\\a\\b",
3141                 "\\\\?\\UNC\\server\\share\\a",
3142                 true);
3143             tp!("\\\\?\\UNC\\server\\share\\a",
3144                 "\\\\?\\UNC\\server\\share\\",
3145                 true);
3146             tp!("\\\\?\\UNC\\server\\share",
3147                 "\\\\?\\UNC\\server\\share",
3148                 false);
3149             tp!("\\\\.\\a\\b\\c", "\\\\.\\a\\b", true);
3150             tp!("\\\\.\\a\\b", "\\\\.\\a\\", true);
3151             tp!("\\\\.\\a", "\\\\.\\a", false);
3152
3153             tp!("\\\\?\\a\\b\\", "\\\\?\\a\\", true);
3154         }
3155     }
3156
3157     #[test]
3158     pub fn test_set_file_name() {
3159         macro_rules! tfn(
3160                 ($path:expr, $file:expr, $expected:expr) => ( {
3161                 let mut p = PathBuf::from($path);
3162                 p.set_file_name($file);
3163                 assert!(p.to_str() == Some($expected),
3164                         "setting file name of {:?} to {:?}: Expected {:?}, got {:?}",
3165                         $path, $file, $expected,
3166                         p.to_str().unwrap());
3167             });
3168         );
3169
3170         tfn!("foo", "foo", "foo");
3171         tfn!("foo", "bar", "bar");
3172         tfn!("foo", "", "");
3173         tfn!("", "foo", "foo");
3174         if cfg!(unix) {
3175             tfn!(".", "foo", "./foo");
3176             tfn!("foo/", "bar", "bar");
3177             tfn!("foo/.", "bar", "bar");
3178             tfn!("..", "foo", "../foo");
3179             tfn!("foo/..", "bar", "foo/../bar");
3180             tfn!("/", "foo", "/foo");
3181         } else {
3182             tfn!(".", "foo", r".\foo");
3183             tfn!(r"foo\", "bar", r"bar");
3184             tfn!(r"foo\.", "bar", r"bar");
3185             tfn!("..", "foo", r"..\foo");
3186             tfn!(r"foo\..", "bar", r"foo\..\bar");
3187             tfn!(r"\", "foo", r"\foo");
3188         }
3189     }
3190
3191     #[test]
3192     pub fn test_set_extension() {
3193         macro_rules! tfe(
3194                 ($path:expr, $ext:expr, $expected:expr, $output:expr) => ( {
3195                 let mut p = PathBuf::from($path);
3196                 let output = p.set_extension($ext);
3197                 assert!(p.to_str() == Some($expected) && output == $output,
3198                         "setting extension of {:?} to {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
3199                         $path, $ext, $expected, $output,
3200                         p.to_str().unwrap(), output);
3201             });
3202         );
3203
3204         tfe!("foo", "txt", "foo.txt", true);
3205         tfe!("foo.bar", "txt", "foo.txt", true);
3206         tfe!("foo.bar.baz", "txt", "foo.bar.txt", true);
3207         tfe!(".test", "txt", ".test.txt", true);
3208         tfe!("foo.txt", "", "foo", true);
3209         tfe!("foo", "", "foo", true);
3210         tfe!("", "foo", "", false);
3211         tfe!(".", "foo", ".", false);
3212         tfe!("foo/", "bar", "foo.bar", true);
3213         tfe!("foo/.", "bar", "foo.bar", true);
3214         tfe!("..", "foo", "..", false);
3215         tfe!("foo/..", "bar", "foo/..", false);
3216         tfe!("/", "foo", "/", false);
3217     }
3218
3219     #[test]
3220     fn test_eq_recievers() {
3221         use borrow::Cow;
3222
3223         let borrowed: &Path = Path::new("foo/bar");
3224         let mut owned: PathBuf = PathBuf::new();
3225         owned.push("foo");
3226         owned.push("bar");
3227         let borrowed_cow: Cow<Path> = borrowed.into();
3228         let owned_cow: Cow<Path> = owned.clone().into();
3229
3230         macro_rules! t {
3231             ($($current:expr),+) => {
3232                 $(
3233                     assert_eq!($current, borrowed);
3234                     assert_eq!($current, owned);
3235                     assert_eq!($current, borrowed_cow);
3236                     assert_eq!($current, owned_cow);
3237                 )+
3238             }
3239         }
3240
3241         t!(borrowed, owned, borrowed_cow, owned_cow);
3242     }
3243
3244     #[test]
3245     pub fn test_compare() {
3246         use hash::{Hash, Hasher, SipHasher};
3247
3248         fn hash<T: Hash>(t: T) -> u64 {
3249             let mut s = SipHasher::new_with_keys(0, 0);
3250             t.hash(&mut s);
3251             s.finish()
3252         }
3253
3254         macro_rules! tc(
3255             ($path1:expr, $path2:expr, eq: $eq:expr,
3256              starts_with: $starts_with:expr, ends_with: $ends_with:expr,
3257              relative_from: $relative_from:expr) => ({
3258                  let path1 = Path::new($path1);
3259                  let path2 = Path::new($path2);
3260
3261                  let eq = path1 == path2;
3262                  assert!(eq == $eq, "{:?} == {:?}, expected {:?}, got {:?}",
3263                          $path1, $path2, $eq, eq);
3264                  assert!($eq == (hash(path1) == hash(path2)),
3265                          "{:?} == {:?}, expected {:?}, got {} and {}",
3266                          $path1, $path2, $eq, hash(path1), hash(path2));
3267
3268                  let starts_with = path1.starts_with(path2);
3269                  assert!(starts_with == $starts_with,
3270                          "{:?}.starts_with({:?}), expected {:?}, got {:?}", $path1, $path2,
3271                          $starts_with, starts_with);
3272
3273                  let ends_with = path1.ends_with(path2);
3274                  assert!(ends_with == $ends_with,
3275                          "{:?}.ends_with({:?}), expected {:?}, got {:?}", $path1, $path2,
3276                          $ends_with, ends_with);
3277
3278                  let relative_from = path1.relative_from(path2).map(|p| p.to_str().unwrap());
3279                  let exp: Option<&str> = $relative_from;
3280                  assert!(relative_from == exp,
3281                          "{:?}.relative_from({:?}), expected {:?}, got {:?}", $path1, $path2,
3282                          exp, relative_from);
3283             });
3284         );
3285
3286         tc!("", "",
3287             eq: true,
3288             starts_with: true,
3289             ends_with: true,
3290             relative_from: Some("")
3291             );
3292
3293         tc!("foo", "",
3294             eq: false,
3295             starts_with: true,
3296             ends_with: true,
3297             relative_from: Some("foo")
3298             );
3299
3300         tc!("", "foo",
3301             eq: false,
3302             starts_with: false,
3303             ends_with: false,
3304             relative_from: None
3305             );
3306
3307         tc!("foo", "foo",
3308             eq: true,
3309             starts_with: true,
3310             ends_with: true,
3311             relative_from: Some("")
3312             );
3313
3314         tc!("foo/", "foo",
3315             eq: true,
3316             starts_with: true,
3317             ends_with: true,
3318             relative_from: Some("")
3319             );
3320
3321         tc!("foo/bar", "foo",
3322             eq: false,
3323             starts_with: true,
3324             ends_with: false,
3325             relative_from: Some("bar")
3326             );
3327
3328         tc!("foo/bar/baz", "foo/bar",
3329             eq: false,
3330             starts_with: true,
3331             ends_with: false,
3332             relative_from: Some("baz")
3333             );
3334
3335         tc!("foo/bar", "foo/bar/baz",
3336             eq: false,
3337             starts_with: false,
3338             ends_with: false,
3339             relative_from: None
3340             );
3341
3342         tc!("./foo/bar/", ".",
3343             eq: false,
3344             starts_with: true,
3345             ends_with: false,
3346             relative_from: Some("foo/bar")
3347             );
3348
3349         if cfg!(windows) {
3350             tc!(r"C:\src\rust\cargo-test\test\Cargo.toml",
3351                 r"c:\src\rust\cargo-test\test",
3352                 eq: false,
3353                 starts_with: true,
3354                 ends_with: false,
3355                 relative_from: Some("Cargo.toml")
3356                 );
3357
3358             tc!(r"c:\foo", r"C:\foo",
3359                 eq: true,
3360                 starts_with: true,
3361                 ends_with: true,
3362                 relative_from: Some("")
3363                 );
3364         }
3365     }
3366 }