]> git.proxmox.com Git - rustc.git/blob - src/libstd/path.rs
New upstream version 1.35.0+dfsg1
[rustc.git] / src / libstd / path.rs
1 //! Cross-platform path manipulation.
2 //!
3 //! This module provides two types, [`PathBuf`] and [`Path`][`Path`] (akin to [`String`]
4 //! and [`str`]), for working with paths abstractly. These types are thin wrappers
5 //! around [`OsString`] and [`OsStr`] respectively, meaning that they work directly
6 //! on strings according to the local platform's path syntax.
7 //!
8 //! Paths can be parsed into [`Component`]s by iterating over the structure
9 //! returned by the [`components`] method on [`Path`]. [`Component`]s roughly
10 //! correspond to the substrings between path separators (`/` or `\`). You can
11 //! reconstruct an equivalent path from components with the [`push`] method on
12 //! [`PathBuf`]; note that the paths may differ syntactically by the
13 //! normalization described in the documentation for the [`components`] method.
14 //!
15 //! ## Simple usage
16 //!
17 //! Path manipulation includes both parsing components from slices and building
18 //! new owned paths.
19 //!
20 //! To parse a path, you can create a [`Path`] slice from a [`str`]
21 //! slice and start asking questions:
22 //!
23 //! ```
24 //! use std::path::Path;
25 //! use std::ffi::OsStr;
26 //!
27 //! let path = Path::new("/tmp/foo/bar.txt");
28 //!
29 //! let parent = path.parent();
30 //! assert_eq!(parent, Some(Path::new("/tmp/foo")));
31 //!
32 //! let file_stem = path.file_stem();
33 //! assert_eq!(file_stem, Some(OsStr::new("bar")));
34 //!
35 //! let extension = path.extension();
36 //! assert_eq!(extension, Some(OsStr::new("txt")));
37 //! ```
38 //!
39 //! To build or modify paths, use [`PathBuf`]:
40 //!
41 //! ```
42 //! use std::path::PathBuf;
43 //!
44 //! // This way works...
45 //! let mut path = PathBuf::from("c:\\");
46 //!
47 //! path.push("windows");
48 //! path.push("system32");
49 //!
50 //! path.set_extension("dll");
51 //!
52 //! // ... but push is best used if you don't know everything up
53 //! // front. If you do, this way is better:
54 //! let path: PathBuf = ["c:\\", "windows", "system32.dll"].iter().collect();
55 //! ```
56 //!
57 //! [`Component`]: ../../std/path/enum.Component.html
58 //! [`components`]: ../../std/path/struct.Path.html#method.components
59 //! [`PathBuf`]: ../../std/path/struct.PathBuf.html
60 //! [`Path`]: ../../std/path/struct.Path.html
61 //! [`push`]: ../../std/path/struct.PathBuf.html#method.push
62 //! [`String`]: ../../std/string/struct.String.html
63 //!
64 //! [`str`]: ../../std/primitive.str.html
65 //! [`OsString`]: ../../std/ffi/struct.OsString.html
66 //! [`OsStr`]: ../../std/ffi/struct.OsStr.html
67
68 #![stable(feature = "rust1", since = "1.0.0")]
69
70 use crate::borrow::{Borrow, Cow};
71 use crate::cmp;
72 use crate::error::Error;
73 use crate::fmt;
74 use crate::fs;
75 use crate::hash::{Hash, Hasher};
76 use crate::io;
77 use crate::iter::{self, FusedIterator};
78 use crate::ops::{self, Deref};
79 use crate::rc::Rc;
80 use crate::str::FromStr;
81 use crate::sync::Arc;
82
83 use crate::ffi::{OsStr, OsString};
84
85 use crate::sys::path::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
86
87 ////////////////////////////////////////////////////////////////////////////////
88 // GENERAL NOTES
89 ////////////////////////////////////////////////////////////////////////////////
90 //
91 // Parsing in this module is done by directly transmuting OsStr to [u8] slices,
92 // taking advantage of the fact that OsStr always encodes ASCII characters
93 // as-is. Eventually, this transmutation should be replaced by direct uses of
94 // OsStr APIs for parsing, but it will take a while for those to become
95 // available.
96
97 ////////////////////////////////////////////////////////////////////////////////
98 // Windows Prefixes
99 ////////////////////////////////////////////////////////////////////////////////
100
101 /// Windows path prefixes, e.g., `C:` or `\\server\share`.
102 ///
103 /// Windows uses a variety of path prefix styles, including references to drive
104 /// volumes (like `C:`), network shared folders (like `\\server\share`), and
105 /// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with
106 /// `\\?\`), in which case `/` is *not* treated as a separator and essentially
107 /// no normalization is performed.
108 ///
109 /// # Examples
110 ///
111 /// ```
112 /// use std::path::{Component, Path, Prefix};
113 /// use std::path::Prefix::*;
114 /// use std::ffi::OsStr;
115 ///
116 /// fn get_path_prefix(s: &str) -> Prefix {
117 /// let path = Path::new(s);
118 /// match path.components().next().unwrap() {
119 /// Component::Prefix(prefix_component) => prefix_component.kind(),
120 /// _ => panic!(),
121 /// }
122 /// }
123 ///
124 /// # if cfg!(windows) {
125 /// assert_eq!(Verbatim(OsStr::new("pictures")),
126 /// get_path_prefix(r"\\?\pictures\kittens"));
127 /// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")),
128 /// get_path_prefix(r"\\?\UNC\server\share"));
129 /// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\"));
130 /// assert_eq!(DeviceNS(OsStr::new("BrainInterface")),
131 /// get_path_prefix(r"\\.\BrainInterface"));
132 /// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")),
133 /// get_path_prefix(r"\\server\share"));
134 /// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));
135 /// # }
136 /// ```
137 #[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
138 #[stable(feature = "rust1", since = "1.0.0")]
139 pub enum Prefix<'a> {
140 /// Verbatim prefix, e.g., `\\?\cat_pics`.
141 ///
142 /// Verbatim prefixes consist of `\\?\` immediately followed by the given
143 /// component.
144 #[stable(feature = "rust1", since = "1.0.0")]
145 Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
146
147 /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_,
148 /// e.g., `\\?\UNC\server\share`.
149 ///
150 /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the
151 /// server's hostname and a share name.
152 #[stable(feature = "rust1", since = "1.0.0")]
153 VerbatimUNC(
154 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
155 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
156 ),
157
158 /// Verbatim disk prefix, e.g., `\\?\C:\`.
159 ///
160 /// Verbatim disk prefixes consist of `\\?\` immediately followed by the
161 /// drive letter and `:\`.
162 #[stable(feature = "rust1", since = "1.0.0")]
163 VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),
164
165 /// Device namespace prefix, e.g., `\\.\COM42`.
166 ///
167 /// Device namespace prefixes consist of `\\.\` immediately followed by the
168 /// device name.
169 #[stable(feature = "rust1", since = "1.0.0")]
170 DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
171
172 /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g.
173 /// `\\server\share`.
174 ///
175 /// UNC prefixes consist of the server's hostname and a share name.
176 #[stable(feature = "rust1", since = "1.0.0")]
177 UNC(
178 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
179 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
180 ),
181
182 /// Prefix `C:` for the given disk drive.
183 #[stable(feature = "rust1", since = "1.0.0")]
184 Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),
185 }
186
187 impl<'a> Prefix<'a> {
188 #[inline]
189 fn len(&self) -> usize {
190 use self::Prefix::*;
191 fn os_str_len(s: &OsStr) -> usize {
192 os_str_as_u8_slice(s).len()
193 }
194 match *self {
195 Verbatim(x) => 4 + os_str_len(x),
196 VerbatimUNC(x, y) => {
197 8 + os_str_len(x) +
198 if os_str_len(y) > 0 {
199 1 + os_str_len(y)
200 } else {
201 0
202 }
203 },
204 VerbatimDisk(_) => 6,
205 UNC(x, y) => {
206 2 + os_str_len(x) +
207 if os_str_len(y) > 0 {
208 1 + os_str_len(y)
209 } else {
210 0
211 }
212 },
213 DeviceNS(x) => 4 + os_str_len(x),
214 Disk(_) => 2,
215 }
216
217 }
218
219 /// Determines if the prefix is verbatim, i.e., begins with `\\?\`.
220 ///
221 /// # Examples
222 ///
223 /// ```
224 /// use std::path::Prefix::*;
225 /// use std::ffi::OsStr;
226 ///
227 /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim());
228 /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
229 /// assert!(VerbatimDisk(b'C').is_verbatim());
230 /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim());
231 /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
232 /// assert!(!Disk(b'C').is_verbatim());
233 /// ```
234 #[inline]
235 #[stable(feature = "rust1", since = "1.0.0")]
236 pub fn is_verbatim(&self) -> bool {
237 use self::Prefix::*;
238 match *self {
239 Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..) => true,
240 _ => false,
241 }
242 }
243
244 #[inline]
245 fn is_drive(&self) -> bool {
246 match *self {
247 Prefix::Disk(_) => true,
248 _ => false,
249 }
250 }
251
252 #[inline]
253 fn has_implicit_root(&self) -> bool {
254 !self.is_drive()
255 }
256 }
257
258 ////////////////////////////////////////////////////////////////////////////////
259 // Exposed parsing helpers
260 ////////////////////////////////////////////////////////////////////////////////
261
262 /// Determines whether the character is one of the permitted path
263 /// separators for the current platform.
264 ///
265 /// # Examples
266 ///
267 /// ```
268 /// use std::path;
269 ///
270 /// assert!(path::is_separator('/')); // '/' works for both Unix and Windows
271 /// assert!(!path::is_separator('❤'));
272 /// ```
273 #[stable(feature = "rust1", since = "1.0.0")]
274 pub fn is_separator(c: char) -> bool {
275 c.is_ascii() && is_sep_byte(c as u8)
276 }
277
278 /// The primary separator of path components for the current platform.
279 ///
280 /// For example, `/` on Unix and `\` on Windows.
281 #[stable(feature = "rust1", since = "1.0.0")]
282 pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
283
284 ////////////////////////////////////////////////////////////////////////////////
285 // Misc helpers
286 ////////////////////////////////////////////////////////////////////////////////
287
288 // Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
289 // is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
290 // `iter` after having exhausted `prefix`.
291 fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
292 where I: Iterator<Item = Component<'a>> + Clone,
293 J: Iterator<Item = Component<'b>>,
294 {
295 loop {
296 let mut iter_next = iter.clone();
297 match (iter_next.next(), prefix.next()) {
298 (Some(ref x), Some(ref y)) if x == y => (),
299 (Some(_), Some(_)) => return None,
300 (Some(_), None) => return Some(iter),
301 (None, None) => return Some(iter),
302 (None, Some(_)) => return None,
303 }
304 iter = iter_next;
305 }
306 }
307
308 // See note at the top of this module to understand why these are used:
309 fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
310 unsafe { &*(s as *const OsStr as *const [u8]) }
311 }
312 unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
313 &*(s as *const [u8] as *const OsStr)
314 }
315
316 // Detect scheme on Redox
317 fn has_redox_scheme(s: &[u8]) -> bool {
318 cfg!(target_os = "redox") && s.split(|b| *b == b'/').next().unwrap_or(b"").contains(&b':')
319 }
320
321 ////////////////////////////////////////////////////////////////////////////////
322 // Cross-platform, iterator-independent parsing
323 ////////////////////////////////////////////////////////////////////////////////
324
325 /// Says whether the first byte after the prefix is a separator.
326 fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
327 let path = if let Some(p) = prefix {
328 &s[p.len()..]
329 } else {
330 s
331 };
332 !path.is_empty() && is_sep_byte(path[0])
333 }
334
335 // basic workhorse for splitting stem and extension
336 fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
337 unsafe {
338 if os_str_as_u8_slice(file) == b".." {
339 return (Some(file), None);
340 }
341
342 // The unsafety here stems from converting between &OsStr and &[u8]
343 // and back. This is safe to do because (1) we only look at ASCII
344 // contents of the encoding and (2) new &OsStr values are produced
345 // only from ASCII-bounded slices of existing &OsStr values.
346
347 let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
348 let after = iter.next();
349 let before = iter.next();
350 if before == Some(b"") {
351 (Some(file), None)
352 } else {
353 (before.map(|s| u8_slice_as_os_str(s)),
354 after.map(|s| u8_slice_as_os_str(s)))
355 }
356 }
357 }
358
359 ////////////////////////////////////////////////////////////////////////////////
360 // The core iterators
361 ////////////////////////////////////////////////////////////////////////////////
362
363 /// Component parsing works by a double-ended state machine; the cursors at the
364 /// front and back of the path each keep track of what parts of the path have
365 /// been consumed so far.
366 ///
367 /// Going front to back, a path is made up of a prefix, a starting
368 /// directory component, and a body (of normal components)
369 #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
370 enum State {
371 Prefix = 0, // c:
372 StartDir = 1, // / or . or nothing
373 Body = 2, // foo/bar/baz
374 Done = 3,
375 }
376
377 /// A structure wrapping a Windows path prefix as well as its unparsed string
378 /// representation.
379 ///
380 /// In addition to the parsed [`Prefix`] information returned by [`kind`],
381 /// `PrefixComponent` also holds the raw and unparsed [`OsStr`] slice,
382 /// returned by [`as_os_str`].
383 ///
384 /// Instances of this `struct` can be obtained by matching against the
385 /// [`Prefix` variant] on [`Component`].
386 ///
387 /// Does not occur on Unix.
388 ///
389 /// # Examples
390 ///
391 /// ```
392 /// # if cfg!(windows) {
393 /// use std::path::{Component, Path, Prefix};
394 /// use std::ffi::OsStr;
395 ///
396 /// let path = Path::new(r"c:\you\later\");
397 /// match path.components().next().unwrap() {
398 /// Component::Prefix(prefix_component) => {
399 /// assert_eq!(Prefix::Disk(b'C'), prefix_component.kind());
400 /// assert_eq!(OsStr::new("c:"), prefix_component.as_os_str());
401 /// }
402 /// _ => unreachable!(),
403 /// }
404 /// # }
405 /// ```
406 ///
407 /// [`as_os_str`]: #method.as_os_str
408 /// [`Component`]: enum.Component.html
409 /// [`kind`]: #method.kind
410 /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
411 /// [`Prefix` variant]: enum.Component.html#variant.Prefix
412 /// [`Prefix`]: enum.Prefix.html
413 #[stable(feature = "rust1", since = "1.0.0")]
414 #[derive(Copy, Clone, Eq, Debug)]
415 pub struct PrefixComponent<'a> {
416 /// The prefix as an unparsed `OsStr` slice.
417 raw: &'a OsStr,
418
419 /// The parsed prefix data.
420 parsed: Prefix<'a>,
421 }
422
423 impl<'a> PrefixComponent<'a> {
424 /// Returns the parsed prefix data.
425 ///
426 /// See [`Prefix`]'s documentation for more information on the different
427 /// kinds of prefixes.
428 ///
429 /// [`Prefix`]: enum.Prefix.html
430 #[stable(feature = "rust1", since = "1.0.0")]
431 pub fn kind(&self) -> Prefix<'a> {
432 self.parsed
433 }
434
435 /// Returns the raw [`OsStr`] slice for this prefix.
436 ///
437 /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
438 #[stable(feature = "rust1", since = "1.0.0")]
439 pub fn as_os_str(&self) -> &'a OsStr {
440 self.raw
441 }
442 }
443
444 #[stable(feature = "rust1", since = "1.0.0")]
445 impl<'a> cmp::PartialEq for PrefixComponent<'a> {
446 fn eq(&self, other: &PrefixComponent<'a>) -> bool {
447 cmp::PartialEq::eq(&self.parsed, &other.parsed)
448 }
449 }
450
451 #[stable(feature = "rust1", since = "1.0.0")]
452 impl<'a> cmp::PartialOrd for PrefixComponent<'a> {
453 fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> {
454 cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed)
455 }
456 }
457
458 #[stable(feature = "rust1", since = "1.0.0")]
459 impl cmp::Ord for PrefixComponent<'_> {
460 fn cmp(&self, other: &Self) -> cmp::Ordering {
461 cmp::Ord::cmp(&self.parsed, &other.parsed)
462 }
463 }
464
465 #[stable(feature = "rust1", since = "1.0.0")]
466 impl Hash for PrefixComponent<'_> {
467 fn hash<H: Hasher>(&self, h: &mut H) {
468 self.parsed.hash(h);
469 }
470 }
471
472 /// A single component of a path.
473 ///
474 /// A `Component` roughly corresponds to a substring between path separators
475 /// (`/` or `\`).
476 ///
477 /// This `enum` is created by iterating over [`Components`], which in turn is
478 /// created by the [`components`][`Path::components`] method on [`Path`].
479 ///
480 /// # Examples
481 ///
482 /// ```rust
483 /// use std::path::{Component, Path};
484 ///
485 /// let path = Path::new("/tmp/foo/bar.txt");
486 /// let components = path.components().collect::<Vec<_>>();
487 /// assert_eq!(&components, &[
488 /// Component::RootDir,
489 /// Component::Normal("tmp".as_ref()),
490 /// Component::Normal("foo".as_ref()),
491 /// Component::Normal("bar.txt".as_ref()),
492 /// ]);
493 /// ```
494 ///
495 /// [`Components`]: struct.Components.html
496 /// [`Path`]: struct.Path.html
497 /// [`Path::components`]: struct.Path.html#method.components
498 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
499 #[stable(feature = "rust1", since = "1.0.0")]
500 pub enum Component<'a> {
501 /// A Windows path prefix, e.g., `C:` or `\\server\share`.
502 ///
503 /// There is a large variety of prefix types, see [`Prefix`]'s documentation
504 /// for more.
505 ///
506 /// Does not occur on Unix.
507 ///
508 /// [`Prefix`]: enum.Prefix.html
509 #[stable(feature = "rust1", since = "1.0.0")]
510 Prefix(
511 #[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>
512 ),
513
514 /// The root directory component, appears after any prefix and before anything else.
515 ///
516 /// It represents a separator that designates that a path starts from root.
517 #[stable(feature = "rust1", since = "1.0.0")]
518 RootDir,
519
520 /// A reference to the current directory, i.e., `.`.
521 #[stable(feature = "rust1", since = "1.0.0")]
522 CurDir,
523
524 /// A reference to the parent directory, i.e., `..`.
525 #[stable(feature = "rust1", since = "1.0.0")]
526 ParentDir,
527
528 /// A normal component, e.g., `a` and `b` in `a/b`.
529 ///
530 /// This variant is the most common one, it represents references to files
531 /// or directories.
532 #[stable(feature = "rust1", since = "1.0.0")]
533 Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
534 }
535
536 impl<'a> Component<'a> {
537 /// Extracts the underlying [`OsStr`] slice.
538 ///
539 /// # Examples
540 ///
541 /// ```
542 /// use std::path::Path;
543 ///
544 /// let path = Path::new("./tmp/foo/bar.txt");
545 /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();
546 /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
547 /// ```
548 ///
549 /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
550 #[stable(feature = "rust1", since = "1.0.0")]
551 pub fn as_os_str(self) -> &'a OsStr {
552 match self {
553 Component::Prefix(p) => p.as_os_str(),
554 Component::RootDir => OsStr::new(MAIN_SEP_STR),
555 Component::CurDir => OsStr::new("."),
556 Component::ParentDir => OsStr::new(".."),
557 Component::Normal(path) => path,
558 }
559 }
560 }
561
562 #[stable(feature = "rust1", since = "1.0.0")]
563 impl AsRef<OsStr> for Component<'_> {
564 fn as_ref(&self) -> &OsStr {
565 self.as_os_str()
566 }
567 }
568
569 #[stable(feature = "path_component_asref", since = "1.25.0")]
570 impl AsRef<Path> for Component<'_> {
571 fn as_ref(&self) -> &Path {
572 self.as_os_str().as_ref()
573 }
574 }
575
576 /// An iterator over the [`Component`]s of a [`Path`].
577 ///
578 /// This `struct` is created by the [`components`] method on [`Path`].
579 /// See its documentation for more.
580 ///
581 /// # Examples
582 ///
583 /// ```
584 /// use std::path::Path;
585 ///
586 /// let path = Path::new("/tmp/foo/bar.txt");
587 ///
588 /// for component in path.components() {
589 /// println!("{:?}", component);
590 /// }
591 /// ```
592 ///
593 /// [`Component`]: enum.Component.html
594 /// [`components`]: struct.Path.html#method.components
595 /// [`Path`]: struct.Path.html
596 #[derive(Clone)]
597 #[stable(feature = "rust1", since = "1.0.0")]
598 pub struct Components<'a> {
599 // The path left to parse components from
600 path: &'a [u8],
601
602 // The prefix as it was originally parsed, if any
603 prefix: Option<Prefix<'a>>,
604
605 // true if path *physically* has a root separator; for most Windows
606 // prefixes, it may have a "logical" rootseparator for the purposes of
607 // normalization, e.g., \\server\share == \\server\share\.
608 has_physical_root: bool,
609
610 // The iterator is double-ended, and these two states keep track of what has
611 // been produced from either end
612 front: State,
613 back: State,
614 }
615
616 /// An iterator over the [`Component`]s of a [`Path`], as [`OsStr`] slices.
617 ///
618 /// This `struct` is created by the [`iter`] method on [`Path`].
619 /// See its documentation for more.
620 ///
621 /// [`Component`]: enum.Component.html
622 /// [`iter`]: struct.Path.html#method.iter
623 /// [`OsStr`]: ../../std/ffi/struct.OsStr.html
624 /// [`Path`]: struct.Path.html
625 #[derive(Clone)]
626 #[stable(feature = "rust1", since = "1.0.0")]
627 pub struct Iter<'a> {
628 inner: Components<'a>,
629 }
630
631 #[stable(feature = "path_components_debug", since = "1.13.0")]
632 impl fmt::Debug for Components<'_> {
633 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
634 struct DebugHelper<'a>(&'a Path);
635
636 impl fmt::Debug for DebugHelper<'_> {
637 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
638 f.debug_list()
639 .entries(self.0.components())
640 .finish()
641 }
642 }
643
644 f.debug_tuple("Components")
645 .field(&DebugHelper(self.as_path()))
646 .finish()
647 }
648 }
649
650 impl<'a> Components<'a> {
651 // how long is the prefix, if any?
652 #[inline]
653 fn prefix_len(&self) -> usize {
654 self.prefix.as_ref().map(Prefix::len).unwrap_or(0)
655 }
656
657 #[inline]
658 fn prefix_verbatim(&self) -> bool {
659 self.prefix.as_ref().map(Prefix::is_verbatim).unwrap_or(false)
660 }
661
662 /// how much of the prefix is left from the point of view of iteration?
663 #[inline]
664 fn prefix_remaining(&self) -> usize {
665 if self.front == State::Prefix {
666 self.prefix_len()
667 } else {
668 0
669 }
670 }
671
672 // Given the iteration so far, how much of the pre-State::Body path is left?
673 #[inline]
674 fn len_before_body(&self) -> usize {
675 let root = if self.front <= State::StartDir && self.has_physical_root {
676 1
677 } else {
678 0
679 };
680 let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() {
681 1
682 } else {
683 0
684 };
685 self.prefix_remaining() + root + cur_dir
686 }
687
688 // is the iteration complete?
689 #[inline]
690 fn finished(&self) -> bool {
691 self.front == State::Done || self.back == State::Done || self.front > self.back
692 }
693
694 #[inline]
695 fn is_sep_byte(&self, b: u8) -> bool {
696 if self.prefix_verbatim() {
697 is_verbatim_sep(b)
698 } else {
699 is_sep_byte(b)
700 }
701 }
702
703 /// Extracts a slice corresponding to the portion of the path remaining for iteration.
704 ///
705 /// # Examples
706 ///
707 /// ```
708 /// use std::path::Path;
709 ///
710 /// let mut components = Path::new("/tmp/foo/bar.txt").components();
711 /// components.next();
712 /// components.next();
713 ///
714 /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());
715 /// ```
716 #[stable(feature = "rust1", since = "1.0.0")]
717 pub fn as_path(&self) -> &'a Path {
718 let mut comps = self.clone();
719 if comps.front == State::Body {
720 comps.trim_left();
721 }
722 if comps.back == State::Body {
723 comps.trim_right();
724 }
725 unsafe { Path::from_u8_slice(comps.path) }
726 }
727
728 /// Is the *original* path rooted?
729 fn has_root(&self) -> bool {
730 if self.has_physical_root {
731 return true;
732 }
733 if let Some(p) = self.prefix {
734 if p.has_implicit_root() {
735 return true;
736 }
737 }
738 false
739 }
740
741 /// Should the normalized path include a leading . ?
742 fn include_cur_dir(&self) -> bool {
743 if self.has_root() {
744 return false;
745 }
746 let mut iter = self.path[self.prefix_len()..].iter();
747 match (iter.next(), iter.next()) {
748 (Some(&b'.'), None) => true,
749 (Some(&b'.'), Some(&b)) => self.is_sep_byte(b),
750 _ => false,
751 }
752 }
753
754 // parse a given byte sequence into the corresponding path component
755 fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
756 match comp {
757 b"." if self.prefix_verbatim() => Some(Component::CurDir),
758 b"." => None, // . components are normalized away, except at
759 // the beginning of a path, which is treated
760 // separately via `include_cur_dir`
761 b".." => Some(Component::ParentDir),
762 b"" => None,
763 _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })),
764 }
765 }
766
767 // parse a component from the left, saying how many bytes to consume to
768 // remove the component
769 fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {
770 debug_assert!(self.front == State::Body);
771 let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) {
772 None => (0, self.path),
773 Some(i) => (1, &self.path[..i]),
774 };
775 (comp.len() + extra, self.parse_single_component(comp))
776 }
777
778 // parse a component from the right, saying how many bytes to consume to
779 // remove the component
780 fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {
781 debug_assert!(self.back == State::Body);
782 let start = self.len_before_body();
783 let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) {
784 None => (0, &self.path[start..]),
785 Some(i) => (1, &self.path[start + i + 1..]),
786 };
787 (comp.len() + extra, self.parse_single_component(comp))
788 }
789
790 // trim away repeated separators (i.e., empty components) on the left
791 fn trim_left(&mut self) {
792 while !self.path.is_empty() {
793 let (size, comp) = self.parse_next_component();
794 if comp.is_some() {
795 return;
796 } else {
797 self.path = &self.path[size..];
798 }
799 }
800 }
801
802 // trim away repeated separators (i.e., empty components) on the right
803 fn trim_right(&mut self) {
804 while self.path.len() > self.len_before_body() {
805 let (size, comp) = self.parse_next_component_back();
806 if comp.is_some() {
807 return;
808 } else {
809 self.path = &self.path[..self.path.len() - size];
810 }
811 }
812 }
813 }
814
815 #[stable(feature = "rust1", since = "1.0.0")]
816 impl AsRef<Path> for Components<'_> {
817 fn as_ref(&self) -> &Path {
818 self.as_path()
819 }
820 }
821
822 #[stable(feature = "rust1", since = "1.0.0")]
823 impl AsRef<OsStr> for Components<'_> {
824 fn as_ref(&self) -> &OsStr {
825 self.as_path().as_os_str()
826 }
827 }
828
829 #[stable(feature = "path_iter_debug", since = "1.13.0")]
830 impl fmt::Debug for Iter<'_> {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 struct DebugHelper<'a>(&'a Path);
833
834 impl fmt::Debug for DebugHelper<'_> {
835 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
836 f.debug_list()
837 .entries(self.0.iter())
838 .finish()
839 }
840 }
841
842 f.debug_tuple("Iter")
843 .field(&DebugHelper(self.as_path()))
844 .finish()
845 }
846 }
847
848 impl<'a> Iter<'a> {
849 /// Extracts a slice corresponding to the portion of the path remaining for iteration.
850 ///
851 /// # Examples
852 ///
853 /// ```
854 /// use std::path::Path;
855 ///
856 /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();
857 /// iter.next();
858 /// iter.next();
859 ///
860 /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());
861 /// ```
862 #[stable(feature = "rust1", since = "1.0.0")]
863 pub fn as_path(&self) -> &'a Path {
864 self.inner.as_path()
865 }
866 }
867
868 #[stable(feature = "rust1", since = "1.0.0")]
869 impl AsRef<Path> for Iter<'_> {
870 fn as_ref(&self) -> &Path {
871 self.as_path()
872 }
873 }
874
875 #[stable(feature = "rust1", since = "1.0.0")]
876 impl AsRef<OsStr> for Iter<'_> {
877 fn as_ref(&self) -> &OsStr {
878 self.as_path().as_os_str()
879 }
880 }
881
882 #[stable(feature = "rust1", since = "1.0.0")]
883 impl<'a> Iterator for Iter<'a> {
884 type Item = &'a OsStr;
885
886 fn next(&mut self) -> Option<&'a OsStr> {
887 self.inner.next().map(Component::as_os_str)
888 }
889 }
890
891 #[stable(feature = "rust1", since = "1.0.0")]
892 impl<'a> DoubleEndedIterator for Iter<'a> {
893 fn next_back(&mut self) -> Option<&'a OsStr> {
894 self.inner.next_back().map(Component::as_os_str)
895 }
896 }
897
898 #[stable(feature = "fused", since = "1.26.0")]
899 impl FusedIterator for Iter<'_> {}
900
901 #[stable(feature = "rust1", since = "1.0.0")]
902 impl<'a> Iterator for Components<'a> {
903 type Item = Component<'a>;
904
905 fn next(&mut self) -> Option<Component<'a>> {
906 while !self.finished() {
907 match self.front {
908 State::Prefix if self.prefix_len() > 0 => {
909 self.front = State::StartDir;
910 debug_assert!(self.prefix_len() <= self.path.len());
911 let raw = &self.path[..self.prefix_len()];
912 self.path = &self.path[self.prefix_len()..];
913 return Some(Component::Prefix(PrefixComponent {
914 raw: unsafe { u8_slice_as_os_str(raw) },
915 parsed: self.prefix.unwrap(),
916 }));
917 }
918 State::Prefix => {
919 self.front = State::StartDir;
920 }
921 State::StartDir => {
922 self.front = State::Body;
923 if self.has_physical_root {
924 debug_assert!(!self.path.is_empty());
925 self.path = &self.path[1..];
926 return Some(Component::RootDir);
927 } else if let Some(p) = self.prefix {
928 if p.has_implicit_root() && !p.is_verbatim() {
929 return Some(Component::RootDir);
930 }
931 } else if self.include_cur_dir() {
932 debug_assert!(!self.path.is_empty());
933 self.path = &self.path[1..];
934 return Some(Component::CurDir);
935 }
936 }
937 State::Body if !self.path.is_empty() => {
938 let (size, comp) = self.parse_next_component();
939 self.path = &self.path[size..];
940 if comp.is_some() {
941 return comp;
942 }
943 }
944 State::Body => {
945 self.front = State::Done;
946 }
947 State::Done => unreachable!(),
948 }
949 }
950 None
951 }
952 }
953
954 #[stable(feature = "rust1", since = "1.0.0")]
955 impl<'a> DoubleEndedIterator for Components<'a> {
956 fn next_back(&mut self) -> Option<Component<'a>> {
957 while !self.finished() {
958 match self.back {
959 State::Body if self.path.len() > self.len_before_body() => {
960 let (size, comp) = self.parse_next_component_back();
961 self.path = &self.path[..self.path.len() - size];
962 if comp.is_some() {
963 return comp;
964 }
965 }
966 State::Body => {
967 self.back = State::StartDir;
968 }
969 State::StartDir => {
970 self.back = State::Prefix;
971 if self.has_physical_root {
972 self.path = &self.path[..self.path.len() - 1];
973 return Some(Component::RootDir);
974 } else if let Some(p) = self.prefix {
975 if p.has_implicit_root() && !p.is_verbatim() {
976 return Some(Component::RootDir);
977 }
978 } else if self.include_cur_dir() {
979 self.path = &self.path[..self.path.len() - 1];
980 return Some(Component::CurDir);
981 }
982 }
983 State::Prefix if self.prefix_len() > 0 => {
984 self.back = State::Done;
985 return Some(Component::Prefix(PrefixComponent {
986 raw: unsafe { u8_slice_as_os_str(self.path) },
987 parsed: self.prefix.unwrap(),
988 }));
989 }
990 State::Prefix => {
991 self.back = State::Done;
992 return None;
993 }
994 State::Done => unreachable!(),
995 }
996 }
997 None
998 }
999 }
1000
1001 #[stable(feature = "fused", since = "1.26.0")]
1002 impl FusedIterator for Components<'_> {}
1003
1004 #[stable(feature = "rust1", since = "1.0.0")]
1005 impl<'a> cmp::PartialEq for Components<'a> {
1006 fn eq(&self, other: &Components<'a>) -> bool {
1007 Iterator::eq(self.clone(), other.clone())
1008 }
1009 }
1010
1011 #[stable(feature = "rust1", since = "1.0.0")]
1012 impl cmp::Eq for Components<'_> {}
1013
1014 #[stable(feature = "rust1", since = "1.0.0")]
1015 impl<'a> cmp::PartialOrd for Components<'a> {
1016 fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
1017 Iterator::partial_cmp(self.clone(), other.clone())
1018 }
1019 }
1020
1021 #[stable(feature = "rust1", since = "1.0.0")]
1022 impl cmp::Ord for Components<'_> {
1023 fn cmp(&self, other: &Self) -> cmp::Ordering {
1024 Iterator::cmp(self.clone(), other.clone())
1025 }
1026 }
1027
1028 /// An iterator over [`Path`] and its ancestors.
1029 ///
1030 /// This `struct` is created by the [`ancestors`] method on [`Path`].
1031 /// See its documentation for more.
1032 ///
1033 /// # Examples
1034 ///
1035 /// ```
1036 /// use std::path::Path;
1037 ///
1038 /// let path = Path::new("/foo/bar");
1039 ///
1040 /// for ancestor in path.ancestors() {
1041 /// println!("{}", ancestor.display());
1042 /// }
1043 /// ```
1044 ///
1045 /// [`ancestors`]: struct.Path.html#method.ancestors
1046 /// [`Path`]: struct.Path.html
1047 #[derive(Copy, Clone, Debug)]
1048 #[stable(feature = "path_ancestors", since = "1.28.0")]
1049 pub struct Ancestors<'a> {
1050 next: Option<&'a Path>,
1051 }
1052
1053 #[stable(feature = "path_ancestors", since = "1.28.0")]
1054 impl<'a> Iterator for Ancestors<'a> {
1055 type Item = &'a Path;
1056
1057 fn next(&mut self) -> Option<Self::Item> {
1058 let next = self.next;
1059 self.next = next.and_then(Path::parent);
1060 next
1061 }
1062 }
1063
1064 #[stable(feature = "path_ancestors", since = "1.28.0")]
1065 impl FusedIterator for Ancestors<'_> {}
1066
1067 ////////////////////////////////////////////////////////////////////////////////
1068 // Basic types and traits
1069 ////////////////////////////////////////////////////////////////////////////////
1070
1071 /// An owned, mutable path (akin to [`String`]).
1072 ///
1073 /// This type provides methods like [`push`] and [`set_extension`] that mutate
1074 /// the path in place. It also implements [`Deref`] to [`Path`], meaning that
1075 /// all methods on [`Path`] slices are available on `PathBuf` values as well.
1076 ///
1077 /// [`String`]: ../string/struct.String.html
1078 /// [`Path`]: struct.Path.html
1079 /// [`push`]: struct.PathBuf.html#method.push
1080 /// [`set_extension`]: struct.PathBuf.html#method.set_extension
1081 /// [`Deref`]: ../ops/trait.Deref.html
1082 ///
1083 /// More details about the overall approach can be found in
1084 /// the [module documentation](index.html).
1085 ///
1086 /// # Examples
1087 ///
1088 /// You can use [`push`] to build up a `PathBuf` from
1089 /// components:
1090 ///
1091 /// ```
1092 /// use std::path::PathBuf;
1093 ///
1094 /// let mut path = PathBuf::new();
1095 ///
1096 /// path.push(r"C:\");
1097 /// path.push("windows");
1098 /// path.push("system32");
1099 ///
1100 /// path.set_extension("dll");
1101 /// ```
1102 ///
1103 /// However, [`push`] is best used for dynamic situations. This is a better way
1104 /// to do this when you know all of the components ahead of time:
1105 ///
1106 /// ```
1107 /// use std::path::PathBuf;
1108 ///
1109 /// let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();
1110 /// ```
1111 ///
1112 /// We can still do better than this! Since these are all strings, we can use
1113 /// `From::from`:
1114 ///
1115 /// ```
1116 /// use std::path::PathBuf;
1117 ///
1118 /// let path = PathBuf::from(r"C:\windows\system32.dll");
1119 /// ```
1120 ///
1121 /// Which method works best depends on what kind of situation you're in.
1122 #[derive(Clone)]
1123 #[stable(feature = "rust1", since = "1.0.0")]
1124 pub struct PathBuf {
1125 inner: OsString,
1126 }
1127
1128 impl PathBuf {
1129 fn as_mut_vec(&mut self) -> &mut Vec<u8> {
1130 unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
1131 }
1132
1133 /// Allocates an empty `PathBuf`.
1134 ///
1135 /// # Examples
1136 ///
1137 /// ```
1138 /// use std::path::PathBuf;
1139 ///
1140 /// let path = PathBuf::new();
1141 /// ```
1142 #[stable(feature = "rust1", since = "1.0.0")]
1143 pub fn new() -> PathBuf {
1144 PathBuf { inner: OsString::new() }
1145 }
1146
1147 /// Creates a new `PathBuf` with a given capacity used to create the
1148 /// internal [`OsString`]. See [`with_capacity`] defined on [`OsString`].
1149 ///
1150 /// # Examples
1151 ///
1152 /// ```
1153 /// #![feature(path_buf_capacity)]
1154 /// use std::path::PathBuf;
1155 ///
1156 /// let mut path = PathBuf::with_capacity(10);
1157 /// let capacity = path.capacity();
1158 ///
1159 /// // This push is done without reallocating
1160 /// path.push(r"C:\");
1161 ///
1162 /// assert_eq!(capacity, path.capacity());
1163 /// ```
1164 ///
1165 /// [`with_capacity`]: ../ffi/struct.OsString.html#method.with_capacity
1166 /// [`OsString`]: ../ffi/struct.OsString.html
1167 #[unstable(feature = "path_buf_capacity", issue = "58234")]
1168 pub fn with_capacity(capacity: usize) -> PathBuf {
1169 PathBuf {
1170 inner: OsString::with_capacity(capacity)
1171 }
1172 }
1173
1174 /// Coerces to a [`Path`] slice.
1175 ///
1176 /// [`Path`]: struct.Path.html
1177 ///
1178 /// # Examples
1179 ///
1180 /// ```
1181 /// use std::path::{Path, PathBuf};
1182 ///
1183 /// let p = PathBuf::from("/test");
1184 /// assert_eq!(Path::new("/test"), p.as_path());
1185 /// ```
1186 #[stable(feature = "rust1", since = "1.0.0")]
1187 pub fn as_path(&self) -> &Path {
1188 self
1189 }
1190
1191 /// Extends `self` with `path`.
1192 ///
1193 /// If `path` is absolute, it replaces the current path.
1194 ///
1195 /// On Windows:
1196 ///
1197 /// * if `path` has a root but no prefix (e.g., `\windows`), it
1198 /// replaces everything except for the prefix (if any) of `self`.
1199 /// * if `path` has a prefix but no root, it replaces `self`.
1200 ///
1201 /// # Examples
1202 ///
1203 /// Pushing a relative path extends the existing path:
1204 ///
1205 /// ```
1206 /// use std::path::PathBuf;
1207 ///
1208 /// let mut path = PathBuf::from("/tmp");
1209 /// path.push("file.bk");
1210 /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
1211 /// ```
1212 ///
1213 /// Pushing an absolute path replaces the existing path:
1214 ///
1215 /// ```
1216 /// use std::path::PathBuf;
1217 ///
1218 /// let mut path = PathBuf::from("/tmp");
1219 /// path.push("/etc");
1220 /// assert_eq!(path, PathBuf::from("/etc"));
1221 /// ```
1222 #[stable(feature = "rust1", since = "1.0.0")]
1223 pub fn push<P: AsRef<Path>>(&mut self, path: P) {
1224 self._push(path.as_ref())
1225 }
1226
1227 fn _push(&mut self, path: &Path) {
1228 // in general, a separator is needed if the rightmost byte is not a separator
1229 let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
1230
1231 // in the special case of `C:` on Windows, do *not* add a separator
1232 {
1233 let comps = self.components();
1234 if comps.prefix_len() > 0 && comps.prefix_len() == comps.path.len() &&
1235 comps.prefix.unwrap().is_drive() {
1236 need_sep = false
1237 }
1238 }
1239
1240 // absolute `path` replaces `self`
1241 if path.is_absolute() || path.prefix().is_some() {
1242 self.as_mut_vec().truncate(0);
1243
1244 // `path` has a root but no prefix, e.g., `\windows` (Windows only)
1245 } else if path.has_root() {
1246 let prefix_len = self.components().prefix_remaining();
1247 self.as_mut_vec().truncate(prefix_len);
1248
1249 // `path` is a pure relative path
1250 } else if need_sep {
1251 self.inner.push(MAIN_SEP_STR);
1252 }
1253
1254 self.inner.push(path);
1255 }
1256
1257 /// Truncates `self` to [`self.parent`].
1258 ///
1259 /// Returns `false` and does nothing if [`self.parent`] is [`None`].
1260 /// Otherwise, returns `true`.
1261 ///
1262 /// [`None`]: ../../std/option/enum.Option.html#variant.None
1263 /// [`self.parent`]: struct.PathBuf.html#method.parent
1264 ///
1265 /// # Examples
1266 ///
1267 /// ```
1268 /// use std::path::{Path, PathBuf};
1269 ///
1270 /// let mut p = PathBuf::from("/test/test.rs");
1271 ///
1272 /// p.pop();
1273 /// assert_eq!(Path::new("/test"), p);
1274 /// p.pop();
1275 /// assert_eq!(Path::new("/"), p);
1276 /// ```
1277 #[stable(feature = "rust1", since = "1.0.0")]
1278 pub fn pop(&mut self) -> bool {
1279 match self.parent().map(|p| p.as_u8_slice().len()) {
1280 Some(len) => {
1281 self.as_mut_vec().truncate(len);
1282 true
1283 }
1284 None => false,
1285 }
1286 }
1287
1288 /// Updates [`self.file_name`] to `file_name`.
1289 ///
1290 /// If [`self.file_name`] was [`None`], this is equivalent to pushing
1291 /// `file_name`.
1292 ///
1293 /// Otherwise it is equivalent to calling [`pop`] and then pushing
1294 /// `file_name`. The new path will be a sibling of the original path.
1295 /// (That is, it will have the same parent.)
1296 ///
1297 /// [`self.file_name`]: struct.PathBuf.html#method.file_name
1298 /// [`None`]: ../../std/option/enum.Option.html#variant.None
1299 /// [`pop`]: struct.PathBuf.html#method.pop
1300 ///
1301 /// # Examples
1302 ///
1303 /// ```
1304 /// use std::path::PathBuf;
1305 ///
1306 /// let mut buf = PathBuf::from("/");
1307 /// assert!(buf.file_name() == None);
1308 /// buf.set_file_name("bar");
1309 /// assert!(buf == PathBuf::from("/bar"));
1310 /// assert!(buf.file_name().is_some());
1311 /// buf.set_file_name("baz.txt");
1312 /// assert!(buf == PathBuf::from("/baz.txt"));
1313 /// ```
1314 #[stable(feature = "rust1", since = "1.0.0")]
1315 pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
1316 self._set_file_name(file_name.as_ref())
1317 }
1318
1319 fn _set_file_name(&mut self, file_name: &OsStr) {
1320 if self.file_name().is_some() {
1321 let popped = self.pop();
1322 debug_assert!(popped);
1323 }
1324 self.push(file_name);
1325 }
1326
1327 /// Updates [`self.extension`] to `extension`.
1328 ///
1329 /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
1330 /// returns `true` and updates the extension otherwise.
1331 ///
1332 /// If [`self.extension`] is [`None`], the extension is added; otherwise
1333 /// it is replaced.
1334 ///
1335 /// [`self.file_name`]: struct.PathBuf.html#method.file_name
1336 /// [`self.extension`]: struct.PathBuf.html#method.extension
1337 /// [`None`]: ../../std/option/enum.Option.html#variant.None
1338 ///
1339 /// # Examples
1340 ///
1341 /// ```
1342 /// use std::path::{Path, PathBuf};
1343 ///
1344 /// let mut p = PathBuf::from("/feel/the");
1345 ///
1346 /// p.set_extension("force");
1347 /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
1348 ///
1349 /// p.set_extension("dark_side");
1350 /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path());
1351 /// ```
1352 #[stable(feature = "rust1", since = "1.0.0")]
1353 pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
1354 self._set_extension(extension.as_ref())
1355 }
1356
1357 fn _set_extension(&mut self, extension: &OsStr) -> bool {
1358 if self.file_name().is_none() {
1359 return false;
1360 }
1361
1362 let mut stem = match self.file_stem() {
1363 Some(stem) => stem.to_os_string(),
1364 None => OsString::new(),
1365 };
1366
1367 if !os_str_as_u8_slice(extension).is_empty() {
1368 stem.push(".");
1369 stem.push(extension);
1370 }
1371 self.set_file_name(&stem);
1372
1373 true
1374 }
1375
1376 /// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.
1377 ///
1378 /// [`OsString`]: ../ffi/struct.OsString.html
1379 ///
1380 /// # Examples
1381 ///
1382 /// ```
1383 /// use std::path::PathBuf;
1384 ///
1385 /// let p = PathBuf::from("/the/head");
1386 /// let os_str = p.into_os_string();
1387 /// ```
1388 #[stable(feature = "rust1", since = "1.0.0")]
1389 pub fn into_os_string(self) -> OsString {
1390 self.inner
1391 }
1392
1393 /// Converts this `PathBuf` into a [boxed][`Box`] [`Path`].
1394 ///
1395 /// [`Box`]: ../../std/boxed/struct.Box.html
1396 /// [`Path`]: struct.Path.html
1397 #[stable(feature = "into_boxed_path", since = "1.20.0")]
1398 pub fn into_boxed_path(self) -> Box<Path> {
1399 let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
1400 unsafe { Box::from_raw(rw) }
1401 }
1402
1403 /// Invokes [`capacity`] on the underlying instance of [`OsString`].
1404 ///
1405 /// [`capacity`]: ../ffi/struct.OsString.html#method.capacity
1406 /// [`OsString`]: ../ffi/struct.OsString.html
1407 #[unstable(feature = "path_buf_capacity", issue = "58234")]
1408 pub fn capacity(&self) -> usize {
1409 self.inner.capacity()
1410 }
1411
1412 /// Invokes [`clear`] on the underlying instance of [`OsString`].
1413 ///
1414 /// [`clear`]: ../ffi/struct.OsString.html#method.clear
1415 /// [`OsString`]: ../ffi/struct.OsString.html
1416 #[unstable(feature = "path_buf_capacity", issue = "58234")]
1417 pub fn clear(&mut self) {
1418 self.inner.clear()
1419 }
1420
1421 /// Invokes [`reserve`] on the underlying instance of [`OsString`].
1422 ///
1423 /// [`reserve`]: ../ffi/struct.OsString.html#method.reserve
1424 /// [`OsString`]: ../ffi/struct.OsString.html
1425 #[unstable(feature = "path_buf_capacity", issue = "58234")]
1426 pub fn reserve(&mut self, additional: usize) {
1427 self.inner.reserve(additional)
1428 }
1429
1430 /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].
1431 ///
1432 /// [`reserve_exact`]: ../ffi/struct.OsString.html#method.reserve_exact
1433 /// [`OsString`]: ../ffi/struct.OsString.html
1434 #[unstable(feature = "path_buf_capacity", issue = "58234")]
1435 pub fn reserve_exact(&mut self, additional: usize) {
1436 self.inner.reserve_exact(additional)
1437 }
1438
1439 /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].
1440 ///
1441 /// [`shrink_to_fit`]: ../ffi/struct.OsString.html#method.shrink_to_fit
1442 /// [`OsString`]: ../ffi/struct.OsString.html
1443 #[unstable(feature = "path_buf_capacity", issue = "58234")]
1444 pub fn shrink_to_fit(&mut self) {
1445 self.inner.shrink_to_fit()
1446 }
1447
1448 /// Invokes [`shrink_to`] on the underlying instance of [`OsString`].
1449 ///
1450 /// [`shrink_to`]: ../ffi/struct.OsString.html#method.shrink_to
1451 /// [`OsString`]: ../ffi/struct.OsString.html
1452 #[unstable(feature = "path_buf_capacity", issue = "58234")]
1453 pub fn shrink_to(&mut self, min_capacity: usize) {
1454 self.inner.shrink_to(min_capacity)
1455 }
1456 }
1457
1458 #[stable(feature = "box_from_path", since = "1.17.0")]
1459 impl From<&Path> for Box<Path> {
1460 fn from(path: &Path) -> Box<Path> {
1461 let boxed: Box<OsStr> = path.inner.into();
1462 let rw = Box::into_raw(boxed) as *mut Path;
1463 unsafe { Box::from_raw(rw) }
1464 }
1465 }
1466
1467 #[stable(feature = "path_buf_from_box", since = "1.18.0")]
1468 impl From<Box<Path>> for PathBuf {
1469 /// Converts a `Box<Path>` into a `PathBuf`
1470 ///
1471 /// This conversion does not allocate or copy memory.
1472 fn from(boxed: Box<Path>) -> PathBuf {
1473 boxed.into_path_buf()
1474 }
1475 }
1476
1477 #[stable(feature = "box_from_path_buf", since = "1.20.0")]
1478 impl From<PathBuf> for Box<Path> {
1479 /// Converts a `PathBuf` into a `Box<Path>`
1480 ///
1481 /// This conversion currently should not allocate memory,
1482 /// but this behavior is not guaranteed on all platforms or in all future versions.
1483 fn from(p: PathBuf) -> Box<Path> {
1484 p.into_boxed_path()
1485 }
1486 }
1487
1488 #[stable(feature = "more_box_slice_clone", since = "1.29.0")]
1489 impl Clone for Box<Path> {
1490 #[inline]
1491 fn clone(&self) -> Self {
1492 self.to_path_buf().into_boxed_path()
1493 }
1494 }
1495
1496 #[stable(feature = "rust1", since = "1.0.0")]
1497 impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
1498 fn from(s: &T) -> PathBuf {
1499 PathBuf::from(s.as_ref().to_os_string())
1500 }
1501 }
1502
1503 #[stable(feature = "rust1", since = "1.0.0")]
1504 impl From<OsString> for PathBuf {
1505 /// Converts a `OsString` into a `PathBuf`
1506 ///
1507 /// This conversion does not allocate or copy memory.
1508 fn from(s: OsString) -> PathBuf {
1509 PathBuf { inner: s }
1510 }
1511 }
1512
1513 #[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
1514 impl From<PathBuf> for OsString {
1515 /// Converts a `PathBuf` into a `OsString`
1516 ///
1517 /// This conversion does not allocate or copy memory.
1518 fn from(path_buf : PathBuf) -> OsString {
1519 path_buf.inner
1520 }
1521 }
1522
1523 #[stable(feature = "rust1", since = "1.0.0")]
1524 impl From<String> for PathBuf {
1525 /// Converts a `String` into a `PathBuf`
1526 ///
1527 /// This conversion does not allocate or copy memory.
1528 fn from(s: String) -> PathBuf {
1529 PathBuf::from(OsString::from(s))
1530 }
1531 }
1532
1533 #[stable(feature = "path_from_str", since = "1.32.0")]
1534 impl FromStr for PathBuf {
1535 type Err = core::convert::Infallible;
1536
1537 fn from_str(s: &str) -> Result<Self, Self::Err> {
1538 Ok(PathBuf::from(s))
1539 }
1540 }
1541
1542 #[stable(feature = "rust1", since = "1.0.0")]
1543 impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
1544 fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
1545 let mut buf = PathBuf::new();
1546 buf.extend(iter);
1547 buf
1548 }
1549 }
1550
1551 #[stable(feature = "rust1", since = "1.0.0")]
1552 impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
1553 fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
1554 iter.into_iter().for_each(move |p| self.push(p.as_ref()));
1555 }
1556 }
1557
1558 #[stable(feature = "rust1", since = "1.0.0")]
1559 impl fmt::Debug for PathBuf {
1560 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1561 fmt::Debug::fmt(&**self, formatter)
1562 }
1563 }
1564
1565 #[stable(feature = "rust1", since = "1.0.0")]
1566 impl ops::Deref for PathBuf {
1567 type Target = Path;
1568
1569 fn deref(&self) -> &Path {
1570 Path::new(&self.inner)
1571 }
1572 }
1573
1574 #[stable(feature = "rust1", since = "1.0.0")]
1575 impl Borrow<Path> for PathBuf {
1576 fn borrow(&self) -> &Path {
1577 self.deref()
1578 }
1579 }
1580
1581 #[stable(feature = "default_for_pathbuf", since = "1.17.0")]
1582 impl Default for PathBuf {
1583 fn default() -> Self {
1584 PathBuf::new()
1585 }
1586 }
1587
1588 #[stable(feature = "cow_from_path", since = "1.6.0")]
1589 impl<'a> From<&'a Path> for Cow<'a, Path> {
1590 #[inline]
1591 fn from(s: &'a Path) -> Cow<'a, Path> {
1592 Cow::Borrowed(s)
1593 }
1594 }
1595
1596 #[stable(feature = "cow_from_path", since = "1.6.0")]
1597 impl<'a> From<PathBuf> for Cow<'a, Path> {
1598 #[inline]
1599 fn from(s: PathBuf) -> Cow<'a, Path> {
1600 Cow::Owned(s)
1601 }
1602 }
1603
1604 #[stable(feature = "cow_from_pathbuf_ref", since = "1.28.0")]
1605 impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
1606 #[inline]
1607 fn from(p: &'a PathBuf) -> Cow<'a, Path> {
1608 Cow::Borrowed(p.as_path())
1609 }
1610 }
1611
1612 #[stable(feature = "pathbuf_from_cow_path", since = "1.28.0")]
1613 impl<'a> From<Cow<'a, Path>> for PathBuf {
1614 #[inline]
1615 fn from(p: Cow<'a, Path>) -> Self {
1616 p.into_owned()
1617 }
1618 }
1619
1620 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1621 impl From<PathBuf> for Arc<Path> {
1622 /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
1623 #[inline]
1624 fn from(s: PathBuf) -> Arc<Path> {
1625 let arc: Arc<OsStr> = Arc::from(s.into_os_string());
1626 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1627 }
1628 }
1629
1630 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1631 impl From<&Path> for Arc<Path> {
1632 /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
1633 #[inline]
1634 fn from(s: &Path) -> Arc<Path> {
1635 let arc: Arc<OsStr> = Arc::from(s.as_os_str());
1636 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1637 }
1638 }
1639
1640 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1641 impl From<PathBuf> for Rc<Path> {
1642 /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
1643 #[inline]
1644 fn from(s: PathBuf) -> Rc<Path> {
1645 let rc: Rc<OsStr> = Rc::from(s.into_os_string());
1646 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1647 }
1648 }
1649
1650 #[stable(feature = "shared_from_slice2", since = "1.24.0")]
1651 impl From<&Path> for Rc<Path> {
1652 /// Converts a Path into a Rc by copying the Path data into a new Rc buffer.
1653 #[inline]
1654 fn from(s: &Path) -> Rc<Path> {
1655 let rc: Rc<OsStr> = Rc::from(s.as_os_str());
1656 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1657 }
1658 }
1659
1660 #[stable(feature = "rust1", since = "1.0.0")]
1661 impl ToOwned for Path {
1662 type Owned = PathBuf;
1663 fn to_owned(&self) -> PathBuf {
1664 self.to_path_buf()
1665 }
1666 fn clone_into(&self, target: &mut PathBuf) {
1667 self.inner.clone_into(&mut target.inner);
1668 }
1669 }
1670
1671 #[stable(feature = "rust1", since = "1.0.0")]
1672 impl cmp::PartialEq for PathBuf {
1673 fn eq(&self, other: &PathBuf) -> bool {
1674 self.components() == other.components()
1675 }
1676 }
1677
1678 #[stable(feature = "rust1", since = "1.0.0")]
1679 impl Hash for PathBuf {
1680 fn hash<H: Hasher>(&self, h: &mut H) {
1681 self.as_path().hash(h)
1682 }
1683 }
1684
1685 #[stable(feature = "rust1", since = "1.0.0")]
1686 impl cmp::Eq for PathBuf {}
1687
1688 #[stable(feature = "rust1", since = "1.0.0")]
1689 impl cmp::PartialOrd for PathBuf {
1690 fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
1691 self.components().partial_cmp(other.components())
1692 }
1693 }
1694
1695 #[stable(feature = "rust1", since = "1.0.0")]
1696 impl cmp::Ord for PathBuf {
1697 fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
1698 self.components().cmp(other.components())
1699 }
1700 }
1701
1702 #[stable(feature = "rust1", since = "1.0.0")]
1703 impl AsRef<OsStr> for PathBuf {
1704 fn as_ref(&self) -> &OsStr {
1705 &self.inner[..]
1706 }
1707 }
1708
1709 /// A slice of a path (akin to [`str`]).
1710 ///
1711 /// This type supports a number of operations for inspecting a path, including
1712 /// breaking the path into its components (separated by `/` on Unix and by either
1713 /// `/` or `\` on Windows), extracting the file name, determining whether the path
1714 /// is absolute, and so on.
1715 ///
1716 /// This is an *unsized* type, meaning that it must always be used behind a
1717 /// pointer like `&` or [`Box`]. For an owned version of this type,
1718 /// see [`PathBuf`].
1719 ///
1720 /// [`str`]: ../primitive.str.html
1721 /// [`Box`]: ../boxed/struct.Box.html
1722 /// [`PathBuf`]: struct.PathBuf.html
1723 ///
1724 /// More details about the overall approach can be found in
1725 /// the [module documentation](index.html).
1726 ///
1727 /// # Examples
1728 ///
1729 /// ```
1730 /// use std::path::Path;
1731 /// use std::ffi::OsStr;
1732 ///
1733 /// // Note: this example does work on Windows
1734 /// let path = Path::new("./foo/bar.txt");
1735 ///
1736 /// let parent = path.parent();
1737 /// assert_eq!(parent, Some(Path::new("./foo")));
1738 ///
1739 /// let file_stem = path.file_stem();
1740 /// assert_eq!(file_stem, Some(OsStr::new("bar")));
1741 ///
1742 /// let extension = path.extension();
1743 /// assert_eq!(extension, Some(OsStr::new("txt")));
1744 /// ```
1745 #[stable(feature = "rust1", since = "1.0.0")]
1746 pub struct Path {
1747 inner: OsStr,
1748 }
1749
1750 /// An error returned from [`Path::strip_prefix`][`strip_prefix`] if the prefix
1751 /// was not found.
1752 ///
1753 /// This `struct` is created by the [`strip_prefix`] method on [`Path`].
1754 /// See its documentation for more.
1755 ///
1756 /// [`strip_prefix`]: struct.Path.html#method.strip_prefix
1757 /// [`Path`]: struct.Path.html
1758 #[derive(Debug, Clone, PartialEq, Eq)]
1759 #[stable(since = "1.7.0", feature = "strip_prefix")]
1760 pub struct StripPrefixError(());
1761
1762 impl Path {
1763 // The following (private!) function allows construction of a path from a u8
1764 // slice, which is only safe when it is known to follow the OsStr encoding.
1765 unsafe fn from_u8_slice(s: &[u8]) -> &Path {
1766 Path::new(u8_slice_as_os_str(s))
1767 }
1768 // The following (private!) function reveals the byte encoding used for OsStr.
1769 fn as_u8_slice(&self) -> &[u8] {
1770 os_str_as_u8_slice(&self.inner)
1771 }
1772
1773 /// Directly wraps a string slice as a `Path` slice.
1774 ///
1775 /// This is a cost-free conversion.
1776 ///
1777 /// # Examples
1778 ///
1779 /// ```
1780 /// use std::path::Path;
1781 ///
1782 /// Path::new("foo.txt");
1783 /// ```
1784 ///
1785 /// You can create `Path`s from `String`s, or even other `Path`s:
1786 ///
1787 /// ```
1788 /// use std::path::Path;
1789 ///
1790 /// let string = String::from("foo.txt");
1791 /// let from_string = Path::new(&string);
1792 /// let from_path = Path::new(&from_string);
1793 /// assert_eq!(from_string, from_path);
1794 /// ```
1795 #[stable(feature = "rust1", since = "1.0.0")]
1796 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
1797 unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
1798 }
1799
1800 /// Yields the underlying [`OsStr`] slice.
1801 ///
1802 /// [`OsStr`]: ../ffi/struct.OsStr.html
1803 ///
1804 /// # Examples
1805 ///
1806 /// ```
1807 /// use std::path::Path;
1808 ///
1809 /// let os_str = Path::new("foo.txt").as_os_str();
1810 /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
1811 /// ```
1812 #[stable(feature = "rust1", since = "1.0.0")]
1813 pub fn as_os_str(&self) -> &OsStr {
1814 &self.inner
1815 }
1816
1817 /// Yields a [`&str`] slice if the `Path` is valid unicode.
1818 ///
1819 /// This conversion may entail doing a check for UTF-8 validity.
1820 ///
1821 /// [`&str`]: ../primitive.str.html
1822 ///
1823 /// # Examples
1824 ///
1825 /// ```
1826 /// use std::path::Path;
1827 ///
1828 /// let path = Path::new("foo.txt");
1829 /// assert_eq!(path.to_str(), Some("foo.txt"));
1830 /// ```
1831 #[stable(feature = "rust1", since = "1.0.0")]
1832 pub fn to_str(&self) -> Option<&str> {
1833 self.inner.to_str()
1834 }
1835
1836 /// Converts a `Path` to a [`Cow<str>`].
1837 ///
1838 /// Any non-Unicode sequences are replaced with
1839 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
1840 ///
1841 /// [`Cow<str>`]: ../borrow/enum.Cow.html
1842 /// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
1843 ///
1844 /// # Examples
1845 ///
1846 /// Calling `to_string_lossy` on a `Path` with valid unicode:
1847 ///
1848 /// ```
1849 /// use std::path::Path;
1850 ///
1851 /// let path = Path::new("foo.txt");
1852 /// assert_eq!(path.to_string_lossy(), "foo.txt");
1853 /// ```
1854 ///
1855 /// Had `path` contained invalid unicode, the `to_string_lossy` call might
1856 /// have returned `"fo�.txt"`.
1857 #[stable(feature = "rust1", since = "1.0.0")]
1858 pub fn to_string_lossy(&self) -> Cow<'_, str> {
1859 self.inner.to_string_lossy()
1860 }
1861
1862 /// Converts a `Path` to an owned [`PathBuf`].
1863 ///
1864 /// [`PathBuf`]: struct.PathBuf.html
1865 ///
1866 /// # Examples
1867 ///
1868 /// ```
1869 /// use std::path::Path;
1870 ///
1871 /// let path_buf = Path::new("foo.txt").to_path_buf();
1872 /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
1873 /// ```
1874 #[rustc_conversion_suggestion]
1875 #[stable(feature = "rust1", since = "1.0.0")]
1876 pub fn to_path_buf(&self) -> PathBuf {
1877 PathBuf::from(self.inner.to_os_string())
1878 }
1879
1880 /// Returns `true` if the `Path` is absolute, i.e., if it is independent of
1881 /// the current directory.
1882 ///
1883 /// * On Unix, a path is absolute if it starts with the root, so
1884 /// `is_absolute` and [`has_root`] are equivalent.
1885 ///
1886 /// * On Windows, a path is absolute if it has a prefix and starts with the
1887 /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not.
1888 ///
1889 /// # Examples
1890 ///
1891 /// ```
1892 /// use std::path::Path;
1893 ///
1894 /// assert!(!Path::new("foo.txt").is_absolute());
1895 /// ```
1896 ///
1897 /// [`has_root`]: #method.has_root
1898 #[stable(feature = "rust1", since = "1.0.0")]
1899 #[allow(deprecated)]
1900 pub fn is_absolute(&self) -> bool {
1901 if cfg!(target_os = "redox") {
1902 // FIXME: Allow Redox prefixes
1903 self.has_root() || has_redox_scheme(self.as_u8_slice())
1904 } else {
1905 self.has_root() && (cfg!(unix) || self.prefix().is_some())
1906 }
1907 }
1908
1909 /// Returns `true` if the `Path` is relative, i.e., not absolute.
1910 ///
1911 /// See [`is_absolute`]'s documentation for more details.
1912 ///
1913 /// # Examples
1914 ///
1915 /// ```
1916 /// use std::path::Path;
1917 ///
1918 /// assert!(Path::new("foo.txt").is_relative());
1919 /// ```
1920 ///
1921 /// [`is_absolute`]: #method.is_absolute
1922 #[stable(feature = "rust1", since = "1.0.0")]
1923 pub fn is_relative(&self) -> bool {
1924 !self.is_absolute()
1925 }
1926
1927 fn prefix(&self) -> Option<Prefix<'_>> {
1928 self.components().prefix
1929 }
1930
1931 /// Returns `true` if the `Path` has a root.
1932 ///
1933 /// * On Unix, a path has a root if it begins with `/`.
1934 ///
1935 /// * On Windows, a path has a root if it:
1936 /// * has no prefix and begins with a separator, e.g., `\windows`
1937 /// * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows`
1938 /// * has any non-disk prefix, e.g., `\\server\share`
1939 ///
1940 /// # Examples
1941 ///
1942 /// ```
1943 /// use std::path::Path;
1944 ///
1945 /// assert!(Path::new("/etc/passwd").has_root());
1946 /// ```
1947 #[stable(feature = "rust1", since = "1.0.0")]
1948 pub fn has_root(&self) -> bool {
1949 self.components().has_root()
1950 }
1951
1952 /// Returns the `Path` without its final component, if there is one.
1953 ///
1954 /// Returns [`None`] if the path terminates in a root or prefix.
1955 ///
1956 /// [`None`]: ../../std/option/enum.Option.html#variant.None
1957 ///
1958 /// # Examples
1959 ///
1960 /// ```
1961 /// use std::path::Path;
1962 ///
1963 /// let path = Path::new("/foo/bar");
1964 /// let parent = path.parent().unwrap();
1965 /// assert_eq!(parent, Path::new("/foo"));
1966 ///
1967 /// let grand_parent = parent.parent().unwrap();
1968 /// assert_eq!(grand_parent, Path::new("/"));
1969 /// assert_eq!(grand_parent.parent(), None);
1970 /// ```
1971 #[stable(feature = "rust1", since = "1.0.0")]
1972 pub fn parent(&self) -> Option<&Path> {
1973 let mut comps = self.components();
1974 let comp = comps.next_back();
1975 comp.and_then(|p| {
1976 match p {
1977 Component::Normal(_) |
1978 Component::CurDir |
1979 Component::ParentDir => Some(comps.as_path()),
1980 _ => None,
1981 }
1982 })
1983 }
1984
1985 /// Produces an iterator over `Path` and its ancestors.
1986 ///
1987 /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
1988 /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
1989 /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
1990 /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
1991 /// namely `&self`.
1992 ///
1993 /// # Examples
1994 ///
1995 /// ```
1996 /// use std::path::Path;
1997 ///
1998 /// let mut ancestors = Path::new("/foo/bar").ancestors();
1999 /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
2000 /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
2001 /// assert_eq!(ancestors.next(), Some(Path::new("/")));
2002 /// assert_eq!(ancestors.next(), None);
2003 /// ```
2004 ///
2005 /// [`None`]: ../../std/option/enum.Option.html#variant.None
2006 /// [`parent`]: struct.Path.html#method.parent
2007 #[stable(feature = "path_ancestors", since = "1.28.0")]
2008 pub fn ancestors(&self) -> Ancestors<'_> {
2009 Ancestors {
2010 next: Some(&self),
2011 }
2012 }
2013
2014 /// Returns the final component of the `Path`, if there is one.
2015 ///
2016 /// If the path is a normal file, this is the file name. If it's the path of a directory, this
2017 /// is the directory name.
2018 ///
2019 /// Returns [`None`] if the path terminates in `..`.
2020 ///
2021 /// [`None`]: ../../std/option/enum.Option.html#variant.None
2022 ///
2023 /// # Examples
2024 ///
2025 /// ```
2026 /// use std::path::Path;
2027 /// use std::ffi::OsStr;
2028 ///
2029 /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name());
2030 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
2031 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
2032 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
2033 /// assert_eq!(None, Path::new("foo.txt/..").file_name());
2034 /// assert_eq!(None, Path::new("/").file_name());
2035 /// ```
2036 #[stable(feature = "rust1", since = "1.0.0")]
2037 pub fn file_name(&self) -> Option<&OsStr> {
2038 self.components().next_back().and_then(|p| {
2039 match p {
2040 Component::Normal(p) => Some(p.as_ref()),
2041 _ => None,
2042 }
2043 })
2044 }
2045
2046 /// Returns a path that, when joined onto `base`, yields `self`.
2047 ///
2048 /// # Errors
2049 ///
2050 /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
2051 /// returns `false`), returns [`Err`].
2052 ///
2053 /// [`starts_with`]: #method.starts_with
2054 /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
2055 ///
2056 /// # Examples
2057 ///
2058 /// ```
2059 /// use std::path::{Path, PathBuf};
2060 ///
2061 /// let path = Path::new("/test/haha/foo.txt");
2062 ///
2063 /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
2064 /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
2065 /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
2066 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
2067 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
2068 /// assert_eq!(path.strip_prefix("test").is_ok(), false);
2069 /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
2070 ///
2071 /// let prefix = PathBuf::from("/test/");
2072 /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
2073 /// ```
2074 #[stable(since = "1.7.0", feature = "path_strip_prefix")]
2075 pub fn strip_prefix<P>(&self, base: P)
2076 -> Result<&Path, StripPrefixError>
2077 where P: AsRef<Path>
2078 {
2079 self._strip_prefix(base.as_ref())
2080 }
2081
2082 fn _strip_prefix(&self, base: &Path)
2083 -> Result<&Path, StripPrefixError> {
2084 iter_after(self.components(), base.components())
2085 .map(|c| c.as_path())
2086 .ok_or(StripPrefixError(()))
2087 }
2088
2089 /// Determines whether `base` is a prefix of `self`.
2090 ///
2091 /// Only considers whole path components to match.
2092 ///
2093 /// # Examples
2094 ///
2095 /// ```
2096 /// use std::path::Path;
2097 ///
2098 /// let path = Path::new("/etc/passwd");
2099 ///
2100 /// assert!(path.starts_with("/etc"));
2101 /// assert!(path.starts_with("/etc/"));
2102 /// assert!(path.starts_with("/etc/passwd"));
2103 /// assert!(path.starts_with("/etc/passwd/"));
2104 ///
2105 /// assert!(!path.starts_with("/e"));
2106 /// ```
2107 #[stable(feature = "rust1", since = "1.0.0")]
2108 pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
2109 self._starts_with(base.as_ref())
2110 }
2111
2112 fn _starts_with(&self, base: &Path) -> bool {
2113 iter_after(self.components(), base.components()).is_some()
2114 }
2115
2116 /// Determines whether `child` is a suffix of `self`.
2117 ///
2118 /// Only considers whole path components to match.
2119 ///
2120 /// # Examples
2121 ///
2122 /// ```
2123 /// use std::path::Path;
2124 ///
2125 /// let path = Path::new("/etc/passwd");
2126 ///
2127 /// assert!(path.ends_with("passwd"));
2128 /// ```
2129 #[stable(feature = "rust1", since = "1.0.0")]
2130 pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
2131 self._ends_with(child.as_ref())
2132 }
2133
2134 fn _ends_with(&self, child: &Path) -> bool {
2135 iter_after(self.components().rev(), child.components().rev()).is_some()
2136 }
2137
2138 /// Extracts the stem (non-extension) portion of [`self.file_name`].
2139 ///
2140 /// [`self.file_name`]: struct.Path.html#method.file_name
2141 ///
2142 /// The stem is:
2143 ///
2144 /// * [`None`], if there is no file name;
2145 /// * The entire file name if there is no embedded `.`;
2146 /// * The entire file name if the file name begins with `.` and has no other `.`s within;
2147 /// * Otherwise, the portion of the file name before the final `.`
2148 ///
2149 /// [`None`]: ../../std/option/enum.Option.html#variant.None
2150 ///
2151 /// # Examples
2152 ///
2153 /// ```
2154 /// use std::path::Path;
2155 ///
2156 /// let path = Path::new("foo.rs");
2157 ///
2158 /// assert_eq!("foo", path.file_stem().unwrap());
2159 /// ```
2160 #[stable(feature = "rust1", since = "1.0.0")]
2161 pub fn file_stem(&self) -> Option<&OsStr> {
2162 self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
2163 }
2164
2165 /// Extracts the extension of [`self.file_name`], if possible.
2166 ///
2167 /// The extension is:
2168 ///
2169 /// * [`None`], if there is no file name;
2170 /// * [`None`], if there is no embedded `.`;
2171 /// * [`None`], if the file name begins with `.` and has no other `.`s within;
2172 /// * Otherwise, the portion of the file name after the final `.`
2173 ///
2174 /// [`self.file_name`]: struct.Path.html#method.file_name
2175 /// [`None`]: ../../std/option/enum.Option.html#variant.None
2176 ///
2177 /// # Examples
2178 ///
2179 /// ```
2180 /// use std::path::Path;
2181 ///
2182 /// let path = Path::new("foo.rs");
2183 ///
2184 /// assert_eq!("rs", path.extension().unwrap());
2185 /// ```
2186 #[stable(feature = "rust1", since = "1.0.0")]
2187 pub fn extension(&self) -> Option<&OsStr> {
2188 self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
2189 }
2190
2191 /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
2192 ///
2193 /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
2194 ///
2195 /// [`PathBuf`]: struct.PathBuf.html
2196 /// [`PathBuf::push`]: struct.PathBuf.html#method.push
2197 ///
2198 /// # Examples
2199 ///
2200 /// ```
2201 /// use std::path::{Path, PathBuf};
2202 ///
2203 /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
2204 /// ```
2205 #[stable(feature = "rust1", since = "1.0.0")]
2206 pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
2207 self._join(path.as_ref())
2208 }
2209
2210 fn _join(&self, path: &Path) -> PathBuf {
2211 let mut buf = self.to_path_buf();
2212 buf.push(path);
2213 buf
2214 }
2215
2216 /// Creates an owned [`PathBuf`] like `self` but with the given file name.
2217 ///
2218 /// See [`PathBuf::set_file_name`] for more details.
2219 ///
2220 /// [`PathBuf`]: struct.PathBuf.html
2221 /// [`PathBuf::set_file_name`]: struct.PathBuf.html#method.set_file_name
2222 ///
2223 /// # Examples
2224 ///
2225 /// ```
2226 /// use std::path::{Path, PathBuf};
2227 ///
2228 /// let path = Path::new("/tmp/foo.txt");
2229 /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
2230 ///
2231 /// let path = Path::new("/tmp");
2232 /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
2233 /// ```
2234 #[stable(feature = "rust1", since = "1.0.0")]
2235 pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
2236 self._with_file_name(file_name.as_ref())
2237 }
2238
2239 fn _with_file_name(&self, file_name: &OsStr) -> PathBuf {
2240 let mut buf = self.to_path_buf();
2241 buf.set_file_name(file_name);
2242 buf
2243 }
2244
2245 /// Creates an owned [`PathBuf`] like `self` but with the given extension.
2246 ///
2247 /// See [`PathBuf::set_extension`] for more details.
2248 ///
2249 /// [`PathBuf`]: struct.PathBuf.html
2250 /// [`PathBuf::set_extension`]: struct.PathBuf.html#method.set_extension
2251 ///
2252 /// # Examples
2253 ///
2254 /// ```
2255 /// use std::path::{Path, PathBuf};
2256 ///
2257 /// let path = Path::new("foo.rs");
2258 /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
2259 /// ```
2260 #[stable(feature = "rust1", since = "1.0.0")]
2261 pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
2262 self._with_extension(extension.as_ref())
2263 }
2264
2265 fn _with_extension(&self, extension: &OsStr) -> PathBuf {
2266 let mut buf = self.to_path_buf();
2267 buf.set_extension(extension);
2268 buf
2269 }
2270
2271 /// Produces an iterator over the [`Component`]s of the path.
2272 ///
2273 /// When parsing the path, there is a small amount of normalization:
2274 ///
2275 /// * Repeated separators are ignored, so `a/b` and `a//b` both have
2276 /// `a` and `b` as components.
2277 ///
2278 /// * Occurrences of `.` are normalized away, except if they are at the
2279 /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
2280 /// `a/b` all have `a` and `b` as components, but `./a/b` starts with
2281 /// an additional [`CurDir`] component.
2282 ///
2283 /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
2284 ///
2285 /// Note that no other normalization takes place; in particular, `a/c`
2286 /// and `a/b/../c` are distinct, to account for the possibility that `b`
2287 /// is a symbolic link (so its parent isn't `a`).
2288 ///
2289 /// # Examples
2290 ///
2291 /// ```
2292 /// use std::path::{Path, Component};
2293 /// use std::ffi::OsStr;
2294 ///
2295 /// let mut components = Path::new("/tmp/foo.txt").components();
2296 ///
2297 /// assert_eq!(components.next(), Some(Component::RootDir));
2298 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
2299 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
2300 /// assert_eq!(components.next(), None)
2301 /// ```
2302 ///
2303 /// [`Component`]: enum.Component.html
2304 /// [`CurDir`]: enum.Component.html#variant.CurDir
2305 #[stable(feature = "rust1", since = "1.0.0")]
2306 pub fn components(&self) -> Components<'_> {
2307 let prefix = parse_prefix(self.as_os_str());
2308 Components {
2309 path: self.as_u8_slice(),
2310 prefix,
2311 has_physical_root: has_physical_root(self.as_u8_slice(), prefix) ||
2312 has_redox_scheme(self.as_u8_slice()),
2313 front: State::Prefix,
2314 back: State::Body,
2315 }
2316 }
2317
2318 /// Produces an iterator over the path's components viewed as [`OsStr`]
2319 /// slices.
2320 ///
2321 /// For more information about the particulars of how the path is separated
2322 /// into components, see [`components`].
2323 ///
2324 /// [`components`]: #method.components
2325 /// [`OsStr`]: ../ffi/struct.OsStr.html
2326 ///
2327 /// # Examples
2328 ///
2329 /// ```
2330 /// use std::path::{self, Path};
2331 /// use std::ffi::OsStr;
2332 ///
2333 /// let mut it = Path::new("/tmp/foo.txt").iter();
2334 /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
2335 /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
2336 /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
2337 /// assert_eq!(it.next(), None)
2338 /// ```
2339 #[stable(feature = "rust1", since = "1.0.0")]
2340 pub fn iter(&self) -> Iter<'_> {
2341 Iter { inner: self.components() }
2342 }
2343
2344 /// Returns an object that implements [`Display`] for safely printing paths
2345 /// that may contain non-Unicode data.
2346 ///
2347 /// [`Display`]: ../fmt/trait.Display.html
2348 ///
2349 /// # Examples
2350 ///
2351 /// ```
2352 /// use std::path::Path;
2353 ///
2354 /// let path = Path::new("/tmp/foo.rs");
2355 ///
2356 /// println!("{}", path.display());
2357 /// ```
2358 #[stable(feature = "rust1", since = "1.0.0")]
2359 pub fn display(&self) -> Display<'_> {
2360 Display { path: self }
2361 }
2362
2363 /// Queries the file system to get information about a file, directory, etc.
2364 ///
2365 /// This function will traverse symbolic links to query information about the
2366 /// destination file.
2367 ///
2368 /// This is an alias to [`fs::metadata`].
2369 ///
2370 /// [`fs::metadata`]: ../fs/fn.metadata.html
2371 ///
2372 /// # Examples
2373 ///
2374 /// ```no_run
2375 /// use std::path::Path;
2376 ///
2377 /// let path = Path::new("/Minas/tirith");
2378 /// let metadata = path.metadata().expect("metadata call failed");
2379 /// println!("{:?}", metadata.file_type());
2380 /// ```
2381 #[stable(feature = "path_ext", since = "1.5.0")]
2382 pub fn metadata(&self) -> io::Result<fs::Metadata> {
2383 fs::metadata(self)
2384 }
2385
2386 /// Queries the metadata about a file without following symlinks.
2387 ///
2388 /// This is an alias to [`fs::symlink_metadata`].
2389 ///
2390 /// [`fs::symlink_metadata`]: ../fs/fn.symlink_metadata.html
2391 ///
2392 /// # Examples
2393 ///
2394 /// ```no_run
2395 /// use std::path::Path;
2396 ///
2397 /// let path = Path::new("/Minas/tirith");
2398 /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
2399 /// println!("{:?}", metadata.file_type());
2400 /// ```
2401 #[stable(feature = "path_ext", since = "1.5.0")]
2402 pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
2403 fs::symlink_metadata(self)
2404 }
2405
2406 /// Returns the canonical, absolute form of the path with all intermediate
2407 /// components normalized and symbolic links resolved.
2408 ///
2409 /// This is an alias to [`fs::canonicalize`].
2410 ///
2411 /// [`fs::canonicalize`]: ../fs/fn.canonicalize.html
2412 ///
2413 /// # Examples
2414 ///
2415 /// ```no_run
2416 /// use std::path::{Path, PathBuf};
2417 ///
2418 /// let path = Path::new("/foo/test/../test/bar.rs");
2419 /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
2420 /// ```
2421 #[stable(feature = "path_ext", since = "1.5.0")]
2422 pub fn canonicalize(&self) -> io::Result<PathBuf> {
2423 fs::canonicalize(self)
2424 }
2425
2426 /// Reads a symbolic link, returning the file that the link points to.
2427 ///
2428 /// This is an alias to [`fs::read_link`].
2429 ///
2430 /// [`fs::read_link`]: ../fs/fn.read_link.html
2431 ///
2432 /// # Examples
2433 ///
2434 /// ```no_run
2435 /// use std::path::Path;
2436 ///
2437 /// let path = Path::new("/laputa/sky_castle.rs");
2438 /// let path_link = path.read_link().expect("read_link call failed");
2439 /// ```
2440 #[stable(feature = "path_ext", since = "1.5.0")]
2441 pub fn read_link(&self) -> io::Result<PathBuf> {
2442 fs::read_link(self)
2443 }
2444
2445 /// Returns an iterator over the entries within a directory.
2446 ///
2447 /// The iterator will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. New
2448 /// errors may be encountered after an iterator is initially constructed.
2449 ///
2450 /// This is an alias to [`fs::read_dir`].
2451 ///
2452 /// [`io::Result`]: ../io/type.Result.html
2453 /// [`DirEntry`]: ../fs/struct.DirEntry.html
2454 /// [`fs::read_dir`]: ../fs/fn.read_dir.html
2455 ///
2456 /// # Examples
2457 ///
2458 /// ```no_run
2459 /// use std::path::Path;
2460 ///
2461 /// let path = Path::new("/laputa");
2462 /// for entry in path.read_dir().expect("read_dir call failed") {
2463 /// if let Ok(entry) = entry {
2464 /// println!("{:?}", entry.path());
2465 /// }
2466 /// }
2467 /// ```
2468 #[stable(feature = "path_ext", since = "1.5.0")]
2469 pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
2470 fs::read_dir(self)
2471 }
2472
2473 /// Returns `true` if the path points at an existing entity.
2474 ///
2475 /// This function will traverse symbolic links to query information about the
2476 /// destination file. In case of broken symbolic links this will return `false`.
2477 ///
2478 /// If you cannot access the directory containing the file, e.g., because of a
2479 /// permission error, this will return `false`.
2480 ///
2481 /// # Examples
2482 ///
2483 /// ```no_run
2484 /// use std::path::Path;
2485 /// assert_eq!(Path::new("does_not_exist.txt").exists(), false);
2486 /// ```
2487 ///
2488 /// # See Also
2489 ///
2490 /// This is a convenience function that coerces errors to false. If you want to
2491 /// check errors, call [fs::metadata].
2492 ///
2493 /// [fs::metadata]: ../../std/fs/fn.metadata.html
2494 #[stable(feature = "path_ext", since = "1.5.0")]
2495 pub fn exists(&self) -> bool {
2496 fs::metadata(self).is_ok()
2497 }
2498
2499 /// Returns `true` if the path exists on disk and is pointing at a regular file.
2500 ///
2501 /// This function will traverse symbolic links to query information about the
2502 /// destination file. In case of broken symbolic links this will return `false`.
2503 ///
2504 /// If you cannot access the directory containing the file, e.g., because of a
2505 /// permission error, this will return `false`.
2506 ///
2507 /// # Examples
2508 ///
2509 /// ```no_run
2510 /// use std::path::Path;
2511 /// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
2512 /// assert_eq!(Path::new("a_file.txt").is_file(), true);
2513 /// ```
2514 ///
2515 /// # See Also
2516 ///
2517 /// This is a convenience function that coerces errors to false. If you want to
2518 /// check errors, call [fs::metadata] and handle its Result. Then call
2519 /// [fs::Metadata::is_file] if it was Ok.
2520 ///
2521 /// [fs::metadata]: ../../std/fs/fn.metadata.html
2522 /// [fs::Metadata::is_file]: ../../std/fs/struct.Metadata.html#method.is_file
2523 #[stable(feature = "path_ext", since = "1.5.0")]
2524 pub fn is_file(&self) -> bool {
2525 fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
2526 }
2527
2528 /// Returns `true` if the path exists on disk and is pointing at a directory.
2529 ///
2530 /// This function will traverse symbolic links to query information about the
2531 /// destination file. In case of broken symbolic links this will return `false`.
2532 ///
2533 /// If you cannot access the directory containing the file, e.g., because of a
2534 /// permission error, this will return `false`.
2535 ///
2536 /// # Examples
2537 ///
2538 /// ```no_run
2539 /// use std::path::Path;
2540 /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
2541 /// assert_eq!(Path::new("a_file.txt").is_dir(), false);
2542 /// ```
2543 ///
2544 /// # See Also
2545 ///
2546 /// This is a convenience function that coerces errors to false. If you want to
2547 /// check errors, call [fs::metadata] and handle its Result. Then call
2548 /// [fs::Metadata::is_dir] if it was Ok.
2549 ///
2550 /// [fs::metadata]: ../../std/fs/fn.metadata.html
2551 /// [fs::Metadata::is_dir]: ../../std/fs/struct.Metadata.html#method.is_dir
2552 #[stable(feature = "path_ext", since = "1.5.0")]
2553 pub fn is_dir(&self) -> bool {
2554 fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
2555 }
2556
2557 /// Converts a [`Box<Path>`][`Box`] into a [`PathBuf`] without copying or
2558 /// allocating.
2559 ///
2560 /// [`Box`]: ../../std/boxed/struct.Box.html
2561 /// [`PathBuf`]: struct.PathBuf.html
2562 #[stable(feature = "into_boxed_path", since = "1.20.0")]
2563 pub fn into_path_buf(self: Box<Path>) -> PathBuf {
2564 let rw = Box::into_raw(self) as *mut OsStr;
2565 let inner = unsafe { Box::from_raw(rw) };
2566 PathBuf { inner: OsString::from(inner) }
2567 }
2568 }
2569
2570 #[stable(feature = "rust1", since = "1.0.0")]
2571 impl AsRef<OsStr> for Path {
2572 fn as_ref(&self) -> &OsStr {
2573 &self.inner
2574 }
2575 }
2576
2577 #[stable(feature = "rust1", since = "1.0.0")]
2578 impl fmt::Debug for Path {
2579 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2580 fmt::Debug::fmt(&self.inner, formatter)
2581 }
2582 }
2583
2584 /// Helper struct for safely printing paths with [`format!`] and `{}`.
2585 ///
2586 /// A [`Path`] might contain non-Unicode data. This `struct` implements the
2587 /// [`Display`] trait in a way that mitigates that. It is created by the
2588 /// [`display`][`Path::display`] method on [`Path`].
2589 ///
2590 /// # Examples
2591 ///
2592 /// ```
2593 /// use std::path::Path;
2594 ///
2595 /// let path = Path::new("/tmp/foo.rs");
2596 ///
2597 /// println!("{}", path.display());
2598 /// ```
2599 ///
2600 /// [`Display`]: ../../std/fmt/trait.Display.html
2601 /// [`format!`]: ../../std/macro.format.html
2602 /// [`Path`]: struct.Path.html
2603 /// [`Path::display`]: struct.Path.html#method.display
2604 #[stable(feature = "rust1", since = "1.0.0")]
2605 pub struct Display<'a> {
2606 path: &'a Path,
2607 }
2608
2609 #[stable(feature = "rust1", since = "1.0.0")]
2610 impl fmt::Debug for Display<'_> {
2611 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2612 fmt::Debug::fmt(&self.path, f)
2613 }
2614 }
2615
2616 #[stable(feature = "rust1", since = "1.0.0")]
2617 impl fmt::Display for Display<'_> {
2618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2619 self.path.inner.display(f)
2620 }
2621 }
2622
2623 #[stable(feature = "rust1", since = "1.0.0")]
2624 impl cmp::PartialEq for Path {
2625 fn eq(&self, other: &Path) -> bool {
2626 self.components().eq(other.components())
2627 }
2628 }
2629
2630 #[stable(feature = "rust1", since = "1.0.0")]
2631 impl Hash for Path {
2632 fn hash<H: Hasher>(&self, h: &mut H) {
2633 for component in self.components() {
2634 component.hash(h);
2635 }
2636 }
2637 }
2638
2639 #[stable(feature = "rust1", since = "1.0.0")]
2640 impl cmp::Eq for Path {}
2641
2642 #[stable(feature = "rust1", since = "1.0.0")]
2643 impl cmp::PartialOrd for Path {
2644 fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
2645 self.components().partial_cmp(other.components())
2646 }
2647 }
2648
2649 #[stable(feature = "rust1", since = "1.0.0")]
2650 impl cmp::Ord for Path {
2651 fn cmp(&self, other: &Path) -> cmp::Ordering {
2652 self.components().cmp(other.components())
2653 }
2654 }
2655
2656 #[stable(feature = "rust1", since = "1.0.0")]
2657 impl AsRef<Path> for Path {
2658 fn as_ref(&self) -> &Path {
2659 self
2660 }
2661 }
2662
2663 #[stable(feature = "rust1", since = "1.0.0")]
2664 impl AsRef<Path> for OsStr {
2665 fn as_ref(&self) -> &Path {
2666 Path::new(self)
2667 }
2668 }
2669
2670 #[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
2671 impl AsRef<Path> for Cow<'_, OsStr> {
2672 fn as_ref(&self) -> &Path {
2673 Path::new(self)
2674 }
2675 }
2676
2677 #[stable(feature = "rust1", since = "1.0.0")]
2678 impl AsRef<Path> for OsString {
2679 fn as_ref(&self) -> &Path {
2680 Path::new(self)
2681 }
2682 }
2683
2684 #[stable(feature = "rust1", since = "1.0.0")]
2685 impl AsRef<Path> for str {
2686 fn as_ref(&self) -> &Path {
2687 Path::new(self)
2688 }
2689 }
2690
2691 #[stable(feature = "rust1", since = "1.0.0")]
2692 impl AsRef<Path> for String {
2693 fn as_ref(&self) -> &Path {
2694 Path::new(self)
2695 }
2696 }
2697
2698 #[stable(feature = "rust1", since = "1.0.0")]
2699 impl AsRef<Path> for PathBuf {
2700 fn as_ref(&self) -> &Path {
2701 self
2702 }
2703 }
2704
2705 #[stable(feature = "path_into_iter", since = "1.6.0")]
2706 impl<'a> IntoIterator for &'a PathBuf {
2707 type Item = &'a OsStr;
2708 type IntoIter = Iter<'a>;
2709 fn into_iter(self) -> Iter<'a> { self.iter() }
2710 }
2711
2712 #[stable(feature = "path_into_iter", since = "1.6.0")]
2713 impl<'a> IntoIterator for &'a Path {
2714 type Item = &'a OsStr;
2715 type IntoIter = Iter<'a>;
2716 fn into_iter(self) -> Iter<'a> { self.iter() }
2717 }
2718
2719 macro_rules! impl_cmp {
2720 ($lhs:ty, $rhs: ty) => {
2721 #[stable(feature = "partialeq_path", since = "1.6.0")]
2722 impl<'a, 'b> PartialEq<$rhs> for $lhs {
2723 #[inline]
2724 fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other) }
2725 }
2726
2727 #[stable(feature = "partialeq_path", since = "1.6.0")]
2728 impl<'a, 'b> PartialEq<$lhs> for $rhs {
2729 #[inline]
2730 fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self, other) }
2731 }
2732
2733 #[stable(feature = "cmp_path", since = "1.8.0")]
2734 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
2735 #[inline]
2736 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
2737 <Path as PartialOrd>::partial_cmp(self, other)
2738 }
2739 }
2740
2741 #[stable(feature = "cmp_path", since = "1.8.0")]
2742 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
2743 #[inline]
2744 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
2745 <Path as PartialOrd>::partial_cmp(self, other)
2746 }
2747 }
2748 }
2749 }
2750
2751 impl_cmp!(PathBuf, Path);
2752 impl_cmp!(PathBuf, &'a Path);
2753 impl_cmp!(Cow<'a, Path>, Path);
2754 impl_cmp!(Cow<'a, Path>, &'b Path);
2755 impl_cmp!(Cow<'a, Path>, PathBuf);
2756
2757 macro_rules! impl_cmp_os_str {
2758 ($lhs:ty, $rhs: ty) => {
2759 #[stable(feature = "cmp_path", since = "1.8.0")]
2760 impl<'a, 'b> PartialEq<$rhs> for $lhs {
2761 #[inline]
2762 fn eq(&self, other: &$rhs) -> bool { <Path as PartialEq>::eq(self, other.as_ref()) }
2763 }
2764
2765 #[stable(feature = "cmp_path", since = "1.8.0")]
2766 impl<'a, 'b> PartialEq<$lhs> for $rhs {
2767 #[inline]
2768 fn eq(&self, other: &$lhs) -> bool { <Path as PartialEq>::eq(self.as_ref(), other) }
2769 }
2770
2771 #[stable(feature = "cmp_path", since = "1.8.0")]
2772 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
2773 #[inline]
2774 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
2775 <Path as PartialOrd>::partial_cmp(self, other.as_ref())
2776 }
2777 }
2778
2779 #[stable(feature = "cmp_path", since = "1.8.0")]
2780 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
2781 #[inline]
2782 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
2783 <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
2784 }
2785 }
2786 }
2787 }
2788
2789 impl_cmp_os_str!(PathBuf, OsStr);
2790 impl_cmp_os_str!(PathBuf, &'a OsStr);
2791 impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
2792 impl_cmp_os_str!(PathBuf, OsString);
2793 impl_cmp_os_str!(Path, OsStr);
2794 impl_cmp_os_str!(Path, &'a OsStr);
2795 impl_cmp_os_str!(Path, Cow<'a, OsStr>);
2796 impl_cmp_os_str!(Path, OsString);
2797 impl_cmp_os_str!(&'a Path, OsStr);
2798 impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
2799 impl_cmp_os_str!(&'a Path, OsString);
2800 impl_cmp_os_str!(Cow<'a, Path>, OsStr);
2801 impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr);
2802 impl_cmp_os_str!(Cow<'a, Path>, OsString);
2803
2804 #[stable(since = "1.7.0", feature = "strip_prefix")]
2805 impl fmt::Display for StripPrefixError {
2806 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2807 self.description().fmt(f)
2808 }
2809 }
2810
2811 #[stable(since = "1.7.0", feature = "strip_prefix")]
2812 impl Error for StripPrefixError {
2813 fn description(&self) -> &str { "prefix not found" }
2814 }
2815
2816 #[cfg(test)]
2817 mod tests {
2818 use super::*;
2819
2820 use crate::rc::Rc;
2821 use crate::sync::Arc;
2822
2823 macro_rules! t(
2824 ($path:expr, iter: $iter:expr) => (
2825 {
2826 let path = Path::new($path);
2827
2828 // Forward iteration
2829 let comps = path.iter()
2830 .map(|p| p.to_string_lossy().into_owned())
2831 .collect::<Vec<String>>();
2832 let exp: &[&str] = &$iter;
2833 let exps = exp.iter().map(|s| s.to_string()).collect::<Vec<String>>();
2834 assert!(comps == exps, "iter: Expected {:?}, found {:?}",
2835 exps, comps);
2836
2837 // Reverse iteration
2838 let comps = Path::new($path).iter().rev()
2839 .map(|p| p.to_string_lossy().into_owned())
2840 .collect::<Vec<String>>();
2841 let exps = exps.into_iter().rev().collect::<Vec<String>>();
2842 assert!(comps == exps, "iter().rev(): Expected {:?}, found {:?}",
2843 exps, comps);
2844 }
2845 );
2846
2847 ($path:expr, has_root: $has_root:expr, is_absolute: $is_absolute:expr) => (
2848 {
2849 let path = Path::new($path);
2850
2851 let act_root = path.has_root();
2852 assert!(act_root == $has_root, "has_root: Expected {:?}, found {:?}",
2853 $has_root, act_root);
2854
2855 let act_abs = path.is_absolute();
2856 assert!(act_abs == $is_absolute, "is_absolute: Expected {:?}, found {:?}",
2857 $is_absolute, act_abs);
2858 }
2859 );
2860
2861 ($path:expr, parent: $parent:expr, file_name: $file:expr) => (
2862 {
2863 let path = Path::new($path);
2864
2865 let parent = path.parent().map(|p| p.to_str().unwrap());
2866 let exp_parent: Option<&str> = $parent;
2867 assert!(parent == exp_parent, "parent: Expected {:?}, found {:?}",
2868 exp_parent, parent);
2869
2870 let file = path.file_name().map(|p| p.to_str().unwrap());
2871 let exp_file: Option<&str> = $file;
2872 assert!(file == exp_file, "file_name: Expected {:?}, found {:?}",
2873 exp_file, file);
2874 }
2875 );
2876
2877 ($path:expr, file_stem: $file_stem:expr, extension: $extension:expr) => (
2878 {
2879 let path = Path::new($path);
2880
2881 let stem = path.file_stem().map(|p| p.to_str().unwrap());
2882 let exp_stem: Option<&str> = $file_stem;
2883 assert!(stem == exp_stem, "file_stem: Expected {:?}, found {:?}",
2884 exp_stem, stem);
2885
2886 let ext = path.extension().map(|p| p.to_str().unwrap());
2887 let exp_ext: Option<&str> = $extension;
2888 assert!(ext == exp_ext, "extension: Expected {:?}, found {:?}",
2889 exp_ext, ext);
2890 }
2891 );
2892
2893 ($path:expr, iter: $iter:expr,
2894 has_root: $has_root:expr, is_absolute: $is_absolute:expr,
2895 parent: $parent:expr, file_name: $file:expr,
2896 file_stem: $file_stem:expr, extension: $extension:expr) => (
2897 {
2898 t!($path, iter: $iter);
2899 t!($path, has_root: $has_root, is_absolute: $is_absolute);
2900 t!($path, parent: $parent, file_name: $file);
2901 t!($path, file_stem: $file_stem, extension: $extension);
2902 }
2903 );
2904 );
2905
2906 #[test]
2907 fn into() {
2908 use crate::borrow::Cow;
2909
2910 let static_path = Path::new("/home/foo");
2911 let static_cow_path: Cow<'static, Path> = static_path.into();
2912 let pathbuf = PathBuf::from("/home/foo");
2913
2914 {
2915 let path: &Path = &pathbuf;
2916 let borrowed_cow_path: Cow<'_, Path> = path.into();
2917
2918 assert_eq!(static_cow_path, borrowed_cow_path);
2919 }
2920
2921 let owned_cow_path: Cow<'static, Path> = pathbuf.into();
2922
2923 assert_eq!(static_cow_path, owned_cow_path);
2924 }
2925
2926 #[test]
2927 #[cfg(unix)]
2928 pub fn test_decompositions_unix() {
2929 t!("",
2930 iter: [],
2931 has_root: false,
2932 is_absolute: false,
2933 parent: None,
2934 file_name: None,
2935 file_stem: None,
2936 extension: None
2937 );
2938
2939 t!("foo",
2940 iter: ["foo"],
2941 has_root: false,
2942 is_absolute: false,
2943 parent: Some(""),
2944 file_name: Some("foo"),
2945 file_stem: Some("foo"),
2946 extension: None
2947 );
2948
2949 t!("/",
2950 iter: ["/"],
2951 has_root: true,
2952 is_absolute: true,
2953 parent: None,
2954 file_name: None,
2955 file_stem: None,
2956 extension: None
2957 );
2958
2959 t!("/foo",
2960 iter: ["/", "foo"],
2961 has_root: true,
2962 is_absolute: true,
2963 parent: Some("/"),
2964 file_name: Some("foo"),
2965 file_stem: Some("foo"),
2966 extension: None
2967 );
2968
2969 t!("foo/",
2970 iter: ["foo"],
2971 has_root: false,
2972 is_absolute: false,
2973 parent: Some(""),
2974 file_name: Some("foo"),
2975 file_stem: Some("foo"),
2976 extension: None
2977 );
2978
2979 t!("/foo/",
2980 iter: ["/", "foo"],
2981 has_root: true,
2982 is_absolute: true,
2983 parent: Some("/"),
2984 file_name: Some("foo"),
2985 file_stem: Some("foo"),
2986 extension: None
2987 );
2988
2989 t!("foo/bar",
2990 iter: ["foo", "bar"],
2991 has_root: false,
2992 is_absolute: false,
2993 parent: Some("foo"),
2994 file_name: Some("bar"),
2995 file_stem: Some("bar"),
2996 extension: None
2997 );
2998
2999 t!("/foo/bar",
3000 iter: ["/", "foo", "bar"],
3001 has_root: true,
3002 is_absolute: true,
3003 parent: Some("/foo"),
3004 file_name: Some("bar"),
3005 file_stem: Some("bar"),
3006 extension: None
3007 );
3008
3009 t!("///foo///",
3010 iter: ["/", "foo"],
3011 has_root: true,
3012 is_absolute: true,
3013 parent: Some("/"),
3014 file_name: Some("foo"),
3015 file_stem: Some("foo"),
3016 extension: None
3017 );
3018
3019 t!("///foo///bar",
3020 iter: ["/", "foo", "bar"],
3021 has_root: true,
3022 is_absolute: true,
3023 parent: Some("///foo"),
3024 file_name: Some("bar"),
3025 file_stem: Some("bar"),
3026 extension: None
3027 );
3028
3029 t!("./.",
3030 iter: ["."],
3031 has_root: false,
3032 is_absolute: false,
3033 parent: Some(""),
3034 file_name: None,
3035 file_stem: None,
3036 extension: None
3037 );
3038
3039 t!("/..",
3040 iter: ["/", ".."],
3041 has_root: true,
3042 is_absolute: true,
3043 parent: Some("/"),
3044 file_name: None,
3045 file_stem: None,
3046 extension: None
3047 );
3048
3049 t!("../",
3050 iter: [".."],
3051 has_root: false,
3052 is_absolute: false,
3053 parent: Some(""),
3054 file_name: None,
3055 file_stem: None,
3056 extension: None
3057 );
3058
3059 t!("foo/.",
3060 iter: ["foo"],
3061 has_root: false,
3062 is_absolute: false,
3063 parent: Some(""),
3064 file_name: Some("foo"),
3065 file_stem: Some("foo"),
3066 extension: None
3067 );
3068
3069 t!("foo/..",
3070 iter: ["foo", ".."],
3071 has_root: false,
3072 is_absolute: false,
3073 parent: Some("foo"),
3074 file_name: None,
3075 file_stem: None,
3076 extension: None
3077 );
3078
3079 t!("foo/./",
3080 iter: ["foo"],
3081 has_root: false,
3082 is_absolute: false,
3083 parent: Some(""),
3084 file_name: Some("foo"),
3085 file_stem: Some("foo"),
3086 extension: None
3087 );
3088
3089 t!("foo/./bar",
3090 iter: ["foo", "bar"],
3091 has_root: false,
3092 is_absolute: false,
3093 parent: Some("foo"),
3094 file_name: Some("bar"),
3095 file_stem: Some("bar"),
3096 extension: None
3097 );
3098
3099 t!("foo/../",
3100 iter: ["foo", ".."],
3101 has_root: false,
3102 is_absolute: false,
3103 parent: Some("foo"),
3104 file_name: None,
3105 file_stem: None,
3106 extension: None
3107 );
3108
3109 t!("foo/../bar",
3110 iter: ["foo", "..", "bar"],
3111 has_root: false,
3112 is_absolute: false,
3113 parent: Some("foo/.."),
3114 file_name: Some("bar"),
3115 file_stem: Some("bar"),
3116 extension: None
3117 );
3118
3119 t!("./a",
3120 iter: [".", "a"],
3121 has_root: false,
3122 is_absolute: false,
3123 parent: Some("."),
3124 file_name: Some("a"),
3125 file_stem: Some("a"),
3126 extension: None
3127 );
3128
3129 t!(".",
3130 iter: ["."],
3131 has_root: false,
3132 is_absolute: false,
3133 parent: Some(""),
3134 file_name: None,
3135 file_stem: None,
3136 extension: None
3137 );
3138
3139 t!("./",
3140 iter: ["."],
3141 has_root: false,
3142 is_absolute: false,
3143 parent: Some(""),
3144 file_name: None,
3145 file_stem: None,
3146 extension: None
3147 );
3148
3149 t!("a/b",
3150 iter: ["a", "b"],
3151 has_root: false,
3152 is_absolute: false,
3153 parent: Some("a"),
3154 file_name: Some("b"),
3155 file_stem: Some("b"),
3156 extension: None
3157 );
3158
3159 t!("a//b",
3160 iter: ["a", "b"],
3161 has_root: false,
3162 is_absolute: false,
3163 parent: Some("a"),
3164 file_name: Some("b"),
3165 file_stem: Some("b"),
3166 extension: None
3167 );
3168
3169 t!("a/./b",
3170 iter: ["a", "b"],
3171 has_root: false,
3172 is_absolute: false,
3173 parent: Some("a"),
3174 file_name: Some("b"),
3175 file_stem: Some("b"),
3176 extension: None
3177 );
3178
3179 t!("a/b/c",
3180 iter: ["a", "b", "c"],
3181 has_root: false,
3182 is_absolute: false,
3183 parent: Some("a/b"),
3184 file_name: Some("c"),
3185 file_stem: Some("c"),
3186 extension: None
3187 );
3188
3189 t!(".foo",
3190 iter: [".foo"],
3191 has_root: false,
3192 is_absolute: false,
3193 parent: Some(""),
3194 file_name: Some(".foo"),
3195 file_stem: Some(".foo"),
3196 extension: None
3197 );
3198 }
3199
3200 #[test]
3201 #[cfg(windows)]
3202 pub fn test_decompositions_windows() {
3203 t!("",
3204 iter: [],
3205 has_root: false,
3206 is_absolute: false,
3207 parent: None,
3208 file_name: None,
3209 file_stem: None,
3210 extension: None
3211 );
3212
3213 t!("foo",
3214 iter: ["foo"],
3215 has_root: false,
3216 is_absolute: false,
3217 parent: Some(""),
3218 file_name: Some("foo"),
3219 file_stem: Some("foo"),
3220 extension: None
3221 );
3222
3223 t!("/",
3224 iter: ["\\"],
3225 has_root: true,
3226 is_absolute: false,
3227 parent: None,
3228 file_name: None,
3229 file_stem: None,
3230 extension: None
3231 );
3232
3233 t!("\\",
3234 iter: ["\\"],
3235 has_root: true,
3236 is_absolute: false,
3237 parent: None,
3238 file_name: None,
3239 file_stem: None,
3240 extension: None
3241 );
3242
3243 t!("c:",
3244 iter: ["c:"],
3245 has_root: false,
3246 is_absolute: false,
3247 parent: None,
3248 file_name: None,
3249 file_stem: None,
3250 extension: None
3251 );
3252
3253 t!("c:\\",
3254 iter: ["c:", "\\"],
3255 has_root: true,
3256 is_absolute: true,
3257 parent: None,
3258 file_name: None,
3259 file_stem: None,
3260 extension: None
3261 );
3262
3263 t!("c:/",
3264 iter: ["c:", "\\"],
3265 has_root: true,
3266 is_absolute: true,
3267 parent: None,
3268 file_name: None,
3269 file_stem: None,
3270 extension: None
3271 );
3272
3273 t!("/foo",
3274 iter: ["\\", "foo"],
3275 has_root: true,
3276 is_absolute: false,
3277 parent: Some("/"),
3278 file_name: Some("foo"),
3279 file_stem: Some("foo"),
3280 extension: None
3281 );
3282
3283 t!("foo/",
3284 iter: ["foo"],
3285 has_root: false,
3286 is_absolute: false,
3287 parent: Some(""),
3288 file_name: Some("foo"),
3289 file_stem: Some("foo"),
3290 extension: None
3291 );
3292
3293 t!("/foo/",
3294 iter: ["\\", "foo"],
3295 has_root: true,
3296 is_absolute: false,
3297 parent: Some("/"),
3298 file_name: Some("foo"),
3299 file_stem: Some("foo"),
3300 extension: None
3301 );
3302
3303 t!("foo/bar",
3304 iter: ["foo", "bar"],
3305 has_root: false,
3306 is_absolute: false,
3307 parent: Some("foo"),
3308 file_name: Some("bar"),
3309 file_stem: Some("bar"),
3310 extension: None
3311 );
3312
3313 t!("/foo/bar",
3314 iter: ["\\", "foo", "bar"],
3315 has_root: true,
3316 is_absolute: false,
3317 parent: Some("/foo"),
3318 file_name: Some("bar"),
3319 file_stem: Some("bar"),
3320 extension: None
3321 );
3322
3323 t!("///foo///",
3324 iter: ["\\", "foo"],
3325 has_root: true,
3326 is_absolute: false,
3327 parent: Some("/"),
3328 file_name: Some("foo"),
3329 file_stem: Some("foo"),
3330 extension: None
3331 );
3332
3333 t!("///foo///bar",
3334 iter: ["\\", "foo", "bar"],
3335 has_root: true,
3336 is_absolute: false,
3337 parent: Some("///foo"),
3338 file_name: Some("bar"),
3339 file_stem: Some("bar"),
3340 extension: None
3341 );
3342
3343 t!("./.",
3344 iter: ["."],
3345 has_root: false,
3346 is_absolute: false,
3347 parent: Some(""),
3348 file_name: None,
3349 file_stem: None,
3350 extension: None
3351 );
3352
3353 t!("/..",
3354 iter: ["\\", ".."],
3355 has_root: true,
3356 is_absolute: false,
3357 parent: Some("/"),
3358 file_name: None,
3359 file_stem: None,
3360 extension: None
3361 );
3362
3363 t!("../",
3364 iter: [".."],
3365 has_root: false,
3366 is_absolute: false,
3367 parent: Some(""),
3368 file_name: None,
3369 file_stem: None,
3370 extension: None
3371 );
3372
3373 t!("foo/.",
3374 iter: ["foo"],
3375 has_root: false,
3376 is_absolute: false,
3377 parent: Some(""),
3378 file_name: Some("foo"),
3379 file_stem: Some("foo"),
3380 extension: None
3381 );
3382
3383 t!("foo/..",
3384 iter: ["foo", ".."],
3385 has_root: false,
3386 is_absolute: false,
3387 parent: Some("foo"),
3388 file_name: None,
3389 file_stem: None,
3390 extension: None
3391 );
3392
3393 t!("foo/./",
3394 iter: ["foo"],
3395 has_root: false,
3396 is_absolute: false,
3397 parent: Some(""),
3398 file_name: Some("foo"),
3399 file_stem: Some("foo"),
3400 extension: None
3401 );
3402
3403 t!("foo/./bar",
3404 iter: ["foo", "bar"],
3405 has_root: false,
3406 is_absolute: false,
3407 parent: Some("foo"),
3408 file_name: Some("bar"),
3409 file_stem: Some("bar"),
3410 extension: None
3411 );
3412
3413 t!("foo/../",
3414 iter: ["foo", ".."],
3415 has_root: false,
3416 is_absolute: false,
3417 parent: Some("foo"),
3418 file_name: None,
3419 file_stem: None,
3420 extension: None
3421 );
3422
3423 t!("foo/../bar",
3424 iter: ["foo", "..", "bar"],
3425 has_root: false,
3426 is_absolute: false,
3427 parent: Some("foo/.."),
3428 file_name: Some("bar"),
3429 file_stem: Some("bar"),
3430 extension: None
3431 );
3432
3433 t!("./a",
3434 iter: [".", "a"],
3435 has_root: false,
3436 is_absolute: false,
3437 parent: Some("."),
3438 file_name: Some("a"),
3439 file_stem: Some("a"),
3440 extension: None
3441 );
3442
3443 t!(".",
3444 iter: ["."],
3445 has_root: false,
3446 is_absolute: false,
3447 parent: Some(""),
3448 file_name: None,
3449 file_stem: None,
3450 extension: None
3451 );
3452
3453 t!("./",
3454 iter: ["."],
3455 has_root: false,
3456 is_absolute: false,
3457 parent: Some(""),
3458 file_name: None,
3459 file_stem: None,
3460 extension: None
3461 );
3462
3463 t!("a/b",
3464 iter: ["a", "b"],
3465 has_root: false,
3466 is_absolute: false,
3467 parent: Some("a"),
3468 file_name: Some("b"),
3469 file_stem: Some("b"),
3470 extension: None
3471 );
3472
3473 t!("a//b",
3474 iter: ["a", "b"],
3475 has_root: false,
3476 is_absolute: false,
3477 parent: Some("a"),
3478 file_name: Some("b"),
3479 file_stem: Some("b"),
3480 extension: None
3481 );
3482
3483 t!("a/./b",
3484 iter: ["a", "b"],
3485 has_root: false,
3486 is_absolute: false,
3487 parent: Some("a"),
3488 file_name: Some("b"),
3489 file_stem: Some("b"),
3490 extension: None
3491 );
3492
3493 t!("a/b/c",
3494 iter: ["a", "b", "c"],
3495 has_root: false,
3496 is_absolute: false,
3497 parent: Some("a/b"),
3498 file_name: Some("c"),
3499 file_stem: Some("c"),
3500 extension: None);
3501
3502 t!("a\\b\\c",
3503 iter: ["a", "b", "c"],
3504 has_root: false,
3505 is_absolute: false,
3506 parent: Some("a\\b"),
3507 file_name: Some("c"),
3508 file_stem: Some("c"),
3509 extension: None
3510 );
3511
3512 t!("\\a",
3513 iter: ["\\", "a"],
3514 has_root: true,
3515 is_absolute: false,
3516 parent: Some("\\"),
3517 file_name: Some("a"),
3518 file_stem: Some("a"),
3519 extension: None
3520 );
3521
3522 t!("c:\\foo.txt",
3523 iter: ["c:", "\\", "foo.txt"],
3524 has_root: true,
3525 is_absolute: true,
3526 parent: Some("c:\\"),
3527 file_name: Some("foo.txt"),
3528 file_stem: Some("foo"),
3529 extension: Some("txt")
3530 );
3531
3532 t!("\\\\server\\share\\foo.txt",
3533 iter: ["\\\\server\\share", "\\", "foo.txt"],
3534 has_root: true,
3535 is_absolute: true,
3536 parent: Some("\\\\server\\share\\"),
3537 file_name: Some("foo.txt"),
3538 file_stem: Some("foo"),
3539 extension: Some("txt")
3540 );
3541
3542 t!("\\\\server\\share",
3543 iter: ["\\\\server\\share", "\\"],
3544 has_root: true,
3545 is_absolute: true,
3546 parent: None,
3547 file_name: None,
3548 file_stem: None,
3549 extension: None
3550 );
3551
3552 t!("\\\\server",
3553 iter: ["\\", "server"],
3554 has_root: true,
3555 is_absolute: false,
3556 parent: Some("\\"),
3557 file_name: Some("server"),
3558 file_stem: Some("server"),
3559 extension: None
3560 );
3561
3562 t!("\\\\?\\bar\\foo.txt",
3563 iter: ["\\\\?\\bar", "\\", "foo.txt"],
3564 has_root: true,
3565 is_absolute: true,
3566 parent: Some("\\\\?\\bar\\"),
3567 file_name: Some("foo.txt"),
3568 file_stem: Some("foo"),
3569 extension: Some("txt")
3570 );
3571
3572 t!("\\\\?\\bar",
3573 iter: ["\\\\?\\bar"],
3574 has_root: true,
3575 is_absolute: true,
3576 parent: None,
3577 file_name: None,
3578 file_stem: None,
3579 extension: None
3580 );
3581
3582 t!("\\\\?\\",
3583 iter: ["\\\\?\\"],
3584 has_root: true,
3585 is_absolute: true,
3586 parent: None,
3587 file_name: None,
3588 file_stem: None,
3589 extension: None
3590 );
3591
3592 t!("\\\\?\\UNC\\server\\share\\foo.txt",
3593 iter: ["\\\\?\\UNC\\server\\share", "\\", "foo.txt"],
3594 has_root: true,
3595 is_absolute: true,
3596 parent: Some("\\\\?\\UNC\\server\\share\\"),
3597 file_name: Some("foo.txt"),
3598 file_stem: Some("foo"),
3599 extension: Some("txt")
3600 );
3601
3602 t!("\\\\?\\UNC\\server",
3603 iter: ["\\\\?\\UNC\\server"],
3604 has_root: true,
3605 is_absolute: true,
3606 parent: None,
3607 file_name: None,
3608 file_stem: None,
3609 extension: None
3610 );
3611
3612 t!("\\\\?\\UNC\\",
3613 iter: ["\\\\?\\UNC\\"],
3614 has_root: true,
3615 is_absolute: true,
3616 parent: None,
3617 file_name: None,
3618 file_stem: None,
3619 extension: None
3620 );
3621
3622 t!("\\\\?\\C:\\foo.txt",
3623 iter: ["\\\\?\\C:", "\\", "foo.txt"],
3624 has_root: true,
3625 is_absolute: true,
3626 parent: Some("\\\\?\\C:\\"),
3627 file_name: Some("foo.txt"),
3628 file_stem: Some("foo"),
3629 extension: Some("txt")
3630 );
3631
3632
3633 t!("\\\\?\\C:\\",
3634 iter: ["\\\\?\\C:", "\\"],
3635 has_root: true,
3636 is_absolute: true,
3637 parent: None,
3638 file_name: None,
3639 file_stem: None,
3640 extension: None
3641 );
3642
3643
3644 t!("\\\\?\\C:",
3645 iter: ["\\\\?\\C:"],
3646 has_root: true,
3647 is_absolute: true,
3648 parent: None,
3649 file_name: None,
3650 file_stem: None,
3651 extension: None
3652 );
3653
3654
3655 t!("\\\\?\\foo/bar",
3656 iter: ["\\\\?\\foo/bar"],
3657 has_root: true,
3658 is_absolute: true,
3659 parent: None,
3660 file_name: None,
3661 file_stem: None,
3662 extension: None
3663 );
3664
3665
3666 t!("\\\\?\\C:/foo",
3667 iter: ["\\\\?\\C:/foo"],
3668 has_root: true,
3669 is_absolute: true,
3670 parent: None,
3671 file_name: None,
3672 file_stem: None,
3673 extension: None
3674 );
3675
3676
3677 t!("\\\\.\\foo\\bar",
3678 iter: ["\\\\.\\foo", "\\", "bar"],
3679 has_root: true,
3680 is_absolute: true,
3681 parent: Some("\\\\.\\foo\\"),
3682 file_name: Some("bar"),
3683 file_stem: Some("bar"),
3684 extension: None
3685 );
3686
3687
3688 t!("\\\\.\\foo",
3689 iter: ["\\\\.\\foo", "\\"],
3690 has_root: true,
3691 is_absolute: true,
3692 parent: None,
3693 file_name: None,
3694 file_stem: None,
3695 extension: None
3696 );
3697
3698
3699 t!("\\\\.\\foo/bar",
3700 iter: ["\\\\.\\foo/bar", "\\"],
3701 has_root: true,
3702 is_absolute: true,
3703 parent: None,
3704 file_name: None,
3705 file_stem: None,
3706 extension: None
3707 );
3708
3709
3710 t!("\\\\.\\foo\\bar/baz",
3711 iter: ["\\\\.\\foo", "\\", "bar", "baz"],
3712 has_root: true,
3713 is_absolute: true,
3714 parent: Some("\\\\.\\foo\\bar"),
3715 file_name: Some("baz"),
3716 file_stem: Some("baz"),
3717 extension: None
3718 );
3719
3720
3721 t!("\\\\.\\",
3722 iter: ["\\\\.\\", "\\"],
3723 has_root: true,
3724 is_absolute: true,
3725 parent: None,
3726 file_name: None,
3727 file_stem: None,
3728 extension: None
3729 );
3730
3731 t!("\\\\?\\a\\b\\",
3732 iter: ["\\\\?\\a", "\\", "b"],
3733 has_root: true,
3734 is_absolute: true,
3735 parent: Some("\\\\?\\a\\"),
3736 file_name: Some("b"),
3737 file_stem: Some("b"),
3738 extension: None
3739 );
3740 }
3741
3742 #[test]
3743 pub fn test_stem_ext() {
3744 t!("foo",
3745 file_stem: Some("foo"),
3746 extension: None
3747 );
3748
3749 t!("foo.",
3750 file_stem: Some("foo"),
3751 extension: Some("")
3752 );
3753
3754 t!(".foo",
3755 file_stem: Some(".foo"),
3756 extension: None
3757 );
3758
3759 t!("foo.txt",
3760 file_stem: Some("foo"),
3761 extension: Some("txt")
3762 );
3763
3764 t!("foo.bar.txt",
3765 file_stem: Some("foo.bar"),
3766 extension: Some("txt")
3767 );
3768
3769 t!("foo.bar.",
3770 file_stem: Some("foo.bar"),
3771 extension: Some("")
3772 );
3773
3774 t!(".",
3775 file_stem: None,
3776 extension: None
3777 );
3778
3779 t!("..",
3780 file_stem: None,
3781 extension: None
3782 );
3783
3784 t!("",
3785 file_stem: None,
3786 extension: None
3787 );
3788 }
3789
3790 #[test]
3791 pub fn test_push() {
3792 macro_rules! tp(
3793 ($path:expr, $push:expr, $expected:expr) => ( {
3794 let mut actual = PathBuf::from($path);
3795 actual.push($push);
3796 assert!(actual.to_str() == Some($expected),
3797 "pushing {:?} onto {:?}: Expected {:?}, got {:?}",
3798 $push, $path, $expected, actual.to_str().unwrap());
3799 });
3800 );
3801
3802 if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
3803 tp!("", "foo", "foo");
3804 tp!("foo", "bar", "foo/bar");
3805 tp!("foo/", "bar", "foo/bar");
3806 tp!("foo//", "bar", "foo//bar");
3807 tp!("foo/.", "bar", "foo/./bar");
3808 tp!("foo./.", "bar", "foo././bar");
3809 tp!("foo", "", "foo/");
3810 tp!("foo", ".", "foo/.");
3811 tp!("foo", "..", "foo/..");
3812 tp!("foo", "/", "/");
3813 tp!("/foo/bar", "/", "/");
3814 tp!("/foo/bar", "/baz", "/baz");
3815 tp!("/foo/bar", "./baz", "/foo/bar/./baz");
3816 } else {
3817 tp!("", "foo", "foo");
3818 tp!("foo", "bar", r"foo\bar");
3819 tp!("foo/", "bar", r"foo/bar");
3820 tp!(r"foo\", "bar", r"foo\bar");
3821 tp!("foo//", "bar", r"foo//bar");
3822 tp!(r"foo\\", "bar", r"foo\\bar");
3823 tp!("foo/.", "bar", r"foo/.\bar");
3824 tp!("foo./.", "bar", r"foo./.\bar");
3825 tp!(r"foo\.", "bar", r"foo\.\bar");
3826 tp!(r"foo.\.", "bar", r"foo.\.\bar");
3827 tp!("foo", "", "foo\\");
3828 tp!("foo", ".", r"foo\.");
3829 tp!("foo", "..", r"foo\..");
3830 tp!("foo", "/", "/");
3831 tp!("foo", r"\", r"\");
3832 tp!("/foo/bar", "/", "/");
3833 tp!(r"\foo\bar", r"\", r"\");
3834 tp!("/foo/bar", "/baz", "/baz");
3835 tp!("/foo/bar", r"\baz", r"\baz");
3836 tp!("/foo/bar", "./baz", r"/foo/bar\./baz");
3837 tp!("/foo/bar", r".\baz", r"/foo/bar\.\baz");
3838
3839 tp!("c:\\", "windows", "c:\\windows");
3840 tp!("c:", "windows", "c:windows");
3841
3842 tp!("a\\b\\c", "d", "a\\b\\c\\d");
3843 tp!("\\a\\b\\c", "d", "\\a\\b\\c\\d");
3844 tp!("a\\b", "c\\d", "a\\b\\c\\d");
3845 tp!("a\\b", "\\c\\d", "\\c\\d");
3846 tp!("a\\b", ".", "a\\b\\.");
3847 tp!("a\\b", "..\\c", "a\\b\\..\\c");
3848 tp!("a\\b", "C:a.txt", "C:a.txt");
3849 tp!("a\\b", "C:\\a.txt", "C:\\a.txt");
3850 tp!("C:\\a", "C:\\b.txt", "C:\\b.txt");
3851 tp!("C:\\a\\b\\c", "C:d", "C:d");
3852 tp!("C:a\\b\\c", "C:d", "C:d");
3853 tp!("C:", r"a\b\c", r"C:a\b\c");
3854 tp!("C:", r"..\a", r"C:..\a");
3855 tp!("\\\\server\\share\\foo",
3856 "bar",
3857 "\\\\server\\share\\foo\\bar");
3858 tp!("\\\\server\\share\\foo", "C:baz", "C:baz");
3859 tp!("\\\\?\\C:\\a\\b", "C:c\\d", "C:c\\d");
3860 tp!("\\\\?\\C:a\\b", "C:c\\d", "C:c\\d");
3861 tp!("\\\\?\\C:\\a\\b", "C:\\c\\d", "C:\\c\\d");
3862 tp!("\\\\?\\foo\\bar", "baz", "\\\\?\\foo\\bar\\baz");
3863 tp!("\\\\?\\UNC\\server\\share\\foo",
3864 "bar",
3865 "\\\\?\\UNC\\server\\share\\foo\\bar");
3866 tp!("\\\\?\\UNC\\server\\share", "C:\\a", "C:\\a");
3867 tp!("\\\\?\\UNC\\server\\share", "C:a", "C:a");
3868
3869 // Note: modified from old path API
3870 tp!("\\\\?\\UNC\\server", "foo", "\\\\?\\UNC\\server\\foo");
3871
3872 tp!("C:\\a",
3873 "\\\\?\\UNC\\server\\share",
3874 "\\\\?\\UNC\\server\\share");
3875 tp!("\\\\.\\foo\\bar", "baz", "\\\\.\\foo\\bar\\baz");
3876 tp!("\\\\.\\foo\\bar", "C:a", "C:a");
3877 // again, not sure about the following, but I'm assuming \\.\ should be verbatim
3878 tp!("\\\\.\\foo", "..\\bar", "\\\\.\\foo\\..\\bar");
3879
3880 tp!("\\\\?\\C:", "foo", "\\\\?\\C:\\foo"); // this is a weird one
3881 }
3882 }
3883
3884 #[test]
3885 pub fn test_pop() {
3886 macro_rules! tp(
3887 ($path:expr, $expected:expr, $output:expr) => ( {
3888 let mut actual = PathBuf::from($path);
3889 let output = actual.pop();
3890 assert!(actual.to_str() == Some($expected) && output == $output,
3891 "popping from {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
3892 $path, $expected, $output,
3893 actual.to_str().unwrap(), output);
3894 });
3895 );
3896
3897 tp!("", "", false);
3898 tp!("/", "/", false);
3899 tp!("foo", "", true);
3900 tp!(".", "", true);
3901 tp!("/foo", "/", true);
3902 tp!("/foo/bar", "/foo", true);
3903 tp!("foo/bar", "foo", true);
3904 tp!("foo/.", "", true);
3905 tp!("foo//bar", "foo", true);
3906
3907 if cfg!(windows) {
3908 tp!("a\\b\\c", "a\\b", true);
3909 tp!("\\a", "\\", true);
3910 tp!("\\", "\\", false);
3911
3912 tp!("C:\\a\\b", "C:\\a", true);
3913 tp!("C:\\a", "C:\\", true);
3914 tp!("C:\\", "C:\\", false);
3915 tp!("C:a\\b", "C:a", true);
3916 tp!("C:a", "C:", true);
3917 tp!("C:", "C:", false);
3918 tp!("\\\\server\\share\\a\\b", "\\\\server\\share\\a", true);
3919 tp!("\\\\server\\share\\a", "\\\\server\\share\\", true);
3920 tp!("\\\\server\\share", "\\\\server\\share", false);
3921 tp!("\\\\?\\a\\b\\c", "\\\\?\\a\\b", true);
3922 tp!("\\\\?\\a\\b", "\\\\?\\a\\", true);
3923 tp!("\\\\?\\a", "\\\\?\\a", false);
3924 tp!("\\\\?\\C:\\a\\b", "\\\\?\\C:\\a", true);
3925 tp!("\\\\?\\C:\\a", "\\\\?\\C:\\", true);
3926 tp!("\\\\?\\C:\\", "\\\\?\\C:\\", false);
3927 tp!("\\\\?\\UNC\\server\\share\\a\\b",
3928 "\\\\?\\UNC\\server\\share\\a",
3929 true);
3930 tp!("\\\\?\\UNC\\server\\share\\a",
3931 "\\\\?\\UNC\\server\\share\\",
3932 true);
3933 tp!("\\\\?\\UNC\\server\\share",
3934 "\\\\?\\UNC\\server\\share",
3935 false);
3936 tp!("\\\\.\\a\\b\\c", "\\\\.\\a\\b", true);
3937 tp!("\\\\.\\a\\b", "\\\\.\\a\\", true);
3938 tp!("\\\\.\\a", "\\\\.\\a", false);
3939
3940 tp!("\\\\?\\a\\b\\", "\\\\?\\a\\", true);
3941 }
3942 }
3943
3944 #[test]
3945 pub fn test_set_file_name() {
3946 macro_rules! tfn(
3947 ($path:expr, $file:expr, $expected:expr) => ( {
3948 let mut p = PathBuf::from($path);
3949 p.set_file_name($file);
3950 assert!(p.to_str() == Some($expected),
3951 "setting file name of {:?} to {:?}: Expected {:?}, got {:?}",
3952 $path, $file, $expected,
3953 p.to_str().unwrap());
3954 });
3955 );
3956
3957 tfn!("foo", "foo", "foo");
3958 tfn!("foo", "bar", "bar");
3959 tfn!("foo", "", "");
3960 tfn!("", "foo", "foo");
3961 if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) {
3962 tfn!(".", "foo", "./foo");
3963 tfn!("foo/", "bar", "bar");
3964 tfn!("foo/.", "bar", "bar");
3965 tfn!("..", "foo", "../foo");
3966 tfn!("foo/..", "bar", "foo/../bar");
3967 tfn!("/", "foo", "/foo");
3968 } else {
3969 tfn!(".", "foo", r".\foo");
3970 tfn!(r"foo\", "bar", r"bar");
3971 tfn!(r"foo\.", "bar", r"bar");
3972 tfn!("..", "foo", r"..\foo");
3973 tfn!(r"foo\..", "bar", r"foo\..\bar");
3974 tfn!(r"\", "foo", r"\foo");
3975 }
3976 }
3977
3978 #[test]
3979 pub fn test_set_extension() {
3980 macro_rules! tfe(
3981 ($path:expr, $ext:expr, $expected:expr, $output:expr) => ( {
3982 let mut p = PathBuf::from($path);
3983 let output = p.set_extension($ext);
3984 assert!(p.to_str() == Some($expected) && output == $output,
3985 "setting extension of {:?} to {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
3986 $path, $ext, $expected, $output,
3987 p.to_str().unwrap(), output);
3988 });
3989 );
3990
3991 tfe!("foo", "txt", "foo.txt", true);
3992 tfe!("foo.bar", "txt", "foo.txt", true);
3993 tfe!("foo.bar.baz", "txt", "foo.bar.txt", true);
3994 tfe!(".test", "txt", ".test.txt", true);
3995 tfe!("foo.txt", "", "foo", true);
3996 tfe!("foo", "", "foo", true);
3997 tfe!("", "foo", "", false);
3998 tfe!(".", "foo", ".", false);
3999 tfe!("foo/", "bar", "foo.bar", true);
4000 tfe!("foo/.", "bar", "foo.bar", true);
4001 tfe!("..", "foo", "..", false);
4002 tfe!("foo/..", "bar", "foo/..", false);
4003 tfe!("/", "foo", "/", false);
4004 }
4005
4006 #[test]
4007 fn test_eq_receivers() {
4008 use crate::borrow::Cow;
4009
4010 let borrowed: &Path = Path::new("foo/bar");
4011 let mut owned: PathBuf = PathBuf::new();
4012 owned.push("foo");
4013 owned.push("bar");
4014 let borrowed_cow: Cow<'_, Path> = borrowed.into();
4015 let owned_cow: Cow<'_, Path> = owned.clone().into();
4016
4017 macro_rules! t {
4018 ($($current:expr),+) => {
4019 $(
4020 assert_eq!($current, borrowed);
4021 assert_eq!($current, owned);
4022 assert_eq!($current, borrowed_cow);
4023 assert_eq!($current, owned_cow);
4024 )+
4025 }
4026 }
4027
4028 t!(borrowed, owned, borrowed_cow, owned_cow);
4029 }
4030
4031 #[test]
4032 pub fn test_compare() {
4033 use crate::hash::{Hash, Hasher};
4034 use crate::collections::hash_map::DefaultHasher;
4035
4036 fn hash<T: Hash>(t: T) -> u64 {
4037 let mut s = DefaultHasher::new();
4038 t.hash(&mut s);
4039 s.finish()
4040 }
4041
4042 macro_rules! tc(
4043 ($path1:expr, $path2:expr, eq: $eq:expr,
4044 starts_with: $starts_with:expr, ends_with: $ends_with:expr,
4045 relative_from: $relative_from:expr) => ({
4046 let path1 = Path::new($path1);
4047 let path2 = Path::new($path2);
4048
4049 let eq = path1 == path2;
4050 assert!(eq == $eq, "{:?} == {:?}, expected {:?}, got {:?}",
4051 $path1, $path2, $eq, eq);
4052 assert!($eq == (hash(path1) == hash(path2)),
4053 "{:?} == {:?}, expected {:?}, got {} and {}",
4054 $path1, $path2, $eq, hash(path1), hash(path2));
4055
4056 let starts_with = path1.starts_with(path2);
4057 assert!(starts_with == $starts_with,
4058 "{:?}.starts_with({:?}), expected {:?}, got {:?}", $path1, $path2,
4059 $starts_with, starts_with);
4060
4061 let ends_with = path1.ends_with(path2);
4062 assert!(ends_with == $ends_with,
4063 "{:?}.ends_with({:?}), expected {:?}, got {:?}", $path1, $path2,
4064 $ends_with, ends_with);
4065
4066 let relative_from = path1.strip_prefix(path2)
4067 .map(|p| p.to_str().unwrap())
4068 .ok();
4069 let exp: Option<&str> = $relative_from;
4070 assert!(relative_from == exp,
4071 "{:?}.strip_prefix({:?}), expected {:?}, got {:?}",
4072 $path1, $path2, exp, relative_from);
4073 });
4074 );
4075
4076 tc!("", "",
4077 eq: true,
4078 starts_with: true,
4079 ends_with: true,
4080 relative_from: Some("")
4081 );
4082
4083 tc!("foo", "",
4084 eq: false,
4085 starts_with: true,
4086 ends_with: true,
4087 relative_from: Some("foo")
4088 );
4089
4090 tc!("", "foo",
4091 eq: false,
4092 starts_with: false,
4093 ends_with: false,
4094 relative_from: None
4095 );
4096
4097 tc!("foo", "foo",
4098 eq: true,
4099 starts_with: true,
4100 ends_with: true,
4101 relative_from: Some("")
4102 );
4103
4104 tc!("foo/", "foo",
4105 eq: true,
4106 starts_with: true,
4107 ends_with: true,
4108 relative_from: Some("")
4109 );
4110
4111 tc!("foo/bar", "foo",
4112 eq: false,
4113 starts_with: true,
4114 ends_with: false,
4115 relative_from: Some("bar")
4116 );
4117
4118 tc!("foo/bar/baz", "foo/bar",
4119 eq: false,
4120 starts_with: true,
4121 ends_with: false,
4122 relative_from: Some("baz")
4123 );
4124
4125 tc!("foo/bar", "foo/bar/baz",
4126 eq: false,
4127 starts_with: false,
4128 ends_with: false,
4129 relative_from: None
4130 );
4131
4132 tc!("./foo/bar/", ".",
4133 eq: false,
4134 starts_with: true,
4135 ends_with: false,
4136 relative_from: Some("foo/bar")
4137 );
4138
4139 if cfg!(windows) {
4140 tc!(r"C:\src\rust\cargo-test\test\Cargo.toml",
4141 r"c:\src\rust\cargo-test\test",
4142 eq: false,
4143 starts_with: true,
4144 ends_with: false,
4145 relative_from: Some("Cargo.toml")
4146 );
4147
4148 tc!(r"c:\foo", r"C:\foo",
4149 eq: true,
4150 starts_with: true,
4151 ends_with: true,
4152 relative_from: Some("")
4153 );
4154 }
4155 }
4156
4157 #[test]
4158 fn test_components_debug() {
4159 let path = Path::new("/tmp");
4160
4161 let mut components = path.components();
4162
4163 let expected = "Components([RootDir, Normal(\"tmp\")])";
4164 let actual = format!("{:?}", components);
4165 assert_eq!(expected, actual);
4166
4167 let _ = components.next().unwrap();
4168 let expected = "Components([Normal(\"tmp\")])";
4169 let actual = format!("{:?}", components);
4170 assert_eq!(expected, actual);
4171
4172 let _ = components.next().unwrap();
4173 let expected = "Components([])";
4174 let actual = format!("{:?}", components);
4175 assert_eq!(expected, actual);
4176 }
4177
4178 #[cfg(unix)]
4179 #[test]
4180 fn test_iter_debug() {
4181 let path = Path::new("/tmp");
4182
4183 let mut iter = path.iter();
4184
4185 let expected = "Iter([\"/\", \"tmp\"])";
4186 let actual = format!("{:?}", iter);
4187 assert_eq!(expected, actual);
4188
4189 let _ = iter.next().unwrap();
4190 let expected = "Iter([\"tmp\"])";
4191 let actual = format!("{:?}", iter);
4192 assert_eq!(expected, actual);
4193
4194 let _ = iter.next().unwrap();
4195 let expected = "Iter([])";
4196 let actual = format!("{:?}", iter);
4197 assert_eq!(expected, actual);
4198 }
4199
4200 #[test]
4201 fn into_boxed() {
4202 let orig: &str = "some/sort/of/path";
4203 let path = Path::new(orig);
4204 let boxed: Box<Path> = Box::from(path);
4205 let path_buf = path.to_owned().into_boxed_path().into_path_buf();
4206 assert_eq!(path, &*boxed);
4207 assert_eq!(&*boxed, &*path_buf);
4208 assert_eq!(&*path_buf, path);
4209 }
4210
4211 #[test]
4212 fn test_clone_into() {
4213 let mut path_buf = PathBuf::from("supercalifragilisticexpialidocious");
4214 let path = Path::new("short");
4215 path.clone_into(&mut path_buf);
4216 assert_eq!(path, path_buf);
4217 assert!(path_buf.into_os_string().capacity() >= 15);
4218 }
4219
4220 #[test]
4221 fn display_format_flags() {
4222 assert_eq!(format!("a{:#<5}b", Path::new("").display()), "a#####b");
4223 assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b");
4224 }
4225
4226 #[test]
4227 fn into_rc() {
4228 let orig = "hello/world";
4229 let path = Path::new(orig);
4230 let rc: Rc<Path> = Rc::from(path);
4231 let arc: Arc<Path> = Arc::from(path);
4232
4233 assert_eq!(&*rc, path);
4234 assert_eq!(&*arc, path);
4235
4236 let rc2: Rc<Path> = Rc::from(path.to_owned());
4237 let arc2: Arc<Path> = Arc::from(path.to_owned());
4238
4239 assert_eq!(&*rc2, path);
4240 assert_eq!(&*arc2, path);
4241 }
4242 }