]> git.lizzy.rs Git - rust.git/blob - src/libstd/path/mod.rs
remove unnecessary parentheses from range notation
[rust.git] / src / libstd / path / mod.rs
1 // Copyright 2013 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 support
12 //!
13 //! This module implements support for two flavors of paths. `PosixPath` represents a path on any
14 //! unix-like system, whereas `WindowsPath` represents a path on Windows. This module also exposes
15 //! a typedef `Path` which is equal to the appropriate platform-specific path variant.
16 //!
17 //! Both `PosixPath` and `WindowsPath` implement a trait `GenericPath`, which contains the set of
18 //! methods that behave the same for both paths. They each also implement some methods that could
19 //! not be expressed in `GenericPath`, yet behave identically for both path flavors, such as
20 //! `.components()`.
21 //!
22 //! The three main design goals of this module are 1) to avoid unnecessary allocation, 2) to behave
23 //! the same regardless of which flavor of path is being used, and 3) to support paths that cannot
24 //! be represented in UTF-8 (as Linux has no restriction on paths beyond disallowing NUL).
25 //!
26 //! ## Usage
27 //!
28 //! Usage of this module is fairly straightforward. Unless writing platform-specific code, `Path`
29 //! should be used to refer to the platform-native path.
30 //!
31 //! Creation of a path is typically done with either `Path::new(some_str)` or
32 //! `Path::new(some_vec)`. This path can be modified with `.push()` and `.pop()` (and other
33 //! setters). The resulting Path can either be passed to another API that expects a path, or can be
34 //! turned into a `&[u8]` with `.as_vec()` or a `Option<&str>` with `.as_str()`. Similarly,
35 //! attributes of the path can be queried with methods such as `.filename()`. There are also
36 //! methods that return a new path instead of modifying the receiver, such as `.join()` or
37 //! `.dir_path()`.
38 //!
39 //! Paths are always kept in normalized form. This means that creating the path
40 //! `Path::new("a/b/../c")` will return the path `a/c`. Similarly any attempt to mutate the path
41 //! will always leave it in normalized form.
42 //!
43 //! When rendering a path to some form of output, there is a method `.display()` which is
44 //! compatible with the `format!()` parameter `{}`. This will render the path as a string,
45 //! replacing all non-utf8 sequences with the Replacement Character (U+FFFD). As such it is not
46 //! suitable for passing to any API that actually operates on the path; it is only intended for
47 //! display.
48 //!
49 //! ## Example
50 //!
51 //! ```rust
52 //! use std::io::fs::PathExtensions;
53 //!
54 //! let mut path = Path::new("/tmp/path");
55 //! println!("path: {}", path.display());
56 //! path.set_filename("foo");
57 //! path.push("bar");
58 //! println!("new path: {}", path.display());
59 //! println!("path exists: {}", path.exists());
60 //! ```
61
62 #![unstable]
63
64 use core::marker::Sized;
65 use ffi::CString;
66 use clone::Clone;
67 use fmt;
68 use iter::IteratorExt;
69 use option::Option;
70 use option::Option::{None, Some};
71 use ops::FullRange;
72 use str;
73 use str::StrExt;
74 use string::{String, CowString};
75 use slice::SliceExt;
76 use vec::Vec;
77
78 /// Typedef for POSIX file paths.
79 /// See `posix::Path` for more info.
80 pub use self::posix::Path as PosixPath;
81
82 /// Typedef for Windows file paths.
83 /// See `windows::Path` for more info.
84 pub use self::windows::Path as WindowsPath;
85
86 /// Typedef for the platform-native path type
87 #[cfg(unix)]
88 pub use self::posix::Path as Path;
89 /// Typedef for the platform-native path type
90 #[cfg(windows)]
91 pub use self::windows::Path as Path;
92
93 /// Typedef for the platform-native component iterator
94 #[cfg(unix)]
95 pub use self::posix::Components as Components;
96 /// Typedef for the platform-native component iterator
97 #[cfg(windows)]
98 pub use self::windows::Components as Components;
99
100 /// Typedef for the platform-native str component iterator
101 #[cfg(unix)]
102 pub use self::posix::StrComponents as StrComponents;
103 /// Typedef for the platform-native str component iterator
104 #[cfg(windows)]
105 pub use self::windows::StrComponents as StrComponents;
106
107 /// Alias for the platform-native separator character.
108 #[cfg(unix)]
109 pub use self::posix::SEP as SEP;
110 /// Alias for the platform-native separator character.
111 #[cfg(windows)]
112 pub use self::windows::SEP as SEP;
113
114 /// Alias for the platform-native separator byte.
115 #[cfg(unix)]
116 pub use self::posix::SEP_BYTE as SEP_BYTE;
117 /// Alias for the platform-native separator byte.
118 #[cfg(windows)]
119 pub use self::windows::SEP_BYTE as SEP_BYTE;
120
121 /// Typedef for the platform-native separator char func
122 #[cfg(unix)]
123 pub use self::posix::is_sep as is_sep;
124 /// Typedef for the platform-native separator char func
125 #[cfg(windows)]
126 pub use self::windows::is_sep as is_sep;
127 /// Typedef for the platform-native separator byte func
128 #[cfg(unix)]
129 pub use self::posix::is_sep_byte as is_sep_byte;
130 /// Typedef for the platform-native separator byte func
131 #[cfg(windows)]
132 pub use self::windows::is_sep_byte as is_sep_byte;
133
134 pub mod posix;
135 pub mod windows;
136
137 /// A trait that represents the generic operations available on paths
138 pub trait GenericPath: Clone + GenericPathUnsafe {
139     /// Creates a new Path from a byte vector or string.
140     /// The resulting Path will always be normalized.
141     ///
142     /// # Example
143     ///
144     /// ```
145     /// # foo();
146     /// # #[cfg(windows)] fn foo() {}
147     /// # #[cfg(unix)] fn foo() {
148     /// let path = Path::new("foo/bar");
149     /// # }
150     /// ```
151     ///
152     /// # Panics
153     ///
154     /// Panics the task if the path contains a NUL.
155     ///
156     /// See individual Path impls for additional restrictions.
157     #[inline]
158     fn new<T: BytesContainer>(path: T) -> Self {
159         assert!(!contains_nul(&path));
160         unsafe { GenericPathUnsafe::new_unchecked(path) }
161     }
162
163     /// Creates a new Path from a byte vector or string, if possible.
164     /// The resulting Path will always be normalized.
165     ///
166     /// # Example
167     ///
168     /// ```
169     /// # foo();
170     /// # #[cfg(windows)] fn foo() {}
171     /// # #[cfg(unix)] fn foo() {
172     /// let x: &[u8] = b"foo\0";
173     /// assert!(Path::new_opt(x).is_none());
174     /// # }
175     /// ```
176     #[inline]
177     fn new_opt<T: BytesContainer>(path: T) -> Option<Self> {
178         if contains_nul(&path) {
179             None
180         } else {
181             Some(unsafe { GenericPathUnsafe::new_unchecked(path) })
182         }
183     }
184
185     /// Returns the path as a string, if possible.
186     /// If the path is not representable in utf-8, this returns None.
187     ///
188     /// # Example
189     ///
190     /// ```
191     /// # foo();
192     /// # #[cfg(windows)] fn foo() {}
193     /// # #[cfg(unix)] fn foo() {
194     /// let p = Path::new("/abc/def");
195     /// assert_eq!(p.as_str(), Some("/abc/def"));
196     /// # }
197     /// ```
198     #[inline]
199     fn as_str<'a>(&'a self) -> Option<&'a str> {
200         str::from_utf8(self.as_vec()).ok()
201     }
202
203     /// Returns the path as a byte vector
204     ///
205     /// # Example
206     ///
207     /// ```
208     /// # foo();
209     /// # #[cfg(windows)] fn foo() {}
210     /// # #[cfg(unix)] fn foo() {
211     /// let p = Path::new("abc/def");
212     /// assert_eq!(p.as_vec(), b"abc/def");
213     /// # }
214     /// ```
215     fn as_vec<'a>(&'a self) -> &'a [u8];
216
217     /// Converts the Path into an owned byte vector
218     ///
219     /// # Example
220     ///
221     /// ```
222     /// # foo();
223     /// # #[cfg(windows)] fn foo() {}
224     /// # #[cfg(unix)] fn foo() {
225     /// let p = Path::new("abc/def");
226     /// assert_eq!(p.into_vec(), b"abc/def".to_vec());
227     /// // attempting to use p now results in "error: use of moved value"
228     /// # }
229     /// ```
230     fn into_vec(self) -> Vec<u8>;
231
232     /// Returns an object that implements `Show` for printing paths
233     ///
234     /// # Example
235     ///
236     /// ```
237     /// # foo();
238     /// # #[cfg(windows)] fn foo() {}
239     /// # #[cfg(unix)] fn foo() {
240     /// let p = Path::new("abc/def");
241     /// println!("{}", p.display()); // prints "abc/def"
242     /// # }
243     /// ```
244     fn display<'a>(&'a self) -> Display<'a, Self> {
245         Display{ path: self, filename: false }
246     }
247
248     /// Returns an object that implements `Show` for printing filenames
249     ///
250     /// If there is no filename, nothing will be printed.
251     ///
252     /// # Example
253     ///
254     /// ```
255     /// # foo();
256     /// # #[cfg(windows)] fn foo() {}
257     /// # #[cfg(unix)] fn foo() {
258     /// let p = Path::new("abc/def");
259     /// println!("{}", p.filename_display()); // prints "def"
260     /// # }
261     /// ```
262     fn filename_display<'a>(&'a self) -> Display<'a, Self> {
263         Display{ path: self, filename: true }
264     }
265
266     /// Returns the directory component of `self`, as a byte vector (with no trailing separator).
267     /// If `self` has no directory component, returns ['.'].
268     ///
269     /// # Example
270     ///
271     /// ```
272     /// # foo();
273     /// # #[cfg(windows)] fn foo() {}
274     /// # #[cfg(unix)] fn foo() {
275     /// let p = Path::new("abc/def/ghi");
276     /// assert_eq!(p.dirname(), b"abc/def");
277     /// # }
278     /// ```
279     fn dirname<'a>(&'a self) -> &'a [u8];
280
281     /// Returns the directory component of `self`, as a string, if possible.
282     /// See `dirname` for details.
283     ///
284     /// # Example
285     ///
286     /// ```
287     /// # foo();
288     /// # #[cfg(windows)] fn foo() {}
289     /// # #[cfg(unix)] fn foo() {
290     /// let p = Path::new("abc/def/ghi");
291     /// assert_eq!(p.dirname_str(), Some("abc/def"));
292     /// # }
293     /// ```
294     #[inline]
295     fn dirname_str<'a>(&'a self) -> Option<&'a str> {
296         str::from_utf8(self.dirname()).ok()
297     }
298
299     /// Returns the file component of `self`, as a byte vector.
300     /// If `self` represents the root of the file hierarchy, returns None.
301     /// If `self` is "." or "..", returns None.
302     ///
303     /// # Example
304     ///
305     /// ```
306     /// # foo();
307     /// # #[cfg(windows)] fn foo() {}
308     /// # #[cfg(unix)] fn foo() {
309     /// let p = Path::new("abc/def/ghi");
310     /// assert_eq!(p.filename(), Some(b"ghi"));
311     /// # }
312     /// ```
313     fn filename<'a>(&'a self) -> Option<&'a [u8]>;
314
315     /// Returns the file component of `self`, as a string, if possible.
316     /// See `filename` for details.
317     ///
318     /// # Example
319     ///
320     /// ```
321     /// # foo();
322     /// # #[cfg(windows)] fn foo() {}
323     /// # #[cfg(unix)] fn foo() {
324     /// let p = Path::new("abc/def/ghi");
325     /// assert_eq!(p.filename_str(), Some("ghi"));
326     /// # }
327     /// ```
328     #[inline]
329     fn filename_str<'a>(&'a self) -> Option<&'a str> {
330         self.filename().and_then(|s| str::from_utf8(s).ok())
331     }
332
333     /// Returns the stem of the filename of `self`, as a byte vector.
334     /// The stem is the portion of the filename just before the last '.'.
335     /// If there is no '.', the entire filename is returned.
336     ///
337     /// # Example
338     ///
339     /// ```
340     /// # foo();
341     /// # #[cfg(windows)] fn foo() {}
342     /// # #[cfg(unix)] fn foo() {
343     /// let p = Path::new("/abc/def.txt");
344     /// assert_eq!(p.filestem(), Some(b"def"));
345     /// # }
346     /// ```
347     fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
348         match self.filename() {
349             None => None,
350             Some(name) => Some({
351                 let dot = b'.';
352                 match name.rposition_elem(&dot) {
353                     None | Some(0) => name,
354                     Some(1) if name == b".." => name,
355                     Some(pos) => &name[..pos]
356                 }
357             })
358         }
359     }
360
361     /// Returns the stem of the filename of `self`, as a string, if possible.
362     /// See `filestem` for details.
363     ///
364     /// # Example
365     ///
366     /// ```
367     /// # foo();
368     /// # #[cfg(windows)] fn foo() {}
369     /// # #[cfg(unix)] fn foo() {
370     /// let p = Path::new("/abc/def.txt");
371     /// assert_eq!(p.filestem_str(), Some("def"));
372     /// # }
373     /// ```
374     #[inline]
375     fn filestem_str<'a>(&'a self) -> Option<&'a str> {
376         self.filestem().and_then(|s| str::from_utf8(s).ok())
377     }
378
379     /// Returns the extension of the filename of `self`, as an optional byte vector.
380     /// The extension is the portion of the filename just after the last '.'.
381     /// If there is no extension, None is returned.
382     /// If the filename ends in '.', the empty vector is returned.
383     ///
384     /// # Example
385     ///
386     /// ```
387     /// # foo();
388     /// # #[cfg(windows)] fn foo() {}
389     /// # #[cfg(unix)] fn foo() {
390     /// let p = Path::new("abc/def.txt");
391     /// assert_eq!(p.extension(), Some(b"txt"));
392     /// # }
393     /// ```
394     fn extension<'a>(&'a self) -> Option<&'a [u8]> {
395         match self.filename() {
396             None => None,
397             Some(name) => {
398                 let dot = b'.';
399                 match name.rposition_elem(&dot) {
400                     None | Some(0) => None,
401                     Some(1) if name == b".." => None,
402                     Some(pos) => Some(&name[pos+1..])
403                 }
404             }
405         }
406     }
407
408     /// Returns the extension of the filename of `self`, as a string, if possible.
409     /// See `extension` for details.
410     ///
411     /// # Example
412     ///
413     /// ```
414     /// # foo();
415     /// # #[cfg(windows)] fn foo() {}
416     /// # #[cfg(unix)] fn foo() {
417     /// let p = Path::new("abc/def.txt");
418     /// assert_eq!(p.extension_str(), Some("txt"));
419     /// # }
420     /// ```
421     #[inline]
422     fn extension_str<'a>(&'a self) -> Option<&'a str> {
423         self.extension().and_then(|s| str::from_utf8(s).ok())
424     }
425
426     /// Replaces the filename portion of the path with the given byte vector or string.
427     /// If the replacement name is [], this is equivalent to popping the path.
428     ///
429     /// # Example
430     ///
431     /// ```
432     /// # foo();
433     /// # #[cfg(windows)] fn foo() {}
434     /// # #[cfg(unix)] fn foo() {
435     /// let mut p = Path::new("abc/def.txt");
436     /// p.set_filename("foo.dat");
437     /// assert!(p == Path::new("abc/foo.dat"));
438     /// # }
439     /// ```
440     ///
441     /// # Panics
442     ///
443     /// Panics the task if the filename contains a NUL.
444     #[inline]
445     fn set_filename<T: BytesContainer>(&mut self, filename: T) {
446         assert!(!contains_nul(&filename));
447         unsafe { self.set_filename_unchecked(filename) }
448     }
449
450     /// Replaces the extension with the given byte vector or string.
451     /// If there is no extension in `self`, this adds one.
452     /// If the argument is [] or "", this removes the extension.
453     /// If `self` has no filename, this is a no-op.
454     ///
455     /// # Example
456     ///
457     /// ```
458     /// # foo();
459     /// # #[cfg(windows)] fn foo() {}
460     /// # #[cfg(unix)] fn foo() {
461     /// let mut p = Path::new("abc/def.txt");
462     /// p.set_extension("csv");
463     /// assert_eq!(p, Path::new("abc/def.csv"));
464     /// # }
465     /// ```
466     ///
467     /// # Panics
468     ///
469     /// Panics the task if the extension contains a NUL.
470     fn set_extension<T: BytesContainer>(&mut self, extension: T) {
471         assert!(!contains_nul(&extension));
472
473         let val = self.filename().and_then(|name| {
474             let dot = b'.';
475             let extlen = extension.container_as_bytes().len();
476             match (name.rposition_elem(&dot), extlen) {
477                 (None, 0) | (Some(0), 0) => None,
478                 (Some(idx), 0) => Some(name[..idx].to_vec()),
479                 (idx, extlen) => {
480                     let idx = match idx {
481                         None | Some(0) => name.len(),
482                         Some(val) => val
483                     };
484
485                     let mut v;
486                     v = Vec::with_capacity(idx + extlen + 1);
487                     v.push_all(&name[..idx]);
488                     v.push(dot);
489                     v.push_all(extension.container_as_bytes());
490                     Some(v)
491                 }
492             }
493         });
494
495         match val {
496             None => (),
497             Some(v) => unsafe { self.set_filename_unchecked(v) }
498         }
499     }
500
501     /// Returns a new Path constructed by replacing the filename with the given
502     /// byte vector or string.
503     /// See `set_filename` for details.
504     ///
505     /// # Example
506     ///
507     /// ```
508     /// # foo();
509     /// # #[cfg(windows)] fn foo() {}
510     /// # #[cfg(unix)] fn foo() {
511     /// let mut p = Path::new("abc/def.txt");
512     /// assert_eq!(p.with_filename("foo.dat"), Path::new("abc/foo.dat"));
513     /// # }
514     /// ```
515     ///
516     /// # Panics
517     ///
518     /// Panics the task if the filename contains a NUL.
519     #[inline]
520     fn with_filename<T: BytesContainer>(&self, filename: T) -> Self {
521         let mut p = self.clone();
522         p.set_filename(filename);
523         p
524     }
525
526     /// Returns a new Path constructed by setting the extension to the given
527     /// byte vector or string.
528     /// See `set_extension` for details.
529     ///
530     /// # Example
531     ///
532     /// ```
533     /// # foo();
534     /// # #[cfg(windows)] fn foo() {}
535     /// # #[cfg(unix)] fn foo() {
536     /// let mut p = Path::new("abc/def.txt");
537     /// assert_eq!(p.with_extension("csv"), Path::new("abc/def.csv"));
538     /// # }
539     /// ```
540     ///
541     /// # Panics
542     ///
543     /// Panics the task if the extension contains a NUL.
544     #[inline]
545     fn with_extension<T: BytesContainer>(&self, extension: T) -> Self {
546         let mut p = self.clone();
547         p.set_extension(extension);
548         p
549     }
550
551     /// Returns the directory component of `self`, as a Path.
552     /// If `self` represents the root of the filesystem hierarchy, returns `self`.
553     ///
554     /// # Example
555     ///
556     /// ```
557     /// # foo();
558     /// # #[cfg(windows)] fn foo() {}
559     /// # #[cfg(unix)] fn foo() {
560     /// let p = Path::new("abc/def/ghi");
561     /// assert_eq!(p.dir_path(), Path::new("abc/def"));
562     /// # }
563     /// ```
564     fn dir_path(&self) -> Self {
565         // self.dirname() returns a NUL-free vector
566         unsafe { GenericPathUnsafe::new_unchecked(self.dirname()) }
567     }
568
569     /// Returns a Path that represents the filesystem root that `self` is rooted in.
570     ///
571     /// If `self` is not absolute, or vol/cwd-relative in the case of Windows, this returns None.
572     ///
573     /// # Example
574     ///
575     /// ```
576     /// # foo();
577     /// # #[cfg(windows)] fn foo() {}
578     /// # #[cfg(unix)] fn foo() {
579     /// assert_eq!(Path::new("abc/def").root_path(), None);
580     /// assert_eq!(Path::new("/abc/def").root_path(), Some(Path::new("/")));
581     /// # }
582     /// ```
583     fn root_path(&self) -> Option<Self>;
584
585     /// Pushes a path (as a byte vector or string) onto `self`.
586     /// If the argument represents an absolute path, it replaces `self`.
587     ///
588     /// # Example
589     ///
590     /// ```
591     /// # foo();
592     /// # #[cfg(windows)] fn foo() {}
593     /// # #[cfg(unix)] fn foo() {
594     /// let mut p = Path::new("foo/bar");
595     /// p.push("baz.txt");
596     /// assert_eq!(p, Path::new("foo/bar/baz.txt"));
597     /// # }
598     /// ```
599     ///
600     /// # Panics
601     ///
602     /// Panics the task if the path contains a NUL.
603     #[inline]
604     fn push<T: BytesContainer>(&mut self, path: T) {
605         assert!(!contains_nul(&path));
606         unsafe { self.push_unchecked(path) }
607     }
608
609     /// Pushes multiple paths (as byte vectors or strings) onto `self`.
610     /// See `push` for details.
611     ///
612     /// # Example
613     ///
614     /// ```
615     /// # foo();
616     /// # #[cfg(windows)] fn foo() {}
617     /// # #[cfg(unix)] fn foo() {
618     /// let mut p = Path::new("foo");
619     /// p.push_many(&["bar", "baz.txt"]);
620     /// assert_eq!(p, Path::new("foo/bar/baz.txt"));
621     /// # }
622     /// ```
623     #[inline]
624     fn push_many<T: BytesContainer>(&mut self, paths: &[T]) {
625         let t: Option<&T> = None;
626         if BytesContainer::is_str(t) {
627             for p in paths.iter() {
628                 self.push(p.container_as_str().unwrap())
629             }
630         } else {
631             for p in paths.iter() {
632                 self.push(p.container_as_bytes())
633             }
634         }
635     }
636
637     /// Removes the last path component from the receiver.
638     /// Returns `true` if the receiver was modified, or `false` if it already
639     /// represented the root of the file hierarchy.
640     ///
641     /// # Example
642     ///
643     /// ```
644     /// # foo();
645     /// # #[cfg(windows)] fn foo() {}
646     /// # #[cfg(unix)] fn foo() {
647     /// let mut p = Path::new("foo/bar/baz.txt");
648     /// p.pop();
649     /// assert_eq!(p, Path::new("foo/bar"));
650     /// # }
651     /// ```
652     fn pop(&mut self) -> bool;
653
654     /// Returns a new Path constructed by joining `self` with the given path
655     /// (as a byte vector or string).
656     /// If the given path is absolute, the new Path will represent just that.
657     ///
658     /// # Example
659     ///
660     /// ```
661     /// # foo();
662     /// # #[cfg(windows)] fn foo() {}
663     /// # #[cfg(unix)] fn foo() {
664     /// let p = Path::new("/foo");
665     /// assert_eq!(p.join("bar.txt"), Path::new("/foo/bar.txt"));
666     /// # }
667     /// ```
668     ///
669     /// # Panics
670     ///
671     /// Panics the task if the path contains a NUL.
672     #[inline]
673     fn join<T: BytesContainer>(&self, path: T) -> Self {
674         let mut p = self.clone();
675         p.push(path);
676         p
677     }
678
679     /// Returns a new Path constructed by joining `self` with the given paths
680     /// (as byte vectors or strings).
681     /// See `join` for details.
682     ///
683     /// # Example
684     ///
685     /// ```
686     /// # foo();
687     /// # #[cfg(windows)] fn foo() {}
688     /// # #[cfg(unix)] fn foo() {
689     /// let p = Path::new("foo");
690     /// let fbbq = Path::new("foo/bar/baz/quux.txt");
691     /// assert_eq!(p.join_many(&["bar", "baz", "quux.txt"]), fbbq);
692     /// # }
693     /// ```
694     #[inline]
695     fn join_many<T: BytesContainer>(&self, paths: &[T]) -> Self {
696         let mut p = self.clone();
697         p.push_many(paths);
698         p
699     }
700
701     /// Returns whether `self` represents an absolute path.
702     /// An absolute path is defined as one that, when joined to another path, will
703     /// yield back the same absolute path.
704     ///
705     /// # Example
706     ///
707     /// ```
708     /// # foo();
709     /// # #[cfg(windows)] fn foo() {}
710     /// # #[cfg(unix)] fn foo() {
711     /// let p = Path::new("/abc/def");
712     /// assert!(p.is_absolute());
713     /// # }
714     /// ```
715     fn is_absolute(&self) -> bool;
716
717     /// Returns whether `self` represents a relative path.
718     /// Typically this is the inverse of `is_absolute`.
719     /// But for Windows paths, it also means the path is not volume-relative or
720     /// relative to the current working directory.
721     ///
722     /// # Example
723     ///
724     /// ```
725     /// # foo();
726     /// # #[cfg(windows)] fn foo() {}
727     /// # #[cfg(unix)] fn foo() {
728     /// let p = Path::new("abc/def");
729     /// assert!(p.is_relative());
730     /// # }
731     /// ```
732     fn is_relative(&self) -> bool {
733         !self.is_absolute()
734     }
735
736     /// Returns whether `self` is equal to, or is an ancestor of, the given path.
737     /// If both paths are relative, they are compared as though they are relative
738     /// to the same parent path.
739     ///
740     /// # Example
741     ///
742     /// ```
743     /// # foo();
744     /// # #[cfg(windows)] fn foo() {}
745     /// # #[cfg(unix)] fn foo() {
746     /// let p = Path::new("foo/bar/baz/quux.txt");
747     /// let fb = Path::new("foo/bar");
748     /// let bq = Path::new("baz/quux.txt");
749     /// assert!(fb.is_ancestor_of(&p));
750     /// # }
751     /// ```
752     fn is_ancestor_of(&self, other: &Self) -> bool;
753
754     /// Returns the Path that, were it joined to `base`, would yield `self`.
755     /// If no such path exists, None is returned.
756     /// If `self` is absolute and `base` is relative, or on Windows if both
757     /// paths refer to separate drives, an absolute path is returned.
758     ///
759     /// # Example
760     ///
761     /// ```
762     /// # foo();
763     /// # #[cfg(windows)] fn foo() {}
764     /// # #[cfg(unix)] fn foo() {
765     /// let p = Path::new("foo/bar/baz/quux.txt");
766     /// let fb = Path::new("foo/bar");
767     /// let bq = Path::new("baz/quux.txt");
768     /// assert_eq!(p.path_relative_from(&fb), Some(bq));
769     /// # }
770     /// ```
771     fn path_relative_from(&self, base: &Self) -> Option<Self>;
772
773     /// Returns whether the relative path `child` is a suffix of `self`.
774     ///
775     /// # Example
776     ///
777     /// ```
778     /// # foo();
779     /// # #[cfg(windows)] fn foo() {}
780     /// # #[cfg(unix)] fn foo() {
781     /// let p = Path::new("foo/bar/baz/quux.txt");
782     /// let bq = Path::new("baz/quux.txt");
783     /// assert!(p.ends_with_path(&bq));
784     /// # }
785     /// ```
786     fn ends_with_path(&self, child: &Self) -> bool;
787 }
788
789 /// A trait that represents something bytes-like (e.g. a &[u8] or a &str)
790 pub trait BytesContainer {
791     /// Returns a &[u8] representing the receiver
792     fn container_as_bytes<'a>(&'a self) -> &'a [u8];
793     /// Returns the receiver interpreted as a utf-8 string, if possible
794     #[inline]
795     fn container_as_str<'a>(&'a self) -> Option<&'a str> {
796         str::from_utf8(self.container_as_bytes()).ok()
797     }
798     /// Returns whether .container_as_str() is guaranteed to not fail
799     // FIXME (#8888): Remove unused arg once ::<for T> works
800     #[inline]
801     fn is_str(_: Option<&Self>) -> bool { false }
802 }
803
804 /// A trait that represents the unsafe operations on GenericPaths
805 pub trait GenericPathUnsafe {
806     /// Creates a new Path without checking for null bytes.
807     /// The resulting Path will always be normalized.
808     unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Self;
809
810     /// Replaces the filename portion of the path without checking for null
811     /// bytes.
812     /// See `set_filename` for details.
813     unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T);
814
815     /// Pushes a path onto `self` without checking for null bytes.
816     /// See `push` for details.
817     unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T);
818 }
819
820 /// Helper struct for printing paths with format!()
821 pub struct Display<'a, P:'a> {
822     path: &'a P,
823     filename: bool
824 }
825
826 impl<'a, P: GenericPath> fmt::Show for Display<'a, P> {
827     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
828         fmt::String::fmt(self, f)
829     }
830 }
831
832 impl<'a, P: GenericPath> fmt::String for Display<'a, P> {
833     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
834         self.as_cow().fmt(f)
835     }
836 }
837
838 impl<'a, P: GenericPath> Display<'a, P> {
839     /// Returns the path as a possibly-owned string.
840     ///
841     /// If the path is not UTF-8, invalid sequences will be replaced with the
842     /// Unicode replacement char. This involves allocation.
843     #[inline]
844     pub fn as_cow(&self) -> CowString<'a> {
845         String::from_utf8_lossy(if self.filename {
846             match self.path.filename() {
847                 None => {
848                     let result: &[u8] = &[];
849                     result
850                 }
851                 Some(v) => v
852             }
853         } else {
854             self.path.as_vec()
855         })
856     }
857 }
858
859 impl BytesContainer for str {
860     #[inline]
861     fn container_as_bytes(&self) -> &[u8] {
862         self.as_bytes()
863     }
864     #[inline]
865     fn container_as_str(&self) -> Option<&str> {
866         Some(self)
867     }
868     #[inline]
869     fn is_str(_: Option<&str>) -> bool { true }
870 }
871
872 impl BytesContainer for String {
873     #[inline]
874     fn container_as_bytes(&self) -> &[u8] {
875         self.as_bytes()
876     }
877     #[inline]
878     fn container_as_str(&self) -> Option<&str> {
879         Some(&self[])
880     }
881     #[inline]
882     fn is_str(_: Option<&String>) -> bool { true }
883 }
884
885 impl BytesContainer for [u8] {
886     #[inline]
887     fn container_as_bytes(&self) -> &[u8] {
888         self
889     }
890 }
891
892 impl BytesContainer for Vec<u8> {
893     #[inline]
894     fn container_as_bytes(&self) -> &[u8] {
895         &self[]
896     }
897 }
898
899 impl BytesContainer for CString {
900     #[inline]
901     fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
902         self.as_bytes()
903     }
904 }
905
906 impl<'a, T: ?Sized + BytesContainer> BytesContainer for &'a T {
907     #[inline]
908     fn container_as_bytes(&self) -> &[u8] {
909         (**self).container_as_bytes()
910     }
911     #[inline]
912     fn container_as_str(&self) -> Option<&str> {
913         (**self).container_as_str()
914     }
915     #[inline]
916     fn is_str(_: Option<& &'a T>) -> bool { BytesContainer::is_str(None::<&T>) }
917 }
918
919 #[inline(always)]
920 fn contains_nul<T: BytesContainer>(v: &T) -> bool {
921     v.container_as_bytes().iter().any(|&x| x == 0)
922 }