]> git.proxmox.com Git - rustc.git/blame - library/std/src/path.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / library / std / src / path.rs
CommitLineData
85aaf69f
SL
1//! Cross-platform path manipulation.
2//!
dfeec247 3//! This module provides two types, [`PathBuf`] and [`Path`] (akin to [`String`]
32a655c1
SL
4//! and [`str`]), for working with paths abstractly. These types are thin wrappers
5//! around [`OsString`] and [`OsStr`] respectively, meaning that they work directly
85aaf69f
SL
6//! on strings according to the local platform's path syntax.
7//!
cc61c64b
XL
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//!
85aaf69f
SL
15//! ## Simple usage
16//!
c34b1796 17//! Path manipulation includes both parsing components from slices and building
85aaf69f
SL
18//! new owned paths.
19//!
32a655c1 20//! To parse a path, you can create a [`Path`] slice from a [`str`]
85aaf69f
SL
21//! slice and start asking questions:
22//!
32a655c1 23//! ```
85aaf69f 24//! use std::path::Path;
476ff2be 25//! use std::ffi::OsStr;
85aaf69f
SL
26//!
27//! let path = Path::new("/tmp/foo/bar.txt");
476ff2be
SL
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//!
85aaf69f 35//! let extension = path.extension();
476ff2be 36//! assert_eq!(extension, Some(OsStr::new("txt")));
85aaf69f
SL
37//! ```
38//!
32a655c1 39//! To build or modify paths, use [`PathBuf`]:
85aaf69f 40//!
32a655c1 41//! ```
85aaf69f
SL
42//! use std::path::PathBuf;
43//!
7cac9316 44//! // This way works...
c34b1796 45//! let mut path = PathBuf::from("c:\\");
7cac9316 46//!
85aaf69f
SL
47//! path.push("windows");
48//! path.push("system32");
7cac9316 49//!
85aaf69f 50//! path.set_extension("dll");
7cac9316
XL
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();
85aaf69f
SL
55//! ```
56//!
3dfed10e
XL
57//! [`components`]: Path::components
58//! [`push`]: PathBuf::push
85aaf69f 59
c34b1796 60#![stable(feature = "rust1", since = "1.0.0")]
1b1a35ee
XL
61#![deny(unsafe_op_in_unsafe_fn)]
62
63#[cfg(test)]
64mod tests;
85aaf69f 65
532ac7d7
XL
66use crate::borrow::{Borrow, Cow};
67use crate::cmp;
68use crate::error::Error;
69use crate::fmt;
70use crate::fs;
71use crate::hash::{Hash, Hasher};
72use crate::io;
73use crate::iter::{self, FusedIterator};
74use crate::ops::{self, Deref};
75use crate::rc::Rc;
76use crate::str::FromStr;
77use crate::sync::Arc;
78
79use crate::ffi::{OsStr, OsString};
80
60c5eb7d 81use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR};
85aaf69f
SL
82
83////////////////////////////////////////////////////////////////////////////////
84// GENERAL NOTES
85////////////////////////////////////////////////////////////////////////////////
86//
87// Parsing in this module is done by directly transmuting OsStr to [u8] slices,
88// taking advantage of the fact that OsStr always encodes ASCII characters
89// as-is. Eventually, this transmutation should be replaced by direct uses of
90// OsStr APIs for parsing, but it will take a while for those to become
91// available.
92
85aaf69f
SL
93////////////////////////////////////////////////////////////////////////////////
94// Windows Prefixes
95////////////////////////////////////////////////////////////////////////////////
96
0731742a 97/// Windows path prefixes, e.g., `C:` or `\\server\share`.
85aaf69f 98///
cc61c64b
XL
99/// Windows uses a variety of path prefix styles, including references to drive
100/// volumes (like `C:`), network shared folders (like `\\server\share`), and
0731742a 101/// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with
cc61c64b
XL
102/// `\\?\`), in which case `/` is *not* treated as a separator and essentially
103/// no normalization is performed.
104///
105/// # Examples
106///
107/// ```
108/// use std::path::{Component, Path, Prefix};
109/// use std::path::Prefix::*;
110/// use std::ffi::OsStr;
111///
112/// fn get_path_prefix(s: &str) -> Prefix {
113/// let path = Path::new(s);
114/// match path.components().next().unwrap() {
115/// Component::Prefix(prefix_component) => prefix_component.kind(),
116/// _ => panic!(),
117/// }
118/// }
119///
120/// # if cfg!(windows) {
121/// assert_eq!(Verbatim(OsStr::new("pictures")),
122/// get_path_prefix(r"\\?\pictures\kittens"));
123/// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")),
124/// get_path_prefix(r"\\?\UNC\server\share"));
041b39d2 125/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\"));
cc61c64b
XL
126/// assert_eq!(DeviceNS(OsStr::new("BrainInterface")),
127/// get_path_prefix(r"\\.\BrainInterface"));
128/// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")),
129/// get_path_prefix(r"\\server\share"));
041b39d2 130/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));
cc61c64b
XL
131/// # }
132/// ```
85aaf69f 133#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
c34b1796 134#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 135pub enum Prefix<'a> {
0731742a 136 /// Verbatim prefix, e.g., `\\?\cat_pics`.
cc61c64b
XL
137 ///
138 /// Verbatim prefixes consist of `\\?\` immediately followed by the given
139 /// component.
c34b1796 140 #[stable(feature = "rust1", since = "1.0.0")]
7453a54e 141 Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
85aaf69f 142
cc61c64b 143 /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_,
0731742a 144 /// e.g., `\\?\UNC\server\share`.
cc61c64b
XL
145 ///
146 /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the
147 /// server's hostname and a share name.
c34b1796 148 #[stable(feature = "rust1", since = "1.0.0")]
9cc50fc6 149 VerbatimUNC(
7453a54e
SL
150 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
151 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
9cc50fc6 152 ),
85aaf69f 153
f9f354fc 154 /// Verbatim disk prefix, e.g., `\\?\C:`.
cc61c64b
XL
155 ///
156 /// Verbatim disk prefixes consist of `\\?\` immediately followed by the
f9f354fc 157 /// drive letter and `:`.
c34b1796 158 #[stable(feature = "rust1", since = "1.0.0")]
7453a54e 159 VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),
85aaf69f 160
0731742a 161 /// Device namespace prefix, e.g., `\\.\COM42`.
cc61c64b
XL
162 ///
163 /// Device namespace prefixes consist of `\\.\` immediately followed by the
164 /// device name.
c34b1796 165 #[stable(feature = "rust1", since = "1.0.0")]
7453a54e 166 DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
85aaf69f 167
cc61c64b
XL
168 /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g.
169 /// `\\server\share`.
170 ///
171 /// UNC prefixes consist of the server's hostname and a share name.
c34b1796 172 #[stable(feature = "rust1", since = "1.0.0")]
9cc50fc6 173 UNC(
7453a54e
SL
174 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
175 #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,
9cc50fc6 176 ),
85aaf69f
SL
177
178 /// Prefix `C:` for the given disk drive.
c34b1796 179 #[stable(feature = "rust1", since = "1.0.0")]
7453a54e 180 Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),
85aaf69f
SL
181}
182
183impl<'a> Prefix<'a> {
184 #[inline]
185 fn len(&self) -> usize {
186 use self::Prefix::*;
187 fn os_str_len(s: &OsStr) -> usize {
188 os_str_as_u8_slice(s).len()
189 }
190 match *self {
191 Verbatim(x) => 4 + os_str_len(x),
92a42be0 192 VerbatimUNC(x, y) => {
60c5eb7d
XL
193 8 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 }
194 }
85aaf69f 195 VerbatimDisk(_) => 6,
60c5eb7d 196 UNC(x, y) => 2 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 },
85aaf69f 197 DeviceNS(x) => 4 + os_str_len(x),
92a42be0 198 Disk(_) => 2,
85aaf69f 199 }
85aaf69f
SL
200 }
201
0731742a 202 /// Determines if the prefix is verbatim, i.e., begins with `\\?\`.
cc61c64b
XL
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// use std::path::Prefix::*;
208 /// use std::ffi::OsStr;
209 ///
210 /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim());
211 /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
041b39d2 212 /// assert!(VerbatimDisk(b'C').is_verbatim());
cc61c64b
XL
213 /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim());
214 /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());
041b39d2 215 /// assert!(!Disk(b'C').is_verbatim());
cc61c64b 216 /// ```
85aaf69f 217 #[inline]
c34b1796 218 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
219 pub fn is_verbatim(&self) -> bool {
220 use self::Prefix::*;
dfeec247 221 matches!(*self, Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..))
85aaf69f
SL
222 }
223
224 #[inline]
225 fn is_drive(&self) -> bool {
dfeec247 226 matches!(*self, Prefix::Disk(_))
85aaf69f
SL
227 }
228
229 #[inline]
230 fn has_implicit_root(&self) -> bool {
231 !self.is_drive()
232 }
233}
234
235////////////////////////////////////////////////////////////////////////////////
236// Exposed parsing helpers
237////////////////////////////////////////////////////////////////////////////////
238
9346a6ac 239/// Determines whether the character is one of the permitted path
85aaf69f 240/// separators for the current platform.
c34b1796
AL
241///
242/// # Examples
243///
244/// ```
245/// use std::path;
246///
041b39d2 247/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows
c34b1796
AL
248/// assert!(!path::is_separator('❤'));
249/// ```
250#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 251pub fn is_separator(c: char) -> bool {
85aaf69f
SL
252 c.is_ascii() && is_sep_byte(c as u8)
253}
254
476ff2be
SL
255/// The primary separator of path components for the current platform.
256///
257/// For example, `/` on Unix and `\` on Windows.
c34b1796 258#[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 259pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
85aaf69f
SL
260
261////////////////////////////////////////////////////////////////////////////////
262// Misc helpers
263////////////////////////////////////////////////////////////////////////////////
264
265// Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
266// is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
267// `iter` after having exhausted `prefix`.
83c7162d 268fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
60c5eb7d
XL
269where
270 I: Iterator<Item = Component<'a>> + Clone,
271 J: Iterator<Item = Component<'b>>,
85aaf69f
SL
272{
273 loop {
274 let mut iter_next = iter.clone();
275 match (iter_next.next(), prefix.next()) {
7453a54e
SL
276 (Some(ref x), Some(ref y)) if x == y => (),
277 (Some(_), Some(_)) => return None,
85aaf69f
SL
278 (Some(_), None) => return Some(iter),
279 (None, None) => return Some(iter),
280 (None, Some(_)) => return None,
281 }
282 iter = iter_next;
283 }
284}
285
286// See note at the top of this module to understand why these are used:
dfeec247
XL
287//
288// These casts are safe as OsStr is internally a wrapper around [u8] on all
289// platforms.
290//
291// Note that currently this relies on the special knowledge that libstd has;
292// these types are single-element structs but are not marked repr(transparent)
293// or repr(C) which would make these casts allowable outside std.
85aaf69f 294fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
ea8adc8c 295 unsafe { &*(s as *const OsStr as *const [u8]) }
85aaf69f
SL
296}
297unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
1b1a35ee
XL
298 // SAFETY: see the comment of `os_str_as_u8_slice`
299 unsafe { &*(s as *const [u8] as *const OsStr) }
85aaf69f
SL
300}
301
3b2f2976
XL
302// Detect scheme on Redox
303fn has_redox_scheme(s: &[u8]) -> bool {
416331ca 304 cfg!(target_os = "redox") && s.contains(&b':')
3b2f2976
XL
305}
306
85aaf69f 307////////////////////////////////////////////////////////////////////////////////
c34b1796 308// Cross-platform, iterator-independent parsing
85aaf69f
SL
309////////////////////////////////////////////////////////////////////////////////
310
85aaf69f 311/// Says whether the first byte after the prefix is a separator.
532ac7d7 312fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
60c5eb7d 313 let path = if let Some(p) = prefix { &s[p.len()..] } else { s };
9346a6ac 314 !path.is_empty() && is_sep_byte(path[0])
85aaf69f
SL
315}
316
85aaf69f 317// basic workhorse for splitting stem and extension
85aaf69f 318fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
1b1a35ee
XL
319 if os_str_as_u8_slice(file) == b".." {
320 return (Some(file), None);
321 }
85aaf69f 322
1b1a35ee
XL
323 // The unsafety here stems from converting between &OsStr and &[u8]
324 // and back. This is safe to do because (1) we only look at ASCII
325 // contents of the encoding and (2) new &OsStr values are produced
326 // only from ASCII-bounded slices of existing &OsStr values.
327 let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
328 let after = iter.next();
329 let before = iter.next();
330 if before == Some(b"") {
331 (Some(file), None)
332 } else {
333 unsafe { (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) }
85aaf69f
SL
334 }
335}
336
337////////////////////////////////////////////////////////////////////////////////
338// The core iterators
339////////////////////////////////////////////////////////////////////////////////
340
341/// Component parsing works by a double-ended state machine; the cursors at the
342/// front and back of the path each keep track of what parts of the path have
343/// been consumed so far.
344///
c34b1796
AL
345/// Going front to back, a path is made up of a prefix, a starting
346/// directory component, and a body (of normal components)
85aaf69f
SL
347#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
348enum State {
60c5eb7d
XL
349 Prefix = 0, // c:
350 StartDir = 1, // / or . or nothing
351 Body = 2, // foo/bar/baz
c34b1796
AL
352 Done = 3,
353}
354
cc61c64b
XL
355/// A structure wrapping a Windows path prefix as well as its unparsed string
356/// representation.
357///
358/// In addition to the parsed [`Prefix`] information returned by [`kind`],
359/// `PrefixComponent` also holds the raw and unparsed [`OsStr`] slice,
360/// returned by [`as_os_str`].
361///
362/// Instances of this `struct` can be obtained by matching against the
363/// [`Prefix` variant] on [`Component`].
c34b1796
AL
364///
365/// Does not occur on Unix.
cc61c64b
XL
366///
367/// # Examples
368///
369/// ```
370/// # if cfg!(windows) {
371/// use std::path::{Component, Path, Prefix};
372/// use std::ffi::OsStr;
373///
374/// let path = Path::new(r"c:\you\later\");
375/// match path.components().next().unwrap() {
376/// Component::Prefix(prefix_component) => {
041b39d2 377/// assert_eq!(Prefix::Disk(b'C'), prefix_component.kind());
cc61c64b
XL
378/// assert_eq!(OsStr::new("c:"), prefix_component.as_os_str());
379/// }
380/// _ => unreachable!(),
381/// }
382/// # }
383/// ```
384///
3dfed10e
XL
385/// [`as_os_str`]: PrefixComponent::as_os_str
386/// [`kind`]: PrefixComponent::kind
387/// [`Prefix` variant]: Component::Prefix
c34b1796 388#[stable(feature = "rust1", since = "1.0.0")]
92a42be0 389#[derive(Copy, Clone, Eq, Debug)]
c34b1796
AL
390pub struct PrefixComponent<'a> {
391 /// The prefix as an unparsed `OsStr` slice.
392 raw: &'a OsStr,
393
394 /// The parsed prefix data.
395 parsed: Prefix<'a>,
396}
397
398impl<'a> PrefixComponent<'a> {
cc61c64b
XL
399 /// Returns the parsed prefix data.
400 ///
401 /// See [`Prefix`]'s documentation for more information on the different
402 /// kinds of prefixes.
c34b1796 403 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 404 #[inline]
c34b1796
AL
405 pub fn kind(&self) -> Prefix<'a> {
406 self.parsed
407 }
408
cc61c64b 409 /// Returns the raw [`OsStr`] slice for this prefix.
c34b1796 410 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 411 #[inline]
c34b1796
AL
412 pub fn as_os_str(&self) -> &'a OsStr {
413 self.raw
414 }
415}
416
417#[stable(feature = "rust1", since = "1.0.0")]
418impl<'a> cmp::PartialEq for PrefixComponent<'a> {
5869c6ff 419 #[inline]
c34b1796
AL
420 fn eq(&self, other: &PrefixComponent<'a>) -> bool {
421 cmp::PartialEq::eq(&self.parsed, &other.parsed)
422 }
423}
424
425#[stable(feature = "rust1", since = "1.0.0")]
426impl<'a> cmp::PartialOrd for PrefixComponent<'a> {
5869c6ff 427 #[inline]
c34b1796
AL
428 fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> {
429 cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed)
430 }
431}
432
433#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 434impl cmp::Ord for PrefixComponent<'_> {
5869c6ff 435 #[inline]
9fa01778 436 fn cmp(&self, other: &Self) -> cmp::Ordering {
c34b1796
AL
437 cmp::Ord::cmp(&self.parsed, &other.parsed)
438 }
85aaf69f
SL
439}
440
92a42be0 441#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 442impl Hash for PrefixComponent<'_> {
92a42be0
SL
443 fn hash<H: Hasher>(&self, h: &mut H) {
444 self.parsed.hash(h);
445 }
446}
447
85aaf69f
SL
448/// A single component of a path.
449///
3b2f2976 450/// A `Component` roughly corresponds to a substring between path separators
cc61c64b 451/// (`/` or `\`).
3157f602 452///
cc61c64b 453/// This `enum` is created by iterating over [`Components`], which in turn is
29967ef6 454/// created by the [`components`](Path::components) method on [`Path`].
3157f602
XL
455///
456/// # Examples
457///
458/// ```rust
459/// use std::path::{Component, Path};
460///
461/// let path = Path::new("/tmp/foo/bar.txt");
462/// let components = path.components().collect::<Vec<_>>();
463/// assert_eq!(&components, &[
464/// Component::RootDir,
465/// Component::Normal("tmp".as_ref()),
466/// Component::Normal("foo".as_ref()),
467/// Component::Normal("bar.txt".as_ref()),
468/// ]);
469/// ```
85aaf69f 470#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
c34b1796 471#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 472pub enum Component<'a> {
0731742a 473 /// A Windows path prefix, e.g., `C:` or `\\server\share`.
85aaf69f 474 ///
cc61c64b
XL
475 /// There is a large variety of prefix types, see [`Prefix`]'s documentation
476 /// for more.
477 ///
85aaf69f 478 /// Does not occur on Unix.
c34b1796 479 #[stable(feature = "rust1", since = "1.0.0")]
60c5eb7d 480 Prefix(#[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>),
85aaf69f 481
cc61c64b
XL
482 /// The root directory component, appears after any prefix and before anything else.
483 ///
484 /// It represents a separator that designates that a path starts from root.
c34b1796 485 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
486 RootDir,
487
0731742a 488 /// A reference to the current directory, i.e., `.`.
c34b1796 489 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
490 CurDir,
491
0731742a 492 /// A reference to the parent directory, i.e., `..`.
c34b1796 493 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
494 ParentDir,
495
0731742a 496 /// A normal component, e.g., `a` and `b` in `a/b`.
cc61c64b
XL
497 ///
498 /// This variant is the most common one, it represents references to files
499 /// or directories.
c34b1796 500 #[stable(feature = "rust1", since = "1.0.0")]
7453a54e 501 Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),
85aaf69f
SL
502}
503
504impl<'a> Component<'a> {
cc61c64b 505 /// Extracts the underlying [`OsStr`] slice.
476ff2be
SL
506 ///
507 /// # Examples
508 ///
509 /// ```
510 /// use std::path::Path;
511 ///
512 /// let path = Path::new("./tmp/foo/bar.txt");
513 /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();
514 /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
515 /// ```
c34b1796 516 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
517 pub fn as_os_str(self) -> &'a OsStr {
518 match self {
c34b1796
AL
519 Component::Prefix(p) => p.as_os_str(),
520 Component::RootDir => OsStr::new(MAIN_SEP_STR),
521 Component::CurDir => OsStr::new("."),
522 Component::ParentDir => OsStr::new(".."),
85aaf69f
SL
523 Component::Normal(path) => path,
524 }
525 }
526}
527
c34b1796 528#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 529impl AsRef<OsStr> for Component<'_> {
5869c6ff 530 #[inline]
c34b1796
AL
531 fn as_ref(&self) -> &OsStr {
532 self.as_os_str()
533 }
534}
535
0531ce1d 536#[stable(feature = "path_component_asref", since = "1.25.0")]
9fa01778 537impl AsRef<Path> for Component<'_> {
5869c6ff 538 #[inline]
2c00a5a8
XL
539 fn as_ref(&self) -> &Path {
540 self.as_os_str().as_ref()
541 }
542}
543
3b2f2976 544/// An iterator over the [`Component`]s of a [`Path`].
c34b1796 545///
cc61c64b
XL
546/// This `struct` is created by the [`components`] method on [`Path`].
547/// See its documentation for more.
3157f602 548///
c34b1796
AL
549/// # Examples
550///
551/// ```
552/// use std::path::Path;
553///
554/// let path = Path::new("/tmp/foo/bar.txt");
555///
556/// for component in path.components() {
557/// println!("{:?}", component);
558/// }
559/// ```
3157f602 560///
3dfed10e 561/// [`components`]: Path::components
85aaf69f 562#[derive(Clone)]
c34b1796 563#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
564pub struct Components<'a> {
565 // The path left to parse components from
566 path: &'a [u8],
567
568 // The prefix as it was originally parsed, if any
569 prefix: Option<Prefix<'a>>,
570
571 // true if path *physically* has a root separator; for most Windows
17df50a5 572 // prefixes, it may have a "logical" root separator for the purposes of
0731742a 573 // normalization, e.g., \\server\share == \\server\share\.
85aaf69f
SL
574 has_physical_root: bool,
575
576 // The iterator is double-ended, and these two states keep track of what has
577 // been produced from either end
578 front: State,
579 back: State,
580}
581
cc61c64b 582/// An iterator over the [`Component`]s of a [`Path`], as [`OsStr`] slices.
32a655c1 583///
cc61c64b
XL
584/// This `struct` is created by the [`iter`] method on [`Path`].
585/// See its documentation for more.
586///
3dfed10e 587/// [`iter`]: Path::iter
85aaf69f 588#[derive(Clone)]
c34b1796 589#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 590pub struct Iter<'a> {
92a42be0 591 inner: Components<'a>,
85aaf69f
SL
592}
593
9e0c209e 594#[stable(feature = "path_components_debug", since = "1.13.0")]
9fa01778 595impl fmt::Debug for Components<'_> {
532ac7d7 596 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9e0c209e
SL
597 struct DebugHelper<'a>(&'a Path);
598
9fa01778 599 impl fmt::Debug for DebugHelper<'_> {
532ac7d7 600 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60c5eb7d 601 f.debug_list().entries(self.0.components()).finish()
9e0c209e
SL
602 }
603 }
604
60c5eb7d 605 f.debug_tuple("Components").field(&DebugHelper(self.as_path())).finish()
9e0c209e
SL
606 }
607}
608
85aaf69f
SL
609impl<'a> Components<'a> {
610 // how long is the prefix, if any?
611 #[inline]
612 fn prefix_len(&self) -> usize {
613 self.prefix.as_ref().map(Prefix::len).unwrap_or(0)
614 }
615
616 #[inline]
617 fn prefix_verbatim(&self) -> bool {
618 self.prefix.as_ref().map(Prefix::is_verbatim).unwrap_or(false)
619 }
620
621 /// how much of the prefix is left from the point of view of iteration?
622 #[inline]
623 fn prefix_remaining(&self) -> usize {
60c5eb7d 624 if self.front == State::Prefix { self.prefix_len() } else { 0 }
85aaf69f
SL
625 }
626
c34b1796
AL
627 // Given the iteration so far, how much of the pre-State::Body path is left?
628 #[inline]
629 fn len_before_body(&self) -> usize {
60c5eb7d
XL
630 let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 };
631 let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 };
c34b1796 632 self.prefix_remaining() + root + cur_dir
85aaf69f
SL
633 }
634
635 // is the iteration complete?
636 #[inline]
637 fn finished(&self) -> bool {
638 self.front == State::Done || self.back == State::Done || self.front > self.back
639 }
640
641 #[inline]
642 fn is_sep_byte(&self, b: u8) -> bool {
60c5eb7d 643 if self.prefix_verbatim() { is_verbatim_sep(b) } else { is_sep_byte(b) }
85aaf69f
SL
644 }
645
9346a6ac 646 /// Extracts a slice corresponding to the portion of the path remaining for iteration.
c34b1796
AL
647 ///
648 /// # Examples
649 ///
650 /// ```
651 /// use std::path::Path;
652 ///
e9174d1e
SL
653 /// let mut components = Path::new("/tmp/foo/bar.txt").components();
654 /// components.next();
655 /// components.next();
c34b1796 656 ///
e9174d1e 657 /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());
c34b1796
AL
658 /// ```
659 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
660 pub fn as_path(&self) -> &'a Path {
661 let mut comps = self.clone();
92a42be0
SL
662 if comps.front == State::Body {
663 comps.trim_left();
664 }
665 if comps.back == State::Body {
666 comps.trim_right();
667 }
c34b1796 668 unsafe { Path::from_u8_slice(comps.path) }
85aaf69f
SL
669 }
670
671 /// Is the *original* path rooted?
672 fn has_root(&self) -> bool {
92a42be0
SL
673 if self.has_physical_root {
674 return true;
675 }
85aaf69f 676 if let Some(p) = self.prefix {
92a42be0
SL
677 if p.has_implicit_root() {
678 return true;
679 }
85aaf69f
SL
680 }
681 false
682 }
683
c34b1796
AL
684 /// Should the normalized path include a leading . ?
685 fn include_cur_dir(&self) -> bool {
92a42be0
SL
686 if self.has_root() {
687 return false;
688 }
c34b1796
AL
689 let mut iter = self.path[self.prefix_len()..].iter();
690 match (iter.next(), iter.next()) {
691 (Some(&b'.'), None) => true,
692 (Some(&b'.'), Some(&b)) => self.is_sep_byte(b),
92a42be0 693 _ => false,
c34b1796
AL
694 }
695 }
696
697 // parse a given byte sequence into the corresponding path component
698 fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
699 match comp {
700 b"." if self.prefix_verbatim() => Some(Component::CurDir),
701 b"." => None, // . components are normalized away, except at
60c5eb7d
XL
702 // the beginning of a path, which is treated
703 // separately via `include_cur_dir`
c34b1796
AL
704 b".." => Some(Component::ParentDir),
705 b"" => None,
92a42be0 706 _ => Some(Component::Normal(unsafe { u8_slice_as_os_str(comp) })),
c34b1796
AL
707 }
708 }
709
85aaf69f
SL
710 // parse a component from the left, saying how many bytes to consume to
711 // remove the component
712 fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {
713 debug_assert!(self.front == State::Body);
714 let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) {
715 None => (0, self.path),
92a42be0 716 Some(i) => (1, &self.path[..i]),
85aaf69f 717 };
c34b1796 718 (comp.len() + extra, self.parse_single_component(comp))
85aaf69f
SL
719 }
720
721 // parse a component from the right, saying how many bytes to consume to
722 // remove the component
723 fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {
724 debug_assert!(self.back == State::Body);
c34b1796 725 let start = self.len_before_body();
85aaf69f 726 let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) {
92a42be0
SL
727 None => (0, &self.path[start..]),
728 Some(i) => (1, &self.path[start + i + 1..]),
85aaf69f 729 };
c34b1796 730 (comp.len() + extra, self.parse_single_component(comp))
85aaf69f
SL
731 }
732
0731742a 733 // trim away repeated separators (i.e., empty components) on the left
85aaf69f
SL
734 fn trim_left(&mut self) {
735 while !self.path.is_empty() {
736 let (size, comp) = self.parse_next_component();
737 if comp.is_some() {
738 return;
739 } else {
92a42be0 740 self.path = &self.path[size..];
85aaf69f
SL
741 }
742 }
743 }
744
0731742a 745 // trim away repeated separators (i.e., empty components) on the right
85aaf69f 746 fn trim_right(&mut self) {
c34b1796 747 while self.path.len() > self.len_before_body() {
85aaf69f
SL
748 let (size, comp) = self.parse_next_component_back();
749 if comp.is_some() {
750 return;
751 } else {
92a42be0 752 self.path = &self.path[..self.path.len() - size];
85aaf69f
SL
753 }
754 }
755 }
85aaf69f
SL
756}
757
c34b1796 758#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 759impl AsRef<Path> for Components<'_> {
5869c6ff 760 #[inline]
c34b1796
AL
761 fn as_ref(&self) -> &Path {
762 self.as_path()
763 }
764}
765
766#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 767impl AsRef<OsStr> for Components<'_> {
5869c6ff 768 #[inline]
c34b1796
AL
769 fn as_ref(&self) -> &OsStr {
770 self.as_path().as_os_str()
771 }
772}
773
9e0c209e 774#[stable(feature = "path_iter_debug", since = "1.13.0")]
9fa01778 775impl fmt::Debug for Iter<'_> {
532ac7d7 776 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9e0c209e
SL
777 struct DebugHelper<'a>(&'a Path);
778
9fa01778 779 impl fmt::Debug for DebugHelper<'_> {
532ac7d7 780 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60c5eb7d 781 f.debug_list().entries(self.0.iter()).finish()
9e0c209e
SL
782 }
783 }
784
60c5eb7d 785 f.debug_tuple("Iter").field(&DebugHelper(self.as_path())).finish()
9e0c209e
SL
786 }
787}
788
85aaf69f 789impl<'a> Iter<'a> {
9346a6ac 790 /// Extracts a slice corresponding to the portion of the path remaining for iteration.
cc61c64b
XL
791 ///
792 /// # Examples
793 ///
794 /// ```
795 /// use std::path::Path;
796 ///
797 /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();
798 /// iter.next();
799 /// iter.next();
800 ///
801 /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());
802 /// ```
c34b1796 803 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 804 #[inline]
85aaf69f
SL
805 pub fn as_path(&self) -> &'a Path {
806 self.inner.as_path()
807 }
808}
809
c34b1796 810#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 811impl AsRef<Path> for Iter<'_> {
5869c6ff 812 #[inline]
c34b1796
AL
813 fn as_ref(&self) -> &Path {
814 self.as_path()
815 }
816}
817
818#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 819impl AsRef<OsStr> for Iter<'_> {
5869c6ff 820 #[inline]
c34b1796
AL
821 fn as_ref(&self) -> &OsStr {
822 self.as_path().as_os_str()
823 }
824}
825
826#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
827impl<'a> Iterator for Iter<'a> {
828 type Item = &'a OsStr;
829
5869c6ff 830 #[inline]
85aaf69f
SL
831 fn next(&mut self) -> Option<&'a OsStr> {
832 self.inner.next().map(Component::as_os_str)
833 }
834}
835
c34b1796 836#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 837impl<'a> DoubleEndedIterator for Iter<'a> {
5869c6ff 838 #[inline]
85aaf69f
SL
839 fn next_back(&mut self) -> Option<&'a OsStr> {
840 self.inner.next_back().map(Component::as_os_str)
841 }
842}
843
0531ce1d 844#[stable(feature = "fused", since = "1.26.0")]
9fa01778 845impl FusedIterator for Iter<'_> {}
9e0c209e 846
c34b1796 847#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
848impl<'a> Iterator for Components<'a> {
849 type Item = Component<'a>;
850
851 fn next(&mut self) -> Option<Component<'a>> {
852 while !self.finished() {
853 match self.front {
854 State::Prefix if self.prefix_len() > 0 => {
c34b1796 855 self.front = State::StartDir;
85aaf69f 856 debug_assert!(self.prefix_len() <= self.path.len());
92a42be0
SL
857 let raw = &self.path[..self.prefix_len()];
858 self.path = &self.path[self.prefix_len()..];
c34b1796 859 return Some(Component::Prefix(PrefixComponent {
85aaf69f 860 raw: unsafe { u8_slice_as_os_str(raw) },
92a42be0
SL
861 parsed: self.prefix.unwrap(),
862 }));
85aaf69f
SL
863 }
864 State::Prefix => {
c34b1796 865 self.front = State::StartDir;
85aaf69f 866 }
c34b1796 867 State::StartDir => {
85aaf69f
SL
868 self.front = State::Body;
869 if self.has_physical_root {
9346a6ac 870 debug_assert!(!self.path.is_empty());
85aaf69f 871 self.path = &self.path[1..];
92a42be0 872 return Some(Component::RootDir);
85aaf69f
SL
873 } else if let Some(p) = self.prefix {
874 if p.has_implicit_root() && !p.is_verbatim() {
92a42be0 875 return Some(Component::RootDir);
85aaf69f 876 }
c34b1796 877 } else if self.include_cur_dir() {
9346a6ac 878 debug_assert!(!self.path.is_empty());
c34b1796 879 self.path = &self.path[1..];
92a42be0 880 return Some(Component::CurDir);
85aaf69f
SL
881 }
882 }
883 State::Body if !self.path.is_empty() => {
884 let (size, comp) = self.parse_next_component();
92a42be0
SL
885 self.path = &self.path[size..];
886 if comp.is_some() {
887 return comp;
888 }
85aaf69f
SL
889 }
890 State::Body => {
85aaf69f 891 self.front = State::Done;
85aaf69f 892 }
92a42be0 893 State::Done => unreachable!(),
85aaf69f
SL
894 }
895 }
896 None
897 }
898}
899
c34b1796 900#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
901impl<'a> DoubleEndedIterator for Components<'a> {
902 fn next_back(&mut self) -> Option<Component<'a>> {
903 while !self.finished() {
904 match self.back {
c34b1796 905 State::Body if self.path.len() > self.len_before_body() => {
85aaf69f 906 let (size, comp) = self.parse_next_component_back();
92a42be0
SL
907 self.path = &self.path[..self.path.len() - size];
908 if comp.is_some() {
909 return comp;
910 }
85aaf69f
SL
911 }
912 State::Body => {
c34b1796 913 self.back = State::StartDir;
85aaf69f 914 }
c34b1796 915 State::StartDir => {
85aaf69f
SL
916 self.back = State::Prefix;
917 if self.has_physical_root {
92a42be0
SL
918 self.path = &self.path[..self.path.len() - 1];
919 return Some(Component::RootDir);
85aaf69f
SL
920 } else if let Some(p) = self.prefix {
921 if p.has_implicit_root() && !p.is_verbatim() {
92a42be0 922 return Some(Component::RootDir);
85aaf69f 923 }
c34b1796 924 } else if self.include_cur_dir() {
92a42be0
SL
925 self.path = &self.path[..self.path.len() - 1];
926 return Some(Component::CurDir);
85aaf69f
SL
927 }
928 }
929 State::Prefix if self.prefix_len() > 0 => {
930 self.back = State::Done;
c34b1796 931 return Some(Component::Prefix(PrefixComponent {
85aaf69f 932 raw: unsafe { u8_slice_as_os_str(self.path) },
92a42be0
SL
933 parsed: self.prefix.unwrap(),
934 }));
85aaf69f
SL
935 }
936 State::Prefix => {
937 self.back = State::Done;
92a42be0 938 return None;
85aaf69f 939 }
92a42be0 940 State::Done => unreachable!(),
85aaf69f
SL
941 }
942 }
943 None
944 }
945}
946
0531ce1d 947#[stable(feature = "fused", since = "1.26.0")]
9fa01778 948impl FusedIterator for Components<'_> {}
9e0c209e 949
c34b1796 950#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 951impl<'a> cmp::PartialEq for Components<'a> {
5869c6ff 952 #[inline]
85aaf69f 953 fn eq(&self, other: &Components<'a>) -> bool {
136023e0 954 Iterator::eq(self.clone().rev(), other.clone().rev())
85aaf69f
SL
955 }
956}
957
c34b1796 958#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 959impl cmp::Eq for Components<'_> {}
85aaf69f 960
c34b1796 961#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 962impl<'a> cmp::PartialOrd for Components<'a> {
5869c6ff 963 #[inline]
85aaf69f 964 fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
e9174d1e 965 Iterator::partial_cmp(self.clone(), other.clone())
85aaf69f
SL
966 }
967}
968
c34b1796 969#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 970impl cmp::Ord for Components<'_> {
5869c6ff 971 #[inline]
9fa01778 972 fn cmp(&self, other: &Self) -> cmp::Ordering {
e9174d1e 973 Iterator::cmp(self.clone(), other.clone())
85aaf69f
SL
974 }
975}
976
0531ce1d
XL
977/// An iterator over [`Path`] and its ancestors.
978///
979/// This `struct` is created by the [`ancestors`] method on [`Path`].
980/// See its documentation for more.
981///
982/// # Examples
983///
984/// ```
0531ce1d
XL
985/// use std::path::Path;
986///
987/// let path = Path::new("/foo/bar");
988///
989/// for ancestor in path.ancestors() {
990/// println!("{}", ancestor.display());
991/// }
992/// ```
993///
3dfed10e 994/// [`ancestors`]: Path::ancestors
0531ce1d 995#[derive(Copy, Clone, Debug)]
94b46f34 996#[stable(feature = "path_ancestors", since = "1.28.0")]
0531ce1d
XL
997pub struct Ancestors<'a> {
998 next: Option<&'a Path>,
999}
1000
94b46f34 1001#[stable(feature = "path_ancestors", since = "1.28.0")]
0531ce1d
XL
1002impl<'a> Iterator for Ancestors<'a> {
1003 type Item = &'a Path;
1004
5869c6ff 1005 #[inline]
0531ce1d
XL
1006 fn next(&mut self) -> Option<Self::Item> {
1007 let next = self.next;
8faf50e0 1008 self.next = next.and_then(Path::parent);
0531ce1d
XL
1009 next
1010 }
1011}
1012
94b46f34 1013#[stable(feature = "path_ancestors", since = "1.28.0")]
9fa01778 1014impl FusedIterator for Ancestors<'_> {}
0531ce1d 1015
85aaf69f
SL
1016////////////////////////////////////////////////////////////////////////////////
1017// Basic types and traits
1018////////////////////////////////////////////////////////////////////////////////
1019
9e0c209e
SL
1020/// An owned, mutable path (akin to [`String`]).
1021///
1022/// This type provides methods like [`push`] and [`set_extension`] that mutate
1023/// the path in place. It also implements [`Deref`] to [`Path`], meaning that
1024/// all methods on [`Path`] slices are available on `PathBuf` values as well.
85aaf69f 1025///
3dfed10e
XL
1026/// [`push`]: PathBuf::push
1027/// [`set_extension`]: PathBuf::set_extension
85aaf69f
SL
1028///
1029/// More details about the overall approach can be found in
29967ef6 1030/// the [module documentation](self).
85aaf69f 1031///
c34b1796 1032/// # Examples
85aaf69f 1033///
7cac9316
XL
1034/// You can use [`push`] to build up a `PathBuf` from
1035/// components:
1036///
c34b1796 1037/// ```
85aaf69f
SL
1038/// use std::path::PathBuf;
1039///
7cac9316
XL
1040/// let mut path = PathBuf::new();
1041///
1042/// path.push(r"C:\");
85aaf69f
SL
1043/// path.push("windows");
1044/// path.push("system32");
7cac9316 1045///
85aaf69f
SL
1046/// path.set_extension("dll");
1047/// ```
7cac9316
XL
1048///
1049/// However, [`push`] is best used for dynamic situations. This is a better way
1050/// to do this when you know all of the components ahead of time:
1051///
1052/// ```
1053/// use std::path::PathBuf;
1054///
1055/// let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();
1056/// ```
1057///
1058/// We can still do better than this! Since these are all strings, we can use
1059/// `From::from`:
1060///
1061/// ```
1062/// use std::path::PathBuf;
1063///
1064/// let path = PathBuf::from(r"C:\windows\system32.dll");
1065/// ```
1066///
1067/// Which method works best depends on what kind of situation you're in.
6a06907d 1068#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
c34b1796 1069#[stable(feature = "rust1", since = "1.0.0")]
416331ca
XL
1070// FIXME:
1071// `PathBuf::as_mut_vec` current implementation relies
1072// on `PathBuf` being layout-compatible with `Vec<u8>`.
1073// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`.
1074// Anyway, `PathBuf` representation and layout are considered implementation detail, are
1075// not documented and must not be relied upon.
85aaf69f 1076pub struct PathBuf {
92a42be0 1077 inner: OsString,
85aaf69f
SL
1078}
1079
1080impl PathBuf {
5869c6ff 1081 #[inline]
85aaf69f 1082 fn as_mut_vec(&mut self) -> &mut Vec<u8> {
e9174d1e 1083 unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
85aaf69f
SL
1084 }
1085
9346a6ac 1086 /// Allocates an empty `PathBuf`.
9e0c209e
SL
1087 ///
1088 /// # Examples
1089 ///
1090 /// ```
1091 /// use std::path::PathBuf;
1092 ///
1093 /// let path = PathBuf::new();
1094 /// ```
c34b1796 1095 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1096 #[inline]
c34b1796
AL
1097 pub fn new() -> PathBuf {
1098 PathBuf { inner: OsString::new() }
1099 }
1100
9fa01778
XL
1101 /// Creates a new `PathBuf` with a given capacity used to create the
1102 /// internal [`OsString`]. See [`with_capacity`] defined on [`OsString`].
1103 ///
1104 /// # Examples
1105 ///
1106 /// ```
9fa01778
XL
1107 /// use std::path::PathBuf;
1108 ///
1109 /// let mut path = PathBuf::with_capacity(10);
1110 /// let capacity = path.capacity();
1111 ///
1112 /// // This push is done without reallocating
1113 /// path.push(r"C:\");
1114 ///
1115 /// assert_eq!(capacity, path.capacity());
1116 /// ```
1117 ///
3dfed10e 1118 /// [`with_capacity`]: OsString::with_capacity
ba9703b0 1119 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1120 #[inline]
9fa01778 1121 pub fn with_capacity(capacity: usize) -> PathBuf {
60c5eb7d 1122 PathBuf { inner: OsString::with_capacity(capacity) }
9fa01778
XL
1123 }
1124
9e0c209e
SL
1125 /// Coerces to a [`Path`] slice.
1126 ///
9e0c209e
SL
1127 /// # Examples
1128 ///
1129 /// ```
1130 /// use std::path::{Path, PathBuf};
1131 ///
1132 /// let p = PathBuf::from("/test");
1133 /// assert_eq!(Path::new("/test"), p.as_path());
1134 /// ```
c34b1796 1135 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1136 #[inline]
c34b1796
AL
1137 pub fn as_path(&self) -> &Path {
1138 self
85aaf69f
SL
1139 }
1140
9346a6ac 1141 /// Extends `self` with `path`.
85aaf69f
SL
1142 ///
1143 /// If `path` is absolute, it replaces the current path.
1144 ///
1145 /// On Windows:
1146 ///
0731742a 1147 /// * if `path` has a root but no prefix (e.g., `\windows`), it
85aaf69f 1148 /// replaces everything except for the prefix (if any) of `self`.
e9174d1e 1149 /// * if `path` has a prefix but no root, it replaces `self`.
92a42be0
SL
1150 ///
1151 /// # Examples
1152 ///
476ff2be
SL
1153 /// Pushing a relative path extends the existing path:
1154 ///
92a42be0
SL
1155 /// ```
1156 /// use std::path::PathBuf;
1157 ///
476ff2be 1158 /// let mut path = PathBuf::from("/tmp");
92a42be0
SL
1159 /// path.push("file.bk");
1160 /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
476ff2be
SL
1161 /// ```
1162 ///
1163 /// Pushing an absolute path replaces the existing path:
1164 ///
1165 /// ```
1166 /// use std::path::PathBuf;
92a42be0 1167 ///
476ff2be
SL
1168 /// let mut path = PathBuf::from("/tmp");
1169 /// path.push("/etc");
1170 /// assert_eq!(path, PathBuf::from("/etc"));
92a42be0 1171 /// ```
c34b1796
AL
1172 #[stable(feature = "rust1", since = "1.0.0")]
1173 pub fn push<P: AsRef<Path>>(&mut self, path: P) {
e9174d1e
SL
1174 self._push(path.as_ref())
1175 }
c34b1796 1176
e9174d1e 1177 fn _push(&mut self, path: &Path) {
85aaf69f
SL
1178 // in general, a separator is needed if the rightmost byte is not a separator
1179 let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
1180
1181 // in the special case of `C:` on Windows, do *not* add a separator
1182 {
1183 let comps = self.components();
60c5eb7d
XL
1184 if comps.prefix_len() > 0
1185 && comps.prefix_len() == comps.path.len()
1186 && comps.prefix.unwrap().is_drive()
1187 {
85aaf69f
SL
1188 need_sep = false
1189 }
1190 }
1191
85aaf69f
SL
1192 // absolute `path` replaces `self`
1193 if path.is_absolute() || path.prefix().is_some() {
1194 self.as_mut_vec().truncate(0);
1195
0731742a 1196 // `path` has a root but no prefix, e.g., `\windows` (Windows only)
85aaf69f
SL
1197 } else if path.has_root() {
1198 let prefix_len = self.components().prefix_remaining();
1199 self.as_mut_vec().truncate(prefix_len);
1200
1201 // `path` is a pure relative path
1202 } else if need_sep {
c34b1796 1203 self.inner.push(MAIN_SEP_STR);
85aaf69f
SL
1204 }
1205
c34b1796 1206 self.inner.push(path);
85aaf69f
SL
1207 }
1208
041b39d2 1209 /// Truncates `self` to [`self.parent`].
85aaf69f 1210 ///
9fa01778 1211 /// Returns `false` and does nothing if [`self.parent`] is [`None`].
85aaf69f 1212 /// Otherwise, returns `true`.
9e0c209e 1213 ///
3dfed10e 1214 /// [`self.parent`]: Path::parent
9e0c209e
SL
1215 ///
1216 /// # Examples
1217 ///
1218 /// ```
1219 /// use std::path::{Path, PathBuf};
1220 ///
3dfed10e 1221 /// let mut p = PathBuf::from("/spirited/away.rs");
9e0c209e
SL
1222 ///
1223 /// p.pop();
3dfed10e 1224 /// assert_eq!(Path::new("/spirited"), p);
9e0c209e
SL
1225 /// p.pop();
1226 /// assert_eq!(Path::new("/"), p);
1227 /// ```
c34b1796 1228 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1229 pub fn pop(&mut self) -> bool {
1230 match self.parent().map(|p| p.as_u8_slice().len()) {
1231 Some(len) => {
1232 self.as_mut_vec().truncate(len);
1233 true
1234 }
92a42be0 1235 None => false,
85aaf69f
SL
1236 }
1237 }
1238
cc61c64b 1239 /// Updates [`self.file_name`] to `file_name`.
85aaf69f 1240 ///
cc61c64b 1241 /// If [`self.file_name`] was [`None`], this is equivalent to pushing
85aaf69f
SL
1242 /// `file_name`.
1243 ///
cc61c64b
XL
1244 /// Otherwise it is equivalent to calling [`pop`] and then pushing
1245 /// `file_name`. The new path will be a sibling of the original path.
1246 /// (That is, it will have the same parent.)
1247 ///
3dfed10e
XL
1248 /// [`self.file_name`]: Path::file_name
1249 /// [`pop`]: PathBuf::pop
9e0c209e 1250 ///
85aaf69f
SL
1251 /// # Examples
1252 ///
c34b1796
AL
1253 /// ```
1254 /// use std::path::PathBuf;
85aaf69f 1255 ///
c34b1796 1256 /// let mut buf = PathBuf::from("/");
85aaf69f
SL
1257 /// assert!(buf.file_name() == None);
1258 /// buf.set_file_name("bar");
c34b1796 1259 /// assert!(buf == PathBuf::from("/bar"));
85aaf69f
SL
1260 /// assert!(buf.file_name().is_some());
1261 /// buf.set_file_name("baz.txt");
c34b1796 1262 /// assert!(buf == PathBuf::from("/baz.txt"));
85aaf69f 1263 /// ```
c34b1796
AL
1264 #[stable(feature = "rust1", since = "1.0.0")]
1265 pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
e9174d1e
SL
1266 self._set_file_name(file_name.as_ref())
1267 }
1268
1269 fn _set_file_name(&mut self, file_name: &OsStr) {
c34b1796
AL
1270 if self.file_name().is_some() {
1271 let popped = self.pop();
1272 debug_assert!(popped);
85aaf69f 1273 }
e9174d1e 1274 self.push(file_name);
85aaf69f
SL
1275 }
1276
cc61c64b 1277 /// Updates [`self.extension`] to `extension`.
9e0c209e 1278 ///
cc61c64b
XL
1279 /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
1280 /// returns `true` and updates the extension otherwise.
9e0c209e 1281 ///
cc61c64b
XL
1282 /// If [`self.extension`] is [`None`], the extension is added; otherwise
1283 /// it is replaced.
85aaf69f 1284 ///
3dfed10e
XL
1285 /// [`self.file_name`]: Path::file_name
1286 /// [`self.extension`]: Path::extension
85aaf69f 1287 ///
9e0c209e
SL
1288 /// # Examples
1289 ///
1290 /// ```
1291 /// use std::path::{Path, PathBuf};
1292 ///
1293 /// let mut p = PathBuf::from("/feel/the");
1294 ///
1295 /// p.set_extension("force");
1296 /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
1297 ///
1298 /// p.set_extension("dark_side");
1299 /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path());
1300 /// ```
c34b1796
AL
1301 #[stable(feature = "rust1", since = "1.0.0")]
1302 pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
e9174d1e
SL
1303 self._set_extension(extension.as_ref())
1304 }
1305
1306 fn _set_extension(&mut self, extension: &OsStr) -> bool {
e74abb32
XL
1307 let file_stem = match self.file_stem() {
1308 None => return false,
1309 Some(f) => os_str_as_u8_slice(f),
85aaf69f
SL
1310 };
1311
e74abb32
XL
1312 // truncate until right after the file stem
1313 let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
1314 let start = os_str_as_u8_slice(&self.inner).as_ptr() as usize;
1315 let v = self.as_mut_vec();
1316 v.truncate(end_file_stem.wrapping_sub(start));
1317
1318 // add the new extension, if any
1319 let new = os_str_as_u8_slice(extension);
1320 if !new.is_empty() {
1321 v.reserve_exact(new.len() + 1);
1322 v.push(b'.');
1323 v.extend_from_slice(new);
85aaf69f 1324 }
85aaf69f
SL
1325
1326 true
1327 }
1328
9e0c209e
SL
1329 /// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.
1330 ///
9e0c209e
SL
1331 /// # Examples
1332 ///
1333 /// ```
1334 /// use std::path::PathBuf;
1335 ///
1336 /// let p = PathBuf::from("/the/head");
1337 /// let os_str = p.into_os_string();
1338 /// ```
c34b1796 1339 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1340 #[inline]
85aaf69f
SL
1341 pub fn into_os_string(self) -> OsString {
1342 self.inner
1343 }
8bb4bdeb 1344
29967ef6 1345 /// Converts this `PathBuf` into a [boxed](Box) [`Path`].
041b39d2 1346 #[stable(feature = "into_boxed_path", since = "1.20.0")]
5869c6ff 1347 #[inline]
8bb4bdeb 1348 pub fn into_boxed_path(self) -> Box<Path> {
ea8adc8c
XL
1349 let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
1350 unsafe { Box::from_raw(rw) }
8bb4bdeb 1351 }
9fa01778
XL
1352
1353 /// Invokes [`capacity`] on the underlying instance of [`OsString`].
1354 ///
3dfed10e 1355 /// [`capacity`]: OsString::capacity
ba9703b0 1356 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1357 #[inline]
9fa01778
XL
1358 pub fn capacity(&self) -> usize {
1359 self.inner.capacity()
1360 }
1361
1362 /// Invokes [`clear`] on the underlying instance of [`OsString`].
1363 ///
3dfed10e 1364 /// [`clear`]: OsString::clear
ba9703b0 1365 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1366 #[inline]
9fa01778
XL
1367 pub fn clear(&mut self) {
1368 self.inner.clear()
1369 }
1370
1371 /// Invokes [`reserve`] on the underlying instance of [`OsString`].
1372 ///
3dfed10e 1373 /// [`reserve`]: OsString::reserve
ba9703b0 1374 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1375 #[inline]
9fa01778
XL
1376 pub fn reserve(&mut self, additional: usize) {
1377 self.inner.reserve(additional)
1378 }
1379
1380 /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].
1381 ///
3dfed10e 1382 /// [`reserve_exact`]: OsString::reserve_exact
ba9703b0 1383 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1384 #[inline]
9fa01778
XL
1385 pub fn reserve_exact(&mut self, additional: usize) {
1386 self.inner.reserve_exact(additional)
1387 }
1388
1389 /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].
1390 ///
3dfed10e 1391 /// [`shrink_to_fit`]: OsString::shrink_to_fit
ba9703b0 1392 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1393 #[inline]
9fa01778
XL
1394 pub fn shrink_to_fit(&mut self) {
1395 self.inner.shrink_to_fit()
1396 }
1397
1398 /// Invokes [`shrink_to`] on the underlying instance of [`OsString`].
1399 ///
3dfed10e 1400 /// [`shrink_to`]: OsString::shrink_to
ba9703b0 1401 #[unstable(feature = "shrink_to", issue = "56431")]
5869c6ff 1402 #[inline]
9fa01778
XL
1403 pub fn shrink_to(&mut self, min_capacity: usize) {
1404 self.inner.shrink_to(min_capacity)
1405 }
8bb4bdeb
XL
1406}
1407
cdc7bbd5
XL
1408#[stable(feature = "rust1", since = "1.0.0")]
1409impl Clone for PathBuf {
1410 #[inline]
1411 fn clone(&self) -> Self {
1412 PathBuf { inner: self.inner.clone() }
1413 }
1414
1415 #[inline]
1416 fn clone_from(&mut self, source: &Self) {
1417 self.inner.clone_from(&source.inner)
1418 }
1419}
1420
8bb4bdeb 1421#[stable(feature = "box_from_path", since = "1.17.0")]
532ac7d7 1422impl From<&Path> for Box<Path> {
17df50a5
XL
1423 /// Creates a boxed [`Path`] from a reference.
1424 ///
1425 /// This will allocate and clone `path` to it.
532ac7d7 1426 fn from(path: &Path) -> Box<Path> {
8bb4bdeb 1427 let boxed: Box<OsStr> = path.inner.into();
ea8adc8c
XL
1428 let rw = Box::into_raw(boxed) as *mut Path;
1429 unsafe { Box::from_raw(rw) }
8bb4bdeb 1430 }
85aaf69f
SL
1431}
1432
f9f354fc
XL
1433#[stable(feature = "box_from_cow", since = "1.45.0")]
1434impl From<Cow<'_, Path>> for Box<Path> {
17df50a5
XL
1435 /// Creates a boxed [`Path`] from a clone-on-write pointer.
1436 ///
1437 /// Converting from a `Cow::Owned` does not clone or allocate.
f9f354fc
XL
1438 #[inline]
1439 fn from(cow: Cow<'_, Path>) -> Box<Path> {
1440 match cow {
1441 Cow::Borrowed(path) => Box::from(path),
1442 Cow::Owned(path) => Box::from(path),
1443 }
1444 }
1445}
1446
7cac9316
XL
1447#[stable(feature = "path_buf_from_box", since = "1.18.0")]
1448impl From<Box<Path>> for PathBuf {
0731742a
XL
1449 /// Converts a `Box<Path>` into a `PathBuf`
1450 ///
1451 /// This conversion does not allocate or copy memory.
5869c6ff 1452 #[inline]
cc61c64b
XL
1453 fn from(boxed: Box<Path>) -> PathBuf {
1454 boxed.into_path_buf()
1455 }
1456}
1457
041b39d2
XL
1458#[stable(feature = "box_from_path_buf", since = "1.20.0")]
1459impl From<PathBuf> for Box<Path> {
0731742a
XL
1460 /// Converts a `PathBuf` into a `Box<Path>`
1461 ///
1462 /// This conversion currently should not allocate memory,
1463 /// but this behavior is not guaranteed on all platforms or in all future versions.
5869c6ff 1464 #[inline]
041b39d2
XL
1465 fn from(p: PathBuf) -> Box<Path> {
1466 p.into_boxed_path()
cc61c64b
XL
1467 }
1468}
1469
8faf50e0
XL
1470#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
1471impl Clone for Box<Path> {
1472 #[inline]
1473 fn clone(&self) -> Self {
1474 self.to_path_buf().into_boxed_path()
1475 }
1476}
1477
c34b1796 1478#[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 1479impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
17df50a5
XL
1480 /// Converts a borrowed `OsStr` to a `PathBuf`.
1481 ///
1482 /// Allocates a [`PathBuf`] and copies the data into it.
5869c6ff 1483 #[inline]
532ac7d7 1484 fn from(s: &T) -> PathBuf {
c34b1796
AL
1485 PathBuf::from(s.as_ref().to_os_string())
1486 }
1487}
1488
1489#[stable(feature = "rust1", since = "1.0.0")]
1490impl From<OsString> for PathBuf {
cdc7bbd5 1491 /// Converts an [`OsString`] into a [`PathBuf`]
0731742a
XL
1492 ///
1493 /// This conversion does not allocate or copy memory.
dfeec247 1494 #[inline]
c34b1796
AL
1495 fn from(s: OsString) -> PathBuf {
1496 PathBuf { inner: s }
1497 }
1498}
1499
c30ab7b3
SL
1500#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
1501impl From<PathBuf> for OsString {
cdc7bbd5 1502 /// Converts a [`PathBuf`] into an [`OsString`]
0731742a
XL
1503 ///
1504 /// This conversion does not allocate or copy memory.
5869c6ff 1505 #[inline]
60c5eb7d 1506 fn from(path_buf: PathBuf) -> OsString {
c30ab7b3
SL
1507 path_buf.inner
1508 }
1509}
1510
c34b1796
AL
1511#[stable(feature = "rust1", since = "1.0.0")]
1512impl From<String> for PathBuf {
cdc7bbd5 1513 /// Converts a [`String`] into a [`PathBuf`]
0731742a
XL
1514 ///
1515 /// This conversion does not allocate or copy memory.
5869c6ff 1516 #[inline]
c34b1796
AL
1517 fn from(s: String) -> PathBuf {
1518 PathBuf::from(OsString::from(s))
1519 }
1520}
1521
0731742a 1522#[stable(feature = "path_from_str", since = "1.32.0")]
a1dfa0c6 1523impl FromStr for PathBuf {
9fa01778 1524 type Err = core::convert::Infallible;
a1dfa0c6 1525
5869c6ff 1526 #[inline]
a1dfa0c6
XL
1527 fn from_str(s: &str) -> Result<Self, Self::Err> {
1528 Ok(PathBuf::from(s))
1529 }
1530}
1531
c34b1796
AL
1532#[stable(feature = "rust1", since = "1.0.0")]
1533impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
1534 fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
1535 let mut buf = PathBuf::new();
85aaf69f
SL
1536 buf.extend(iter);
1537 buf
1538 }
1539}
1540
c34b1796
AL
1541#[stable(feature = "rust1", since = "1.0.0")]
1542impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
1543 fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
532ac7d7 1544 iter.into_iter().for_each(move |p| self.push(p.as_ref()));
85aaf69f 1545 }
f9f354fc
XL
1546
1547 #[inline]
1548 fn extend_one(&mut self, p: P) {
1549 self.push(p.as_ref());
1550 }
85aaf69f
SL
1551}
1552
c34b1796 1553#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1554impl fmt::Debug for PathBuf {
532ac7d7 1555 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
85aaf69f
SL
1556 fmt::Debug::fmt(&**self, formatter)
1557 }
1558}
1559
c34b1796 1560#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1561impl ops::Deref for PathBuf {
1562 type Target = Path;
dfeec247 1563 #[inline]
85aaf69f 1564 fn deref(&self) -> &Path {
e9174d1e 1565 Path::new(&self.inner)
85aaf69f
SL
1566 }
1567}
1568
c34b1796 1569#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1570impl Borrow<Path> for PathBuf {
5869c6ff 1571 #[inline]
85aaf69f
SL
1572 fn borrow(&self) -> &Path {
1573 self.deref()
1574 }
1575}
1576
7cac9316 1577#[stable(feature = "default_for_pathbuf", since = "1.17.0")]
8bb4bdeb 1578impl Default for PathBuf {
5869c6ff 1579 #[inline]
8bb4bdeb
XL
1580 fn default() -> Self {
1581 PathBuf::new()
1582 }
1583}
1584
92a42be0
SL
1585#[stable(feature = "cow_from_path", since = "1.6.0")]
1586impl<'a> From<&'a Path> for Cow<'a, Path> {
17df50a5
XL
1587 /// Creates a clone-on-write pointer from a reference to
1588 /// [`Path`].
1589 ///
1590 /// This conversion does not clone or allocate.
92a42be0
SL
1591 #[inline]
1592 fn from(s: &'a Path) -> Cow<'a, Path> {
1593 Cow::Borrowed(s)
1594 }
1595}
1596
1597#[stable(feature = "cow_from_path", since = "1.6.0")]
1598impl<'a> From<PathBuf> for Cow<'a, Path> {
17df50a5
XL
1599 /// Creates a clone-on-write pointer from an owned
1600 /// instance of [`PathBuf`].
1601 ///
1602 /// This conversion does not clone or allocate.
92a42be0
SL
1603 #[inline]
1604 fn from(s: PathBuf) -> Cow<'a, Path> {
1605 Cow::Owned(s)
1606 }
1607}
1608
94b46f34
XL
1609#[stable(feature = "cow_from_pathbuf_ref", since = "1.28.0")]
1610impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
17df50a5
XL
1611 /// Creates a clone-on-write pointer from a reference to
1612 /// [`PathBuf`].
1613 ///
1614 /// This conversion does not clone or allocate.
94b46f34
XL
1615 #[inline]
1616 fn from(p: &'a PathBuf) -> Cow<'a, Path> {
1617 Cow::Borrowed(p.as_path())
1618 }
1619}
1620
1621#[stable(feature = "pathbuf_from_cow_path", since = "1.28.0")]
1622impl<'a> From<Cow<'a, Path>> for PathBuf {
17df50a5
XL
1623 /// Converts a clone-on-write pointer to an owned path.
1624 ///
1625 /// Converting from a `Cow::Owned` does not clone or allocate.
94b46f34
XL
1626 #[inline]
1627 fn from(p: Cow<'a, Path>) -> Self {
1628 p.into_owned()
1629 }
1630}
1631
2c00a5a8 1632#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11 1633impl From<PathBuf> for Arc<Path> {
cdc7bbd5 1634 /// Converts a [`PathBuf`] into an [`Arc`] by moving the [`PathBuf`] data into a new [`Arc`] buffer.
ff7c6d11
XL
1635 #[inline]
1636 fn from(s: PathBuf) -> Arc<Path> {
1637 let arc: Arc<OsStr> = Arc::from(s.into_os_string());
1638 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1639 }
1640}
1641
2c00a5a8 1642#[stable(feature = "shared_from_slice2", since = "1.24.0")]
532ac7d7 1643impl From<&Path> for Arc<Path> {
cdc7bbd5 1644 /// Converts a [`Path`] into an [`Arc`] by copying the [`Path`] data into a new [`Arc`] buffer.
ff7c6d11
XL
1645 #[inline]
1646 fn from(s: &Path) -> Arc<Path> {
1647 let arc: Arc<OsStr> = Arc::from(s.as_os_str());
1648 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1649 }
1650}
1651
2c00a5a8 1652#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11 1653impl From<PathBuf> for Rc<Path> {
cdc7bbd5 1654 /// Converts a [`PathBuf`] into an [`Rc`] by moving the [`PathBuf`] data into a new `Rc` buffer.
ff7c6d11
XL
1655 #[inline]
1656 fn from(s: PathBuf) -> Rc<Path> {
1657 let rc: Rc<OsStr> = Rc::from(s.into_os_string());
1658 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1659 }
1660}
1661
2c00a5a8 1662#[stable(feature = "shared_from_slice2", since = "1.24.0")]
532ac7d7 1663impl From<&Path> for Rc<Path> {
cdc7bbd5 1664 /// Converts a [`Path`] into an [`Rc`] by copying the [`Path`] data into a new `Rc` buffer.
ff7c6d11
XL
1665 #[inline]
1666 fn from(s: &Path) -> Rc<Path> {
1667 let rc: Rc<OsStr> = Rc::from(s.as_os_str());
1668 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1669 }
1670}
1671
c34b1796 1672#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1673impl ToOwned for Path {
1674 type Owned = PathBuf;
5869c6ff 1675 #[inline]
92a42be0
SL
1676 fn to_owned(&self) -> PathBuf {
1677 self.to_path_buf()
1678 }
5869c6ff 1679 #[inline]
cc61c64b
XL
1680 fn clone_into(&self, target: &mut PathBuf) {
1681 self.inner.clone_into(&mut target.inner);
1682 }
85aaf69f
SL
1683}
1684
c34b1796 1685#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1686impl cmp::PartialEq for PathBuf {
5869c6ff 1687 #[inline]
85aaf69f
SL
1688 fn eq(&self, other: &PathBuf) -> bool {
1689 self.components() == other.components()
1690 }
1691}
1692
92a42be0
SL
1693#[stable(feature = "rust1", since = "1.0.0")]
1694impl Hash for PathBuf {
1695 fn hash<H: Hasher>(&self, h: &mut H) {
1696 self.as_path().hash(h)
1697 }
1698}
1699
c34b1796 1700#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1701impl cmp::Eq for PathBuf {}
1702
c34b1796 1703#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1704impl cmp::PartialOrd for PathBuf {
5869c6ff 1705 #[inline]
85aaf69f 1706 fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
e9174d1e 1707 self.components().partial_cmp(other.components())
85aaf69f
SL
1708 }
1709}
1710
c34b1796 1711#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1712impl cmp::Ord for PathBuf {
5869c6ff 1713 #[inline]
85aaf69f 1714 fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
e9174d1e 1715 self.components().cmp(other.components())
85aaf69f
SL
1716 }
1717}
1718
c34b1796
AL
1719#[stable(feature = "rust1", since = "1.0.0")]
1720impl AsRef<OsStr> for PathBuf {
5869c6ff 1721 #[inline]
c34b1796
AL
1722 fn as_ref(&self) -> &OsStr {
1723 &self.inner[..]
1724 }
1725}
1726
9e0c209e 1727/// A slice of a path (akin to [`str`]).
85aaf69f
SL
1728///
1729/// This type supports a number of operations for inspecting a path, including
041b39d2
XL
1730/// breaking the path into its components (separated by `/` on Unix and by either
1731/// `/` or `\` on Windows), extracting the file name, determining whether the path
1732/// is absolute, and so on.
85aaf69f 1733///
d9579d0f 1734/// This is an *unsized* type, meaning that it must always be used behind a
c30ab7b3
SL
1735/// pointer like `&` or [`Box`]. For an owned version of this type,
1736/// see [`PathBuf`].
9e0c209e 1737///
c30ab7b3 1738/// More details about the overall approach can be found in
29967ef6 1739/// the [module documentation](self).
85aaf69f 1740///
c34b1796 1741/// # Examples
85aaf69f 1742///
c34b1796 1743/// ```
85aaf69f 1744/// use std::path::Path;
476ff2be 1745/// use std::ffi::OsStr;
85aaf69f 1746///
041b39d2
XL
1747/// // Note: this example does work on Windows
1748/// let path = Path::new("./foo/bar.txt");
476ff2be
SL
1749///
1750/// let parent = path.parent();
041b39d2 1751/// assert_eq!(parent, Some(Path::new("./foo")));
476ff2be
SL
1752///
1753/// let file_stem = path.file_stem();
1754/// assert_eq!(file_stem, Some(OsStr::new("bar")));
1755///
85aaf69f 1756/// let extension = path.extension();
476ff2be 1757/// assert_eq!(extension, Some(OsStr::new("txt")));
85aaf69f 1758/// ```
6a06907d 1759#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
c34b1796 1760#[stable(feature = "rust1", since = "1.0.0")]
416331ca
XL
1761// FIXME:
1762// `Path::new` current implementation relies
1763// on `Path` being layout-compatible with `OsStr`.
1764// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`.
1765// Anyway, `Path` representation and layout are considered implementation detail, are
1766// not documented and must not be relied upon.
85aaf69f 1767pub struct Path {
92a42be0 1768 inner: OsStr,
85aaf69f
SL
1769}
1770
29967ef6 1771/// An error returned from [`Path::strip_prefix`] if the prefix was not found.
cc61c64b
XL
1772///
1773/// This `struct` is created by the [`strip_prefix`] method on [`Path`].
1774/// See its documentation for more.
32a655c1 1775///
3dfed10e 1776/// [`strip_prefix`]: Path::strip_prefix
9cc50fc6
SL
1777#[derive(Debug, Clone, PartialEq, Eq)]
1778#[stable(since = "1.7.0", feature = "strip_prefix")]
1779pub struct StripPrefixError(());
1780
85aaf69f
SL
1781impl Path {
1782 // The following (private!) function allows construction of a path from a u8
1783 // slice, which is only safe when it is known to follow the OsStr encoding.
1784 unsafe fn from_u8_slice(s: &[u8]) -> &Path {
1b1a35ee 1785 unsafe { Path::new(u8_slice_as_os_str(s)) }
85aaf69f
SL
1786 }
1787 // The following (private!) function reveals the byte encoding used for OsStr.
1788 fn as_u8_slice(&self) -> &[u8] {
e9174d1e 1789 os_str_as_u8_slice(&self.inner)
85aaf69f
SL
1790 }
1791
cc61c64b 1792 /// Directly wraps a string slice as a `Path` slice.
85aaf69f
SL
1793 ///
1794 /// This is a cost-free conversion.
c34b1796
AL
1795 ///
1796 /// # Examples
1797 ///
1798 /// ```
1799 /// use std::path::Path;
1800 ///
1801 /// Path::new("foo.txt");
1802 /// ```
bd371182
AL
1803 ///
1804 /// You can create `Path`s from `String`s, or even other `Path`s:
1805 ///
1806 /// ```
1807 /// use std::path::Path;
1808 ///
62682a34
SL
1809 /// let string = String::from("foo.txt");
1810 /// let from_string = Path::new(&string);
1811 /// let from_path = Path::new(&from_string);
1812 /// assert_eq!(from_string, from_path);
bd371182 1813 /// ```
c34b1796
AL
1814 #[stable(feature = "rust1", since = "1.0.0")]
1815 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
ea8adc8c 1816 unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
c34b1796
AL
1817 }
1818
9e0c209e
SL
1819 /// Yields the underlying [`OsStr`] slice.
1820 ///
c34b1796
AL
1821 /// # Examples
1822 ///
1823 /// ```
1824 /// use std::path::Path;
1825 ///
1826 /// let os_str = Path::new("foo.txt").as_os_str();
62682a34 1827 /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
c34b1796
AL
1828 /// ```
1829 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1830 #[inline]
c34b1796
AL
1831 pub fn as_os_str(&self) -> &OsStr {
1832 &self.inner
85aaf69f
SL
1833 }
1834
9e0c209e 1835 /// Yields a [`&str`] slice if the `Path` is valid unicode.
85aaf69f
SL
1836 ///
1837 /// This conversion may entail doing a check for UTF-8 validity.
416331ca
XL
1838 /// Note that validation is performed because non-UTF-8 strings are
1839 /// perfectly valid for some OS.
c34b1796 1840 ///
3dfed10e 1841 /// [`&str`]: str
9e0c209e 1842 ///
c34b1796
AL
1843 /// # Examples
1844 ///
1845 /// ```
1846 /// use std::path::Path;
1847 ///
32a655c1
SL
1848 /// let path = Path::new("foo.txt");
1849 /// assert_eq!(path.to_str(), Some("foo.txt"));
c34b1796
AL
1850 /// ```
1851 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1852 #[inline]
85aaf69f
SL
1853 pub fn to_str(&self) -> Option<&str> {
1854 self.inner.to_str()
1855 }
1856
9e0c209e 1857 /// Converts a `Path` to a [`Cow<str>`].
85aaf69f 1858 ///
b7449926
XL
1859 /// Any non-Unicode sequences are replaced with
1860 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
c34b1796 1861 ///
3dfed10e 1862 /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
9e0c209e 1863 ///
c34b1796
AL
1864 /// # Examples
1865 ///
32a655c1
SL
1866 /// Calling `to_string_lossy` on a `Path` with valid unicode:
1867 ///
c34b1796
AL
1868 /// ```
1869 /// use std::path::Path;
1870 ///
32a655c1
SL
1871 /// let path = Path::new("foo.txt");
1872 /// assert_eq!(path.to_string_lossy(), "foo.txt");
c34b1796 1873 /// ```
32a655c1 1874 ///
cc61c64b 1875 /// Had `path` contained invalid unicode, the `to_string_lossy` call might
32a655c1 1876 /// have returned `"fo�.txt"`.
c34b1796 1877 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1878 #[inline]
532ac7d7 1879 pub fn to_string_lossy(&self) -> Cow<'_, str> {
85aaf69f
SL
1880 self.inner.to_string_lossy()
1881 }
1882
9e0c209e
SL
1883 /// Converts a `Path` to an owned [`PathBuf`].
1884 ///
c34b1796
AL
1885 /// # Examples
1886 ///
1887 /// ```
1888 /// use std::path::Path;
1889 ///
62682a34
SL
1890 /// let path_buf = Path::new("foo.txt").to_path_buf();
1891 /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
c34b1796 1892 /// ```
2c00a5a8 1893 #[rustc_conversion_suggestion]
c34b1796 1894 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1895 pub fn to_path_buf(&self) -> PathBuf {
c34b1796 1896 PathBuf::from(self.inner.to_os_string())
85aaf69f
SL
1897 }
1898
0731742a 1899 /// Returns `true` if the `Path` is absolute, i.e., if it is independent of
cc61c64b 1900 /// the current directory.
85aaf69f
SL
1901 ///
1902 /// * On Unix, a path is absolute if it starts with the root, so
cc61c64b 1903 /// `is_absolute` and [`has_root`] are equivalent.
85aaf69f
SL
1904 ///
1905 /// * On Windows, a path is absolute if it has a prefix and starts with the
3157f602 1906 /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not.
c34b1796
AL
1907 ///
1908 /// # Examples
1909 ///
1910 /// ```
1911 /// use std::path::Path;
1912 ///
62682a34 1913 /// assert!(!Path::new("foo.txt").is_absolute());
c34b1796 1914 /// ```
cc61c64b 1915 ///
3dfed10e 1916 /// [`has_root`]: Path::has_root
c34b1796 1917 #[stable(feature = "rust1", since = "1.0.0")]
9cc50fc6 1918 #[allow(deprecated)]
85aaf69f 1919 pub fn is_absolute(&self) -> bool {
abe05a73 1920 if cfg!(target_os = "redox") {
3b2f2976 1921 // FIXME: Allow Redox prefixes
abe05a73
XL
1922 self.has_root() || has_redox_scheme(self.as_u8_slice())
1923 } else {
1b1a35ee 1924 self.has_root() && (cfg!(any(unix, target_os = "wasi")) || self.prefix().is_some())
3b2f2976 1925 }
85aaf69f
SL
1926 }
1927
0731742a 1928 /// Returns `true` if the `Path` is relative, i.e., not absolute.
cc61c64b
XL
1929 ///
1930 /// See [`is_absolute`]'s documentation for more details.
c34b1796
AL
1931 ///
1932 /// # Examples
1933 ///
1934 /// ```
1935 /// use std::path::Path;
1936 ///
1937 /// assert!(Path::new("foo.txt").is_relative());
1938 /// ```
cc61c64b 1939 ///
3dfed10e 1940 /// [`is_absolute`]: Path::is_absolute
c34b1796 1941 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1942 #[inline]
85aaf69f
SL
1943 pub fn is_relative(&self) -> bool {
1944 !self.is_absolute()
1945 }
1946
532ac7d7 1947 fn prefix(&self) -> Option<Prefix<'_>> {
c34b1796 1948 self.components().prefix
85aaf69f
SL
1949 }
1950
cc61c64b 1951 /// Returns `true` if the `Path` has a root.
85aaf69f
SL
1952 ///
1953 /// * On Unix, a path has a root if it begins with `/`.
1954 ///
1955 /// * On Windows, a path has a root if it:
0731742a
XL
1956 /// * has no prefix and begins with a separator, e.g., `\windows`
1957 /// * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows`
1958 /// * has any non-disk prefix, e.g., `\\server\share`
c34b1796
AL
1959 ///
1960 /// # Examples
1961 ///
1962 /// ```
1963 /// use std::path::Path;
1964 ///
1965 /// assert!(Path::new("/etc/passwd").has_root());
1966 /// ```
1967 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1968 #[inline]
85aaf69f 1969 pub fn has_root(&self) -> bool {
92a42be0 1970 self.components().has_root()
85aaf69f
SL
1971 }
1972
cc61c64b 1973 /// Returns the `Path` without its final component, if there is one.
85aaf69f 1974 ///
32a655c1
SL
1975 /// Returns [`None`] if the path terminates in a root or prefix.
1976 ///
85aaf69f
SL
1977 /// # Examples
1978 ///
c34b1796 1979 /// ```
85aaf69f
SL
1980 /// use std::path::Path;
1981 ///
1982 /// let path = Path::new("/foo/bar");
62682a34
SL
1983 /// let parent = path.parent().unwrap();
1984 /// assert_eq!(parent, Path::new("/foo"));
c34b1796 1985 ///
62682a34
SL
1986 /// let grand_parent = parent.parent().unwrap();
1987 /// assert_eq!(grand_parent, Path::new("/"));
1988 /// assert_eq!(grand_parent.parent(), None);
85aaf69f 1989 /// ```
c34b1796 1990 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1991 pub fn parent(&self) -> Option<&Path> {
1992 let mut comps = self.components();
1993 let comp = comps.next_back();
60c5eb7d
XL
1994 comp.and_then(|p| match p {
1995 Component::Normal(_) | Component::CurDir | Component::ParentDir => {
1996 Some(comps.as_path())
92a42be0 1997 }
60c5eb7d 1998 _ => None,
c34b1796 1999 })
85aaf69f
SL
2000 }
2001
0531ce1d
XL
2002 /// Produces an iterator over `Path` and its ancestors.
2003 ///
2004 /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
2005 /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
2006 /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
2007 /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
2008 /// namely `&self`.
2009 ///
2010 /// # Examples
2011 ///
2012 /// ```
0531ce1d
XL
2013 /// use std::path::Path;
2014 ///
2015 /// let mut ancestors = Path::new("/foo/bar").ancestors();
2016 /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
2017 /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
2018 /// assert_eq!(ancestors.next(), Some(Path::new("/")));
2019 /// assert_eq!(ancestors.next(), None);
3dfed10e
XL
2020 ///
2021 /// let mut ancestors = Path::new("../foo/bar").ancestors();
2022 /// assert_eq!(ancestors.next(), Some(Path::new("../foo/bar")));
2023 /// assert_eq!(ancestors.next(), Some(Path::new("../foo")));
2024 /// assert_eq!(ancestors.next(), Some(Path::new("..")));
2025 /// assert_eq!(ancestors.next(), Some(Path::new("")));
2026 /// assert_eq!(ancestors.next(), None);
0531ce1d
XL
2027 /// ```
2028 ///
3dfed10e 2029 /// [`parent`]: Path::parent
94b46f34 2030 #[stable(feature = "path_ancestors", since = "1.28.0")]
5869c6ff 2031 #[inline]
532ac7d7 2032 pub fn ancestors(&self) -> Ancestors<'_> {
60c5eb7d 2033 Ancestors { next: Some(&self) }
0531ce1d
XL
2034 }
2035
cc61c64b 2036 /// Returns the final component of the `Path`, if there is one.
85aaf69f 2037 ///
cc61c64b
XL
2038 /// If the path is a normal file, this is the file name. If it's the path of a directory, this
2039 /// is the directory name.
2040 ///
0531ce1d 2041 /// Returns [`None`] if the path terminates in `..`.
32a655c1 2042 ///
c34b1796
AL
2043 /// # Examples
2044 ///
2045 /// ```
2046 /// use std::path::Path;
62682a34 2047 /// use std::ffi::OsStr;
c34b1796 2048 ///
cc61c64b
XL
2049 /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name());
2050 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
5bcae85e
SL
2051 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
2052 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
2053 /// assert_eq!(None, Path::new("foo.txt/..").file_name());
cc61c64b 2054 /// assert_eq!(None, Path::new("/").file_name());
5bcae85e 2055 /// ```
c34b1796 2056 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2057 pub fn file_name(&self) -> Option<&OsStr> {
60c5eb7d 2058 self.components().next_back().and_then(|p| match p {
74b04a01 2059 Component::Normal(p) => Some(p),
60c5eb7d 2060 _ => None,
85aaf69f
SL
2061 })
2062 }
2063
9cc50fc6
SL
2064 /// Returns a path that, when joined onto `base`, yields `self`.
2065 ///
7453a54e
SL
2066 /// # Errors
2067 ///
0731742a 2068 /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
32a655c1
SL
2069 /// returns `false`), returns [`Err`].
2070 ///
3dfed10e 2071 /// [`starts_with`]: Path::starts_with
9e0c209e
SL
2072 ///
2073 /// # Examples
2074 ///
2075 /// ```
83c7162d 2076 /// use std::path::{Path, PathBuf};
9e0c209e
SL
2077 ///
2078 /// let path = Path::new("/test/haha/foo.txt");
2079 ///
2c00a5a8 2080 /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
9e0c209e 2081 /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
2c00a5a8
XL
2082 /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
2083 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
2084 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
3dfed10e
XL
2085 ///
2086 /// assert!(path.strip_prefix("test").is_err());
2087 /// assert!(path.strip_prefix("/haha").is_err());
83c7162d
XL
2088 ///
2089 /// let prefix = PathBuf::from("/test/");
2090 /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
9e0c209e 2091 /// ```
9cc50fc6 2092 #[stable(since = "1.7.0", feature = "path_strip_prefix")]
60c5eb7d
XL
2093 pub fn strip_prefix<P>(&self, base: P) -> Result<&Path, StripPrefixError>
2094 where
2095 P: AsRef<Path>,
9cc50fc6
SL
2096 {
2097 self._strip_prefix(base.as_ref())
e9174d1e
SL
2098 }
2099
60c5eb7d 2100 fn _strip_prefix(&self, base: &Path) -> Result<&Path, StripPrefixError> {
9cc50fc6
SL
2101 iter_after(self.components(), base.components())
2102 .map(|c| c.as_path())
2103 .ok_or(StripPrefixError(()))
85aaf69f
SL
2104 }
2105
2106 /// Determines whether `base` is a prefix of `self`.
c34b1796 2107 ///
d9579d0f
AL
2108 /// Only considers whole path components to match.
2109 ///
c34b1796
AL
2110 /// # Examples
2111 ///
2112 /// ```
2113 /// use std::path::Path;
2114 ///
2115 /// let path = Path::new("/etc/passwd");
2116 ///
2117 /// assert!(path.starts_with("/etc"));
2c00a5a8
XL
2118 /// assert!(path.starts_with("/etc/"));
2119 /// assert!(path.starts_with("/etc/passwd"));
3dfed10e
XL
2120 /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay
2121 /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay
d9579d0f
AL
2122 ///
2123 /// assert!(!path.starts_with("/e"));
3dfed10e
XL
2124 /// assert!(!path.starts_with("/etc/passwd.txt"));
2125 ///
2126 /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo"));
c34b1796
AL
2127 /// ```
2128 #[stable(feature = "rust1", since = "1.0.0")]
2129 pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
e9174d1e
SL
2130 self._starts_with(base.as_ref())
2131 }
2132
2133 fn _starts_with(&self, base: &Path) -> bool {
2134 iter_after(self.components(), base.components()).is_some()
85aaf69f
SL
2135 }
2136
c34b1796
AL
2137 /// Determines whether `child` is a suffix of `self`.
2138 ///
d9579d0f
AL
2139 /// Only considers whole path components to match.
2140 ///
c34b1796
AL
2141 /// # Examples
2142 ///
2143 /// ```
2144 /// use std::path::Path;
2145 ///
3dfed10e 2146 /// let path = Path::new("/etc/resolv.conf");
c34b1796 2147 ///
3dfed10e
XL
2148 /// assert!(path.ends_with("resolv.conf"));
2149 /// assert!(path.ends_with("etc/resolv.conf"));
2150 /// assert!(path.ends_with("/etc/resolv.conf"));
2151 ///
2152 /// assert!(!path.ends_with("/resolv.conf"));
2153 /// assert!(!path.ends_with("conf")); // use .extension() instead
c34b1796
AL
2154 /// ```
2155 #[stable(feature = "rust1", since = "1.0.0")]
2156 pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
e9174d1e
SL
2157 self._ends_with(child.as_ref())
2158 }
2159
2160 fn _ends_with(&self, child: &Path) -> bool {
2161 iter_after(self.components().rev(), child.components().rev()).is_some()
85aaf69f
SL
2162 }
2163
cc61c64b 2164 /// Extracts the stem (non-extension) portion of [`self.file_name`].
9e0c209e 2165 ///
3dfed10e 2166 /// [`self.file_name`]: Path::file_name
85aaf69f
SL
2167 ///
2168 /// The stem is:
2169 ///
32a655c1 2170 /// * [`None`], if there is no file name;
85aaf69f
SL
2171 /// * The entire file name if there is no embedded `.`;
2172 /// * The entire file name if the file name begins with `.` and has no other `.`s within;
2173 /// * Otherwise, the portion of the file name before the final `.`
c34b1796
AL
2174 ///
2175 /// # Examples
2176 ///
2177 /// ```
2178 /// use std::path::Path;
2179 ///
3dfed10e
XL
2180 /// assert_eq!("foo", Path::new("foo.rs").file_stem().unwrap());
2181 /// assert_eq!("foo.tar", Path::new("foo.tar.gz").file_stem().unwrap());
c34b1796
AL
2182 /// ```
2183 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
2184 pub fn file_stem(&self) -> Option<&OsStr> {
2185 self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
2186 }
2187
cc61c64b 2188 /// Extracts the extension of [`self.file_name`], if possible.
9e0c209e 2189 ///
85aaf69f
SL
2190 /// The extension is:
2191 ///
32a655c1
SL
2192 /// * [`None`], if there is no file name;
2193 /// * [`None`], if there is no embedded `.`;
2194 /// * [`None`], if the file name begins with `.` and has no other `.`s within;
85aaf69f 2195 /// * Otherwise, the portion of the file name after the final `.`
c34b1796 2196 ///
3dfed10e 2197 /// [`self.file_name`]: Path::file_name
32a655c1 2198 ///
c34b1796
AL
2199 /// # Examples
2200 ///
2201 /// ```
2202 /// use std::path::Path;
2203 ///
3dfed10e
XL
2204 /// assert_eq!("rs", Path::new("foo.rs").extension().unwrap());
2205 /// assert_eq!("gz", Path::new("foo.tar.gz").extension().unwrap());
c34b1796
AL
2206 /// ```
2207 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
2208 pub fn extension(&self) -> Option<&OsStr> {
2209 self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
2210 }
2211
9e0c209e
SL
2212 /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
2213 ///
2214 /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
85aaf69f 2215 ///
c34b1796
AL
2216 /// # Examples
2217 ///
2218 /// ```
62682a34 2219 /// use std::path::{Path, PathBuf};
c34b1796 2220 ///
62682a34 2221 /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
c34b1796
AL
2222 /// ```
2223 #[stable(feature = "rust1", since = "1.0.0")]
e74abb32 2224 #[must_use]
c34b1796 2225 pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
e9174d1e
SL
2226 self._join(path.as_ref())
2227 }
2228
2229 fn _join(&self, path: &Path) -> PathBuf {
85aaf69f
SL
2230 let mut buf = self.to_path_buf();
2231 buf.push(path);
2232 buf
2233 }
2234
9e0c209e
SL
2235 /// Creates an owned [`PathBuf`] like `self` but with the given file name.
2236 ///
2237 /// See [`PathBuf::set_file_name`] for more details.
85aaf69f 2238 ///
c34b1796
AL
2239 /// # Examples
2240 ///
2241 /// ```
62682a34 2242 /// use std::path::{Path, PathBuf};
c34b1796 2243 ///
62682a34
SL
2244 /// let path = Path::new("/tmp/foo.txt");
2245 /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
cc61c64b
XL
2246 ///
2247 /// let path = Path::new("/tmp");
2248 /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
c34b1796
AL
2249 /// ```
2250 #[stable(feature = "rust1", since = "1.0.0")]
2251 pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
e9174d1e
SL
2252 self._with_file_name(file_name.as_ref())
2253 }
2254
2255 fn _with_file_name(&self, file_name: &OsStr) -> PathBuf {
85aaf69f
SL
2256 let mut buf = self.to_path_buf();
2257 buf.set_file_name(file_name);
2258 buf
2259 }
2260
9e0c209e 2261 /// Creates an owned [`PathBuf`] like `self` but with the given extension.
85aaf69f 2262 ///
9e0c209e
SL
2263 /// See [`PathBuf::set_extension`] for more details.
2264 ///
c34b1796
AL
2265 /// # Examples
2266 ///
2267 /// ```
9346a6ac 2268 /// use std::path::{Path, PathBuf};
c34b1796 2269 ///
62682a34
SL
2270 /// let path = Path::new("foo.rs");
2271 /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
3dfed10e
XL
2272 ///
2273 /// let path = Path::new("foo.tar.gz");
2274 /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
2275 /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz"));
2276 /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt"));
c34b1796
AL
2277 /// ```
2278 #[stable(feature = "rust1", since = "1.0.0")]
2279 pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
e9174d1e
SL
2280 self._with_extension(extension.as_ref())
2281 }
2282
2283 fn _with_extension(&self, extension: &OsStr) -> PathBuf {
85aaf69f
SL
2284 let mut buf = self.to_path_buf();
2285 buf.set_extension(extension);
2286 buf
2287 }
2288
cc61c64b
XL
2289 /// Produces an iterator over the [`Component`]s of the path.
2290 ///
2291 /// When parsing the path, there is a small amount of normalization:
2292 ///
2293 /// * Repeated separators are ignored, so `a/b` and `a//b` both have
2294 /// `a` and `b` as components.
2295 ///
3b2f2976 2296 /// * Occurrences of `.` are normalized away, except if they are at the
cc61c64b
XL
2297 /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
2298 /// `a/b` all have `a` and `b` as components, but `./a/b` starts with
2299 /// an additional [`CurDir`] component.
2300 ///
0731742a
XL
2301 /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
2302 ///
cc61c64b
XL
2303 /// Note that no other normalization takes place; in particular, `a/c`
2304 /// and `a/b/../c` are distinct, to account for the possibility that `b`
2305 /// is a symbolic link (so its parent isn't `a`).
c34b1796
AL
2306 ///
2307 /// # Examples
2308 ///
2309 /// ```
62682a34
SL
2310 /// use std::path::{Path, Component};
2311 /// use std::ffi::OsStr;
c34b1796 2312 ///
62682a34 2313 /// let mut components = Path::new("/tmp/foo.txt").components();
c34b1796 2314 ///
62682a34
SL
2315 /// assert_eq!(components.next(), Some(Component::RootDir));
2316 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
2317 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
2318 /// assert_eq!(components.next(), None)
c34b1796 2319 /// ```
cc61c64b 2320 ///
3dfed10e 2321 /// [`CurDir`]: Component::CurDir
c34b1796 2322 #[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 2323 pub fn components(&self) -> Components<'_> {
85aaf69f
SL
2324 let prefix = parse_prefix(self.as_os_str());
2325 Components {
2326 path: self.as_u8_slice(),
3b2f2976 2327 prefix,
60c5eb7d
XL
2328 has_physical_root: has_physical_root(self.as_u8_slice(), prefix)
2329 || has_redox_scheme(self.as_u8_slice()),
85aaf69f 2330 front: State::Prefix,
c34b1796 2331 back: State::Body,
85aaf69f
SL
2332 }
2333 }
2334
cc61c64b
XL
2335 /// Produces an iterator over the path's components viewed as [`OsStr`]
2336 /// slices.
2337 ///
2338 /// For more information about the particulars of how the path is separated
2339 /// into components, see [`components`].
9e0c209e 2340 ///
3dfed10e 2341 /// [`components`]: Path::components
c34b1796
AL
2342 ///
2343 /// # Examples
2344 ///
2345 /// ```
62682a34
SL
2346 /// use std::path::{self, Path};
2347 /// use std::ffi::OsStr;
2348 ///
2349 /// let mut it = Path::new("/tmp/foo.txt").iter();
2350 /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
2351 /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
2352 /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
2353 /// assert_eq!(it.next(), None)
c34b1796
AL
2354 /// ```
2355 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 2356 #[inline]
532ac7d7 2357 pub fn iter(&self) -> Iter<'_> {
85aaf69f
SL
2358 Iter { inner: self.components() }
2359 }
2360
9e0c209e 2361 /// Returns an object that implements [`Display`] for safely printing paths
6a06907d
XL
2362 /// that may contain non-Unicode data. This may perform lossy conversion,
2363 /// depending on the platform. If you would like an implementation which
2364 /// escapes the path please use [`Debug`] instead.
c34b1796 2365 ///
3dfed10e 2366 /// [`Display`]: fmt::Display
9e0c209e 2367 ///
c34b1796
AL
2368 /// # Examples
2369 ///
2370 /// ```
2371 /// use std::path::Path;
2372 ///
2373 /// let path = Path::new("/tmp/foo.rs");
2374 ///
2375 /// println!("{}", path.display());
2376 /// ```
2377 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 2378 #[inline]
532ac7d7 2379 pub fn display(&self) -> Display<'_> {
85aaf69f
SL
2380 Display { path: self }
2381 }
b039eaaf 2382
cc61c64b 2383 /// Queries the file system to get information about a file, directory, etc.
b039eaaf 2384 ///
7453a54e
SL
2385 /// This function will traverse symbolic links to query information about the
2386 /// destination file.
b039eaaf 2387 ///
3157f602
XL
2388 /// This is an alias to [`fs::metadata`].
2389 ///
32a655c1
SL
2390 /// # Examples
2391 ///
2392 /// ```no_run
2393 /// use std::path::Path;
2394 ///
2395 /// let path = Path::new("/Minas/tirith");
2396 /// let metadata = path.metadata().expect("metadata call failed");
2397 /// println!("{:?}", metadata.file_type());
2398 /// ```
b039eaaf 2399 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2400 #[inline]
b039eaaf
SL
2401 pub fn metadata(&self) -> io::Result<fs::Metadata> {
2402 fs::metadata(self)
2403 }
2404
cc61c64b 2405 /// Queries the metadata about a file without following symlinks.
b039eaaf 2406 ///
3157f602
XL
2407 /// This is an alias to [`fs::symlink_metadata`].
2408 ///
32a655c1
SL
2409 /// # Examples
2410 ///
2411 /// ```no_run
2412 /// use std::path::Path;
2413 ///
2414 /// let path = Path::new("/Minas/tirith");
2415 /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
2416 /// println!("{:?}", metadata.file_type());
2417 /// ```
b039eaaf 2418 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2419 #[inline]
b039eaaf
SL
2420 pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
2421 fs::symlink_metadata(self)
2422 }
2423
94b46f34
XL
2424 /// Returns the canonical, absolute form of the path with all intermediate
2425 /// components normalized and symbolic links resolved.
b039eaaf 2426 ///
3157f602
XL
2427 /// This is an alias to [`fs::canonicalize`].
2428 ///
32a655c1
SL
2429 /// # Examples
2430 ///
2431 /// ```no_run
2432 /// use std::path::{Path, PathBuf};
2433 ///
2434 /// let path = Path::new("/foo/test/../test/bar.rs");
2435 /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
2436 /// ```
b039eaaf 2437 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2438 #[inline]
b039eaaf
SL
2439 pub fn canonicalize(&self) -> io::Result<PathBuf> {
2440 fs::canonicalize(self)
2441 }
2442
7453a54e 2443 /// Reads a symbolic link, returning the file that the link points to.
b039eaaf 2444 ///
3157f602
XL
2445 /// This is an alias to [`fs::read_link`].
2446 ///
32a655c1
SL
2447 /// # Examples
2448 ///
2449 /// ```no_run
2450 /// use std::path::Path;
2451 ///
2452 /// let path = Path::new("/laputa/sky_castle.rs");
2453 /// let path_link = path.read_link().expect("read_link call failed");
2454 /// ```
b039eaaf 2455 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2456 #[inline]
b039eaaf
SL
2457 pub fn read_link(&self) -> io::Result<PathBuf> {
2458 fs::read_link(self)
2459 }
2460
7453a54e 2461 /// Returns an iterator over the entries within a directory.
b039eaaf 2462 ///
3dfed10e 2463 /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New
9e0c209e 2464 /// errors may be encountered after an iterator is initially constructed.
7453a54e 2465 ///
3157f602
XL
2466 /// This is an alias to [`fs::read_dir`].
2467 ///
32a655c1
SL
2468 /// # Examples
2469 ///
2470 /// ```no_run
2471 /// use std::path::Path;
2472 ///
2473 /// let path = Path::new("/laputa");
2474 /// for entry in path.read_dir().expect("read_dir call failed") {
2475 /// if let Ok(entry) = entry {
2476 /// println!("{:?}", entry.path());
2477 /// }
2478 /// }
2479 /// ```
b039eaaf 2480 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2481 #[inline]
b039eaaf
SL
2482 pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
2483 fs::read_dir(self)
2484 }
2485
9fa01778 2486 /// Returns `true` if the path points at an existing entity.
7453a54e
SL
2487 ///
2488 /// This function will traverse symbolic links to query information about the
17df50a5 2489 /// destination file.
7453a54e 2490 ///
17df50a5
XL
2491 /// If you cannot access the metadata of the file, e.g. because of a
2492 /// permission error or broken symbolic links, this will return `false`.
041b39d2 2493 ///
7453a54e
SL
2494 /// # Examples
2495 ///
2496 /// ```no_run
2497 /// use std::path::Path;
3dfed10e 2498 /// assert!(!Path::new("does_not_exist.txt").exists());
7453a54e 2499 /// ```
041b39d2
XL
2500 ///
2501 /// # See Also
2502 ///
2503 /// This is a convenience function that coerces errors to false. If you want to
3dfed10e 2504 /// check errors, call [`fs::metadata`].
b039eaaf 2505 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2506 #[inline]
b039eaaf
SL
2507 pub fn exists(&self) -> bool {
2508 fs::metadata(self).is_ok()
2509 }
2510
6a06907d
XL
2511 /// Returns `Ok(true)` if the path points at an existing entity.
2512 ///
2513 /// This function will traverse symbolic links to query information about the
2514 /// destination file. In case of broken symbolic links this will return `Ok(false)`.
2515 ///
2516 /// As opposed to the `exists()` method, this one doesn't silently ignore errors
2517 /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
2518 /// denied on some of the parent directories.)
2519 ///
2520 /// # Examples
2521 ///
2522 /// ```no_run
2523 /// #![feature(path_try_exists)]
2524 ///
2525 /// use std::path::Path;
2526 /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
2527 /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
2528 /// ```
2529 // FIXME: stabilization should modify documentation of `exists()` to recommend this method
2530 // instead.
2531 #[unstable(feature = "path_try_exists", issue = "83186")]
2532 #[inline]
2533 pub fn try_exists(&self) -> io::Result<bool> {
17df50a5 2534 fs::try_exists(self)
6a06907d
XL
2535 }
2536
9fa01778 2537 /// Returns `true` if the path exists on disk and is pointing at a regular file.
7453a54e
SL
2538 ///
2539 /// This function will traverse symbolic links to query information about the
17df50a5 2540 /// destination file.
7453a54e 2541 ///
17df50a5
XL
2542 /// If you cannot access the metadata of the file, e.g. because of a
2543 /// permission error or broken symbolic links, this will return `false`.
041b39d2 2544 ///
7453a54e
SL
2545 /// # Examples
2546 ///
2547 /// ```no_run
2548 /// use std::path::Path;
2549 /// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
2550 /// assert_eq!(Path::new("a_file.txt").is_file(), true);
2551 /// ```
041b39d2
XL
2552 ///
2553 /// # See Also
2554 ///
2555 /// This is a convenience function that coerces errors to false. If you want to
3dfed10e
XL
2556 /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
2557 /// [`fs::Metadata::is_file`] if it was [`Ok`].
f035d41b
XL
2558 ///
2559 /// When the goal is simply to read from (or write to) the source, the most
2560 /// reliable way to test the source can be read (or written to) is to open
2561 /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
3dfed10e
XL
2562 /// a Unix-like system for example. See [`fs::File::open`] or
2563 /// [`fs::OpenOptions::open`] for more information.
b039eaaf
SL
2564 #[stable(feature = "path_ext", since = "1.5.0")]
2565 pub fn is_file(&self) -> bool {
2566 fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
2567 }
2568
9fa01778 2569 /// Returns `true` if the path exists on disk and is pointing at a directory.
7453a54e
SL
2570 ///
2571 /// This function will traverse symbolic links to query information about the
17df50a5 2572 /// destination file.
7453a54e 2573 ///
17df50a5
XL
2574 /// If you cannot access the metadata of the file, e.g. because of a
2575 /// permission error or broken symbolic links, this will return `false`.
041b39d2 2576 ///
7453a54e
SL
2577 /// # Examples
2578 ///
2579 /// ```no_run
2580 /// use std::path::Path;
2581 /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
2582 /// assert_eq!(Path::new("a_file.txt").is_dir(), false);
2583 /// ```
041b39d2
XL
2584 ///
2585 /// # See Also
2586 ///
2587 /// This is a convenience function that coerces errors to false. If you want to
3dfed10e
XL
2588 /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
2589 /// [`fs::Metadata::is_dir`] if it was [`Ok`].
b039eaaf
SL
2590 #[stable(feature = "path_ext", since = "1.5.0")]
2591 pub fn is_dir(&self) -> bool {
2592 fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
2593 }
cc61c64b 2594
136023e0
XL
2595 /// Returns true if the path exists on disk and is pointing at a symbolic link.
2596 ///
2597 /// This function will not traverse symbolic links.
2598 /// In case of a broken symbolic link this will also return true.
2599 ///
2600 /// If you cannot access the directory containing the file, e.g., because of a
2601 /// permission error, this will return false.
2602 ///
2603 /// # Examples
2604 ///
2605 #[cfg_attr(unix, doc = "```no_run")]
2606 #[cfg_attr(not(unix), doc = "```ignore")]
2607 /// #![feature(is_symlink)]
2608 /// use std::path::Path;
2609 /// use std::os::unix::fs::symlink;
2610 ///
2611 /// let link_path = Path::new("link");
2612 /// symlink("/origin_does_not_exists/", link_path).unwrap();
2613 /// assert_eq!(link_path.is_symlink(), true);
2614 /// assert_eq!(link_path.exists(), false);
2615 /// ```
2616 #[unstable(feature = "is_symlink", issue = "85748")]
2617 pub fn is_symlink(&self) -> bool {
2618 fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
2619 }
2620
29967ef6 2621 /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
cc61c64b 2622 /// allocating.
041b39d2 2623 #[stable(feature = "into_boxed_path", since = "1.20.0")]
cc61c64b 2624 pub fn into_path_buf(self: Box<Path>) -> PathBuf {
ea8adc8c
XL
2625 let rw = Box::into_raw(self) as *mut OsStr;
2626 let inner = unsafe { Box::from_raw(rw) };
cc61c64b
XL
2627 PathBuf { inner: OsString::from(inner) }
2628 }
85aaf69f
SL
2629}
2630
c34b1796
AL
2631#[stable(feature = "rust1", since = "1.0.0")]
2632impl AsRef<OsStr> for Path {
5869c6ff 2633 #[inline]
c34b1796
AL
2634 fn as_ref(&self) -> &OsStr {
2635 &self.inner
2636 }
2637}
2638
c34b1796 2639#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2640impl fmt::Debug for Path {
532ac7d7 2641 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2 2642 fmt::Debug::fmt(&self.inner, formatter)
85aaf69f
SL
2643 }
2644}
2645
cc61c64b
XL
2646/// Helper struct for safely printing paths with [`format!`] and `{}`.
2647///
2648/// A [`Path`] might contain non-Unicode data. This `struct` implements the
2649/// [`Display`] trait in a way that mitigates that. It is created by the
6a06907d
XL
2650/// [`display`](Path::display) method on [`Path`]. This may perform lossy
2651/// conversion, depending on the platform. If you would like an implementation
2652/// which escapes the path please use [`Debug`] instead.
cc61c64b
XL
2653///
2654/// # Examples
2655///
2656/// ```
2657/// use std::path::Path;
2658///
2659/// let path = Path::new("/tmp/foo.rs");
2660///
2661/// println!("{}", path.display());
2662/// ```
2663///
3dfed10e
XL
2664/// [`Display`]: fmt::Display
2665/// [`format!`]: crate::format
c34b1796 2666#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2667pub struct Display<'a> {
92a42be0 2668 path: &'a Path,
85aaf69f
SL
2669}
2670
c34b1796 2671#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 2672impl fmt::Debug for Display<'_> {
532ac7d7 2673 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2 2674 fmt::Debug::fmt(&self.path, f)
85aaf69f
SL
2675 }
2676}
2677
c34b1796 2678#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 2679impl fmt::Display for Display<'_> {
532ac7d7 2680 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2 2681 self.path.inner.display(f)
85aaf69f
SL
2682 }
2683}
2684
c34b1796 2685#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2686impl cmp::PartialEq for Path {
5869c6ff 2687 #[inline]
85aaf69f 2688 fn eq(&self, other: &Path) -> bool {
e9174d1e 2689 self.components().eq(other.components())
85aaf69f
SL
2690 }
2691}
2692
92a42be0
SL
2693#[stable(feature = "rust1", since = "1.0.0")]
2694impl Hash for Path {
2695 fn hash<H: Hasher>(&self, h: &mut H) {
2696 for component in self.components() {
2697 component.hash(h);
2698 }
2699 }
2700}
2701
c34b1796 2702#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
2703impl cmp::Eq for Path {}
2704
c34b1796 2705#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2706impl cmp::PartialOrd for Path {
5869c6ff 2707 #[inline]
85aaf69f 2708 fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
e9174d1e 2709 self.components().partial_cmp(other.components())
85aaf69f
SL
2710 }
2711}
2712
c34b1796 2713#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2714impl cmp::Ord for Path {
5869c6ff 2715 #[inline]
85aaf69f 2716 fn cmp(&self, other: &Path) -> cmp::Ordering {
e9174d1e 2717 self.components().cmp(other.components())
85aaf69f
SL
2718 }
2719}
2720
c34b1796
AL
2721#[stable(feature = "rust1", since = "1.0.0")]
2722impl AsRef<Path> for Path {
5869c6ff 2723 #[inline]
92a42be0
SL
2724 fn as_ref(&self) -> &Path {
2725 self
2726 }
c34b1796
AL
2727}
2728
2729#[stable(feature = "rust1", since = "1.0.0")]
2730impl AsRef<Path> for OsStr {
5869c6ff 2731 #[inline]
92a42be0
SL
2732 fn as_ref(&self) -> &Path {
2733 Path::new(self)
2734 }
c34b1796
AL
2735}
2736
7453a54e 2737#[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
9fa01778 2738impl AsRef<Path> for Cow<'_, OsStr> {
5869c6ff 2739 #[inline]
7453a54e
SL
2740 fn as_ref(&self) -> &Path {
2741 Path::new(self)
2742 }
2743}
2744
c34b1796
AL
2745#[stable(feature = "rust1", since = "1.0.0")]
2746impl AsRef<Path> for OsString {
5869c6ff 2747 #[inline]
92a42be0
SL
2748 fn as_ref(&self) -> &Path {
2749 Path::new(self)
2750 }
c34b1796
AL
2751}
2752
2753#[stable(feature = "rust1", since = "1.0.0")]
2754impl AsRef<Path> for str {
dfeec247 2755 #[inline]
92a42be0
SL
2756 fn as_ref(&self) -> &Path {
2757 Path::new(self)
2758 }
c34b1796
AL
2759}
2760
2761#[stable(feature = "rust1", since = "1.0.0")]
2762impl AsRef<Path> for String {
5869c6ff 2763 #[inline]
92a42be0
SL
2764 fn as_ref(&self) -> &Path {
2765 Path::new(self)
2766 }
c34b1796
AL
2767}
2768
2769#[stable(feature = "rust1", since = "1.0.0")]
2770impl AsRef<Path> for PathBuf {
dfeec247 2771 #[inline]
92a42be0
SL
2772 fn as_ref(&self) -> &Path {
2773 self
2774 }
2775}
2776
2777#[stable(feature = "path_into_iter", since = "1.6.0")]
2778impl<'a> IntoIterator for &'a PathBuf {
2779 type Item = &'a OsStr;
2780 type IntoIter = Iter<'a>;
5869c6ff 2781 #[inline]
60c5eb7d
XL
2782 fn into_iter(self) -> Iter<'a> {
2783 self.iter()
2784 }
92a42be0
SL
2785}
2786
2787#[stable(feature = "path_into_iter", since = "1.6.0")]
2788impl<'a> IntoIterator for &'a Path {
2789 type Item = &'a OsStr;
2790 type IntoIter = Iter<'a>;
5869c6ff 2791 #[inline]
60c5eb7d
XL
2792 fn into_iter(self) -> Iter<'a> {
2793 self.iter()
2794 }
92a42be0
SL
2795}
2796
7453a54e 2797macro_rules! impl_cmp {
92a42be0
SL
2798 ($lhs:ty, $rhs: ty) => {
2799 #[stable(feature = "partialeq_path", since = "1.6.0")]
2800 impl<'a, 'b> PartialEq<$rhs> for $lhs {
2801 #[inline]
60c5eb7d
XL
2802 fn eq(&self, other: &$rhs) -> bool {
2803 <Path as PartialEq>::eq(self, other)
2804 }
92a42be0
SL
2805 }
2806
2807 #[stable(feature = "partialeq_path", since = "1.6.0")]
2808 impl<'a, 'b> PartialEq<$lhs> for $rhs {
2809 #[inline]
60c5eb7d
XL
2810 fn eq(&self, other: &$lhs) -> bool {
2811 <Path as PartialEq>::eq(self, other)
2812 }
92a42be0
SL
2813 }
2814
7453a54e
SL
2815 #[stable(feature = "cmp_path", since = "1.8.0")]
2816 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
2817 #[inline]
2818 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
2819 <Path as PartialOrd>::partial_cmp(self, other)
2820 }
2821 }
2822
2823 #[stable(feature = "cmp_path", since = "1.8.0")]
2824 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
2825 #[inline]
2826 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
2827 <Path as PartialOrd>::partial_cmp(self, other)
2828 }
2829 }
60c5eb7d 2830 };
7453a54e
SL
2831}
2832
2833impl_cmp!(PathBuf, Path);
2834impl_cmp!(PathBuf, &'a Path);
2835impl_cmp!(Cow<'a, Path>, Path);
2836impl_cmp!(Cow<'a, Path>, &'b Path);
2837impl_cmp!(Cow<'a, Path>, PathBuf);
2838
2839macro_rules! impl_cmp_os_str {
2840 ($lhs:ty, $rhs: ty) => {
2841 #[stable(feature = "cmp_path", since = "1.8.0")]
2842 impl<'a, 'b> PartialEq<$rhs> for $lhs {
2843 #[inline]
60c5eb7d
XL
2844 fn eq(&self, other: &$rhs) -> bool {
2845 <Path as PartialEq>::eq(self, other.as_ref())
2846 }
7453a54e
SL
2847 }
2848
2849 #[stable(feature = "cmp_path", since = "1.8.0")]
2850 impl<'a, 'b> PartialEq<$lhs> for $rhs {
2851 #[inline]
60c5eb7d
XL
2852 fn eq(&self, other: &$lhs) -> bool {
2853 <Path as PartialEq>::eq(self.as_ref(), other)
2854 }
7453a54e
SL
2855 }
2856
2857 #[stable(feature = "cmp_path", since = "1.8.0")]
2858 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
2859 #[inline]
2860 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
2861 <Path as PartialOrd>::partial_cmp(self, other.as_ref())
2862 }
2863 }
2864
2865 #[stable(feature = "cmp_path", since = "1.8.0")]
2866 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
2867 #[inline]
2868 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
2869 <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
2870 }
2871 }
60c5eb7d 2872 };
c34b1796
AL
2873}
2874
7453a54e
SL
2875impl_cmp_os_str!(PathBuf, OsStr);
2876impl_cmp_os_str!(PathBuf, &'a OsStr);
2877impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
2878impl_cmp_os_str!(PathBuf, OsString);
2879impl_cmp_os_str!(Path, OsStr);
2880impl_cmp_os_str!(Path, &'a OsStr);
2881impl_cmp_os_str!(Path, Cow<'a, OsStr>);
2882impl_cmp_os_str!(Path, OsString);
2883impl_cmp_os_str!(&'a Path, OsStr);
2884impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
2885impl_cmp_os_str!(&'a Path, OsString);
2886impl_cmp_os_str!(Cow<'a, Path>, OsStr);
2887impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr);
2888impl_cmp_os_str!(Cow<'a, Path>, OsString);
92a42be0 2889
9cc50fc6
SL
2890#[stable(since = "1.7.0", feature = "strip_prefix")]
2891impl fmt::Display for StripPrefixError {
dfeec247 2892 #[allow(deprecated, deprecated_in_future)]
532ac7d7 2893 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9cc50fc6
SL
2894 self.description().fmt(f)
2895 }
2896}
2897
2898#[stable(since = "1.7.0", feature = "strip_prefix")]
2899impl Error for StripPrefixError {
dfeec247 2900 #[allow(deprecated)]
60c5eb7d
XL
2901 fn description(&self) -> &str {
2902 "prefix not found"
2903 }
9cc50fc6 2904}