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