]> git.proxmox.com Git - rustc.git/blame - library/std/src/path.rs
New upstream version 1.52.0~beta.3+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
572 // prefixes, it may have a "logical" rootseparator 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 {
e9174d1e 954 Iterator::eq(self.clone(), other.clone())
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.
92a42be0 1068#[derive(Clone)]
6a06907d 1069#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
c34b1796 1070#[stable(feature = "rust1", since = "1.0.0")]
416331ca
XL
1071// FIXME:
1072// `PathBuf::as_mut_vec` current implementation relies
1073// on `PathBuf` being layout-compatible with `Vec<u8>`.
1074// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`.
1075// Anyway, `PathBuf` representation and layout are considered implementation detail, are
1076// not documented and must not be relied upon.
85aaf69f 1077pub struct PathBuf {
92a42be0 1078 inner: OsString,
85aaf69f
SL
1079}
1080
1081impl PathBuf {
5869c6ff 1082 #[inline]
85aaf69f 1083 fn as_mut_vec(&mut self) -> &mut Vec<u8> {
e9174d1e 1084 unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
85aaf69f
SL
1085 }
1086
9346a6ac 1087 /// Allocates an empty `PathBuf`.
9e0c209e
SL
1088 ///
1089 /// # Examples
1090 ///
1091 /// ```
1092 /// use std::path::PathBuf;
1093 ///
1094 /// let path = PathBuf::new();
1095 /// ```
c34b1796 1096 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1097 #[inline]
c34b1796
AL
1098 pub fn new() -> PathBuf {
1099 PathBuf { inner: OsString::new() }
1100 }
1101
9fa01778
XL
1102 /// Creates a new `PathBuf` with a given capacity used to create the
1103 /// internal [`OsString`]. See [`with_capacity`] defined on [`OsString`].
1104 ///
1105 /// # Examples
1106 ///
1107 /// ```
9fa01778
XL
1108 /// use std::path::PathBuf;
1109 ///
1110 /// let mut path = PathBuf::with_capacity(10);
1111 /// let capacity = path.capacity();
1112 ///
1113 /// // This push is done without reallocating
1114 /// path.push(r"C:\");
1115 ///
1116 /// assert_eq!(capacity, path.capacity());
1117 /// ```
1118 ///
3dfed10e 1119 /// [`with_capacity`]: OsString::with_capacity
ba9703b0 1120 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1121 #[inline]
9fa01778 1122 pub fn with_capacity(capacity: usize) -> PathBuf {
60c5eb7d 1123 PathBuf { inner: OsString::with_capacity(capacity) }
9fa01778
XL
1124 }
1125
9e0c209e
SL
1126 /// Coerces to a [`Path`] slice.
1127 ///
9e0c209e
SL
1128 /// # Examples
1129 ///
1130 /// ```
1131 /// use std::path::{Path, PathBuf};
1132 ///
1133 /// let p = PathBuf::from("/test");
1134 /// assert_eq!(Path::new("/test"), p.as_path());
1135 /// ```
c34b1796 1136 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1137 #[inline]
c34b1796
AL
1138 pub fn as_path(&self) -> &Path {
1139 self
85aaf69f
SL
1140 }
1141
9346a6ac 1142 /// Extends `self` with `path`.
85aaf69f
SL
1143 ///
1144 /// If `path` is absolute, it replaces the current path.
1145 ///
1146 /// On Windows:
1147 ///
0731742a 1148 /// * if `path` has a root but no prefix (e.g., `\windows`), it
85aaf69f 1149 /// replaces everything except for the prefix (if any) of `self`.
e9174d1e 1150 /// * if `path` has a prefix but no root, it replaces `self`.
92a42be0
SL
1151 ///
1152 /// # Examples
1153 ///
476ff2be
SL
1154 /// Pushing a relative path extends the existing path:
1155 ///
92a42be0
SL
1156 /// ```
1157 /// use std::path::PathBuf;
1158 ///
476ff2be 1159 /// let mut path = PathBuf::from("/tmp");
92a42be0
SL
1160 /// path.push("file.bk");
1161 /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
476ff2be
SL
1162 /// ```
1163 ///
1164 /// Pushing an absolute path replaces the existing path:
1165 ///
1166 /// ```
1167 /// use std::path::PathBuf;
92a42be0 1168 ///
476ff2be
SL
1169 /// let mut path = PathBuf::from("/tmp");
1170 /// path.push("/etc");
1171 /// assert_eq!(path, PathBuf::from("/etc"));
92a42be0 1172 /// ```
c34b1796
AL
1173 #[stable(feature = "rust1", since = "1.0.0")]
1174 pub fn push<P: AsRef<Path>>(&mut self, path: P) {
e9174d1e
SL
1175 self._push(path.as_ref())
1176 }
c34b1796 1177
e9174d1e 1178 fn _push(&mut self, path: &Path) {
85aaf69f
SL
1179 // in general, a separator is needed if the rightmost byte is not a separator
1180 let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
1181
1182 // in the special case of `C:` on Windows, do *not* add a separator
1183 {
1184 let comps = self.components();
60c5eb7d
XL
1185 if comps.prefix_len() > 0
1186 && comps.prefix_len() == comps.path.len()
1187 && comps.prefix.unwrap().is_drive()
1188 {
85aaf69f
SL
1189 need_sep = false
1190 }
1191 }
1192
85aaf69f
SL
1193 // absolute `path` replaces `self`
1194 if path.is_absolute() || path.prefix().is_some() {
1195 self.as_mut_vec().truncate(0);
1196
0731742a 1197 // `path` has a root but no prefix, e.g., `\windows` (Windows only)
85aaf69f
SL
1198 } else if path.has_root() {
1199 let prefix_len = self.components().prefix_remaining();
1200 self.as_mut_vec().truncate(prefix_len);
1201
1202 // `path` is a pure relative path
1203 } else if need_sep {
c34b1796 1204 self.inner.push(MAIN_SEP_STR);
85aaf69f
SL
1205 }
1206
c34b1796 1207 self.inner.push(path);
85aaf69f
SL
1208 }
1209
041b39d2 1210 /// Truncates `self` to [`self.parent`].
85aaf69f 1211 ///
9fa01778 1212 /// Returns `false` and does nothing if [`self.parent`] is [`None`].
85aaf69f 1213 /// Otherwise, returns `true`.
9e0c209e 1214 ///
3dfed10e 1215 /// [`self.parent`]: Path::parent
9e0c209e
SL
1216 ///
1217 /// # Examples
1218 ///
1219 /// ```
1220 /// use std::path::{Path, PathBuf};
1221 ///
3dfed10e 1222 /// let mut p = PathBuf::from("/spirited/away.rs");
9e0c209e
SL
1223 ///
1224 /// p.pop();
3dfed10e 1225 /// assert_eq!(Path::new("/spirited"), p);
9e0c209e
SL
1226 /// p.pop();
1227 /// assert_eq!(Path::new("/"), p);
1228 /// ```
c34b1796 1229 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1230 pub fn pop(&mut self) -> bool {
1231 match self.parent().map(|p| p.as_u8_slice().len()) {
1232 Some(len) => {
1233 self.as_mut_vec().truncate(len);
1234 true
1235 }
92a42be0 1236 None => false,
85aaf69f
SL
1237 }
1238 }
1239
cc61c64b 1240 /// Updates [`self.file_name`] to `file_name`.
85aaf69f 1241 ///
cc61c64b 1242 /// If [`self.file_name`] was [`None`], this is equivalent to pushing
85aaf69f
SL
1243 /// `file_name`.
1244 ///
cc61c64b
XL
1245 /// Otherwise it is equivalent to calling [`pop`] and then pushing
1246 /// `file_name`. The new path will be a sibling of the original path.
1247 /// (That is, it will have the same parent.)
1248 ///
3dfed10e
XL
1249 /// [`self.file_name`]: Path::file_name
1250 /// [`pop`]: PathBuf::pop
9e0c209e 1251 ///
85aaf69f
SL
1252 /// # Examples
1253 ///
c34b1796
AL
1254 /// ```
1255 /// use std::path::PathBuf;
85aaf69f 1256 ///
c34b1796 1257 /// let mut buf = PathBuf::from("/");
85aaf69f
SL
1258 /// assert!(buf.file_name() == None);
1259 /// buf.set_file_name("bar");
c34b1796 1260 /// assert!(buf == PathBuf::from("/bar"));
85aaf69f
SL
1261 /// assert!(buf.file_name().is_some());
1262 /// buf.set_file_name("baz.txt");
c34b1796 1263 /// assert!(buf == PathBuf::from("/baz.txt"));
85aaf69f 1264 /// ```
c34b1796
AL
1265 #[stable(feature = "rust1", since = "1.0.0")]
1266 pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
e9174d1e
SL
1267 self._set_file_name(file_name.as_ref())
1268 }
1269
1270 fn _set_file_name(&mut self, file_name: &OsStr) {
c34b1796
AL
1271 if self.file_name().is_some() {
1272 let popped = self.pop();
1273 debug_assert!(popped);
85aaf69f 1274 }
e9174d1e 1275 self.push(file_name);
85aaf69f
SL
1276 }
1277
cc61c64b 1278 /// Updates [`self.extension`] to `extension`.
9e0c209e 1279 ///
cc61c64b
XL
1280 /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
1281 /// returns `true` and updates the extension otherwise.
9e0c209e 1282 ///
cc61c64b
XL
1283 /// If [`self.extension`] is [`None`], the extension is added; otherwise
1284 /// it is replaced.
85aaf69f 1285 ///
3dfed10e
XL
1286 /// [`self.file_name`]: Path::file_name
1287 /// [`self.extension`]: Path::extension
85aaf69f 1288 ///
9e0c209e
SL
1289 /// # Examples
1290 ///
1291 /// ```
1292 /// use std::path::{Path, PathBuf};
1293 ///
1294 /// let mut p = PathBuf::from("/feel/the");
1295 ///
1296 /// p.set_extension("force");
1297 /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
1298 ///
1299 /// p.set_extension("dark_side");
1300 /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path());
1301 /// ```
c34b1796
AL
1302 #[stable(feature = "rust1", since = "1.0.0")]
1303 pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
e9174d1e
SL
1304 self._set_extension(extension.as_ref())
1305 }
1306
1307 fn _set_extension(&mut self, extension: &OsStr) -> bool {
e74abb32
XL
1308 let file_stem = match self.file_stem() {
1309 None => return false,
1310 Some(f) => os_str_as_u8_slice(f),
85aaf69f
SL
1311 };
1312
e74abb32
XL
1313 // truncate until right after the file stem
1314 let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
1315 let start = os_str_as_u8_slice(&self.inner).as_ptr() as usize;
1316 let v = self.as_mut_vec();
1317 v.truncate(end_file_stem.wrapping_sub(start));
1318
1319 // add the new extension, if any
1320 let new = os_str_as_u8_slice(extension);
1321 if !new.is_empty() {
1322 v.reserve_exact(new.len() + 1);
1323 v.push(b'.');
1324 v.extend_from_slice(new);
85aaf69f 1325 }
85aaf69f
SL
1326
1327 true
1328 }
1329
9e0c209e
SL
1330 /// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.
1331 ///
9e0c209e
SL
1332 /// # Examples
1333 ///
1334 /// ```
1335 /// use std::path::PathBuf;
1336 ///
1337 /// let p = PathBuf::from("/the/head");
1338 /// let os_str = p.into_os_string();
1339 /// ```
c34b1796 1340 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1341 #[inline]
85aaf69f
SL
1342 pub fn into_os_string(self) -> OsString {
1343 self.inner
1344 }
8bb4bdeb 1345
29967ef6 1346 /// Converts this `PathBuf` into a [boxed](Box) [`Path`].
041b39d2 1347 #[stable(feature = "into_boxed_path", since = "1.20.0")]
5869c6ff 1348 #[inline]
8bb4bdeb 1349 pub fn into_boxed_path(self) -> Box<Path> {
ea8adc8c
XL
1350 let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
1351 unsafe { Box::from_raw(rw) }
8bb4bdeb 1352 }
9fa01778
XL
1353
1354 /// Invokes [`capacity`] on the underlying instance of [`OsString`].
1355 ///
3dfed10e 1356 /// [`capacity`]: OsString::capacity
ba9703b0 1357 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1358 #[inline]
9fa01778
XL
1359 pub fn capacity(&self) -> usize {
1360 self.inner.capacity()
1361 }
1362
1363 /// Invokes [`clear`] on the underlying instance of [`OsString`].
1364 ///
3dfed10e 1365 /// [`clear`]: OsString::clear
ba9703b0 1366 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1367 #[inline]
9fa01778
XL
1368 pub fn clear(&mut self) {
1369 self.inner.clear()
1370 }
1371
1372 /// Invokes [`reserve`] on the underlying instance of [`OsString`].
1373 ///
3dfed10e 1374 /// [`reserve`]: OsString::reserve
ba9703b0 1375 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1376 #[inline]
9fa01778
XL
1377 pub fn reserve(&mut self, additional: usize) {
1378 self.inner.reserve(additional)
1379 }
1380
1381 /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].
1382 ///
3dfed10e 1383 /// [`reserve_exact`]: OsString::reserve_exact
ba9703b0 1384 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1385 #[inline]
9fa01778
XL
1386 pub fn reserve_exact(&mut self, additional: usize) {
1387 self.inner.reserve_exact(additional)
1388 }
1389
1390 /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].
1391 ///
3dfed10e 1392 /// [`shrink_to_fit`]: OsString::shrink_to_fit
ba9703b0 1393 #[stable(feature = "path_buf_capacity", since = "1.44.0")]
5869c6ff 1394 #[inline]
9fa01778
XL
1395 pub fn shrink_to_fit(&mut self) {
1396 self.inner.shrink_to_fit()
1397 }
1398
1399 /// Invokes [`shrink_to`] on the underlying instance of [`OsString`].
1400 ///
3dfed10e 1401 /// [`shrink_to`]: OsString::shrink_to
ba9703b0 1402 #[unstable(feature = "shrink_to", issue = "56431")]
5869c6ff 1403 #[inline]
9fa01778
XL
1404 pub fn shrink_to(&mut self, min_capacity: usize) {
1405 self.inner.shrink_to(min_capacity)
1406 }
8bb4bdeb
XL
1407}
1408
1409#[stable(feature = "box_from_path", since = "1.17.0")]
532ac7d7
XL
1410impl From<&Path> for Box<Path> {
1411 fn from(path: &Path) -> Box<Path> {
8bb4bdeb 1412 let boxed: Box<OsStr> = path.inner.into();
ea8adc8c
XL
1413 let rw = Box::into_raw(boxed) as *mut Path;
1414 unsafe { Box::from_raw(rw) }
8bb4bdeb 1415 }
85aaf69f
SL
1416}
1417
f9f354fc
XL
1418#[stable(feature = "box_from_cow", since = "1.45.0")]
1419impl From<Cow<'_, Path>> for Box<Path> {
1420 #[inline]
1421 fn from(cow: Cow<'_, Path>) -> Box<Path> {
1422 match cow {
1423 Cow::Borrowed(path) => Box::from(path),
1424 Cow::Owned(path) => Box::from(path),
1425 }
1426 }
1427}
1428
7cac9316
XL
1429#[stable(feature = "path_buf_from_box", since = "1.18.0")]
1430impl From<Box<Path>> for PathBuf {
0731742a
XL
1431 /// Converts a `Box<Path>` into a `PathBuf`
1432 ///
1433 /// This conversion does not allocate or copy memory.
5869c6ff 1434 #[inline]
cc61c64b
XL
1435 fn from(boxed: Box<Path>) -> PathBuf {
1436 boxed.into_path_buf()
1437 }
1438}
1439
041b39d2
XL
1440#[stable(feature = "box_from_path_buf", since = "1.20.0")]
1441impl From<PathBuf> for Box<Path> {
0731742a
XL
1442 /// Converts a `PathBuf` into a `Box<Path>`
1443 ///
1444 /// This conversion currently should not allocate memory,
1445 /// but this behavior is not guaranteed on all platforms or in all future versions.
5869c6ff 1446 #[inline]
041b39d2
XL
1447 fn from(p: PathBuf) -> Box<Path> {
1448 p.into_boxed_path()
cc61c64b
XL
1449 }
1450}
1451
8faf50e0
XL
1452#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
1453impl Clone for Box<Path> {
1454 #[inline]
1455 fn clone(&self) -> Self {
1456 self.to_path_buf().into_boxed_path()
1457 }
1458}
1459
c34b1796 1460#[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 1461impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
5869c6ff 1462 #[inline]
532ac7d7 1463 fn from(s: &T) -> PathBuf {
c34b1796
AL
1464 PathBuf::from(s.as_ref().to_os_string())
1465 }
1466}
1467
1468#[stable(feature = "rust1", since = "1.0.0")]
1469impl From<OsString> for PathBuf {
0731742a
XL
1470 /// Converts a `OsString` into a `PathBuf`
1471 ///
1472 /// This conversion does not allocate or copy memory.
dfeec247 1473 #[inline]
c34b1796
AL
1474 fn from(s: OsString) -> PathBuf {
1475 PathBuf { inner: s }
1476 }
1477}
1478
c30ab7b3
SL
1479#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]
1480impl From<PathBuf> for OsString {
0731742a
XL
1481 /// Converts a `PathBuf` into a `OsString`
1482 ///
1483 /// This conversion does not allocate or copy memory.
5869c6ff 1484 #[inline]
60c5eb7d 1485 fn from(path_buf: PathBuf) -> OsString {
c30ab7b3
SL
1486 path_buf.inner
1487 }
1488}
1489
c34b1796
AL
1490#[stable(feature = "rust1", since = "1.0.0")]
1491impl From<String> for PathBuf {
0731742a
XL
1492 /// Converts a `String` into a `PathBuf`
1493 ///
1494 /// This conversion does not allocate or copy memory.
5869c6ff 1495 #[inline]
c34b1796
AL
1496 fn from(s: String) -> PathBuf {
1497 PathBuf::from(OsString::from(s))
1498 }
1499}
1500
0731742a 1501#[stable(feature = "path_from_str", since = "1.32.0")]
a1dfa0c6 1502impl FromStr for PathBuf {
9fa01778 1503 type Err = core::convert::Infallible;
a1dfa0c6 1504
5869c6ff 1505 #[inline]
a1dfa0c6
XL
1506 fn from_str(s: &str) -> Result<Self, Self::Err> {
1507 Ok(PathBuf::from(s))
1508 }
1509}
1510
c34b1796
AL
1511#[stable(feature = "rust1", since = "1.0.0")]
1512impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
1513 fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
1514 let mut buf = PathBuf::new();
85aaf69f
SL
1515 buf.extend(iter);
1516 buf
1517 }
1518}
1519
c34b1796
AL
1520#[stable(feature = "rust1", since = "1.0.0")]
1521impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
1522 fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
532ac7d7 1523 iter.into_iter().for_each(move |p| self.push(p.as_ref()));
85aaf69f 1524 }
f9f354fc
XL
1525
1526 #[inline]
1527 fn extend_one(&mut self, p: P) {
1528 self.push(p.as_ref());
1529 }
85aaf69f
SL
1530}
1531
c34b1796 1532#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1533impl fmt::Debug for PathBuf {
532ac7d7 1534 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
85aaf69f
SL
1535 fmt::Debug::fmt(&**self, formatter)
1536 }
1537}
1538
c34b1796 1539#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1540impl ops::Deref for PathBuf {
1541 type Target = Path;
dfeec247 1542 #[inline]
85aaf69f 1543 fn deref(&self) -> &Path {
e9174d1e 1544 Path::new(&self.inner)
85aaf69f
SL
1545 }
1546}
1547
c34b1796 1548#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1549impl Borrow<Path> for PathBuf {
5869c6ff 1550 #[inline]
85aaf69f
SL
1551 fn borrow(&self) -> &Path {
1552 self.deref()
1553 }
1554}
1555
7cac9316 1556#[stable(feature = "default_for_pathbuf", since = "1.17.0")]
8bb4bdeb 1557impl Default for PathBuf {
5869c6ff 1558 #[inline]
8bb4bdeb
XL
1559 fn default() -> Self {
1560 PathBuf::new()
1561 }
1562}
1563
92a42be0
SL
1564#[stable(feature = "cow_from_path", since = "1.6.0")]
1565impl<'a> From<&'a Path> for Cow<'a, Path> {
1566 #[inline]
1567 fn from(s: &'a Path) -> Cow<'a, Path> {
1568 Cow::Borrowed(s)
1569 }
1570}
1571
1572#[stable(feature = "cow_from_path", since = "1.6.0")]
1573impl<'a> From<PathBuf> for Cow<'a, Path> {
1574 #[inline]
1575 fn from(s: PathBuf) -> Cow<'a, Path> {
1576 Cow::Owned(s)
1577 }
1578}
1579
94b46f34
XL
1580#[stable(feature = "cow_from_pathbuf_ref", since = "1.28.0")]
1581impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
1582 #[inline]
1583 fn from(p: &'a PathBuf) -> Cow<'a, Path> {
1584 Cow::Borrowed(p.as_path())
1585 }
1586}
1587
1588#[stable(feature = "pathbuf_from_cow_path", since = "1.28.0")]
1589impl<'a> From<Cow<'a, Path>> for PathBuf {
1590 #[inline]
1591 fn from(p: Cow<'a, Path>) -> Self {
1592 p.into_owned()
1593 }
1594}
1595
2c00a5a8 1596#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11 1597impl From<PathBuf> for Arc<Path> {
e74abb32 1598 /// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer.
ff7c6d11
XL
1599 #[inline]
1600 fn from(s: PathBuf) -> Arc<Path> {
1601 let arc: Arc<OsStr> = Arc::from(s.into_os_string());
1602 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1603 }
1604}
1605
2c00a5a8 1606#[stable(feature = "shared_from_slice2", since = "1.24.0")]
532ac7d7 1607impl From<&Path> for Arc<Path> {
e74abb32 1608 /// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer.
ff7c6d11
XL
1609 #[inline]
1610 fn from(s: &Path) -> Arc<Path> {
1611 let arc: Arc<OsStr> = Arc::from(s.as_os_str());
1612 unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1613 }
1614}
1615
2c00a5a8 1616#[stable(feature = "shared_from_slice2", since = "1.24.0")]
ff7c6d11 1617impl From<PathBuf> for Rc<Path> {
e74abb32 1618 /// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer.
ff7c6d11
XL
1619 #[inline]
1620 fn from(s: PathBuf) -> Rc<Path> {
1621 let rc: Rc<OsStr> = Rc::from(s.into_os_string());
1622 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1623 }
1624}
1625
2c00a5a8 1626#[stable(feature = "shared_from_slice2", since = "1.24.0")]
532ac7d7 1627impl From<&Path> for Rc<Path> {
e74abb32 1628 /// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer.
ff7c6d11
XL
1629 #[inline]
1630 fn from(s: &Path) -> Rc<Path> {
1631 let rc: Rc<OsStr> = Rc::from(s.as_os_str());
1632 unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1633 }
1634}
1635
c34b1796 1636#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1637impl ToOwned for Path {
1638 type Owned = PathBuf;
5869c6ff 1639 #[inline]
92a42be0
SL
1640 fn to_owned(&self) -> PathBuf {
1641 self.to_path_buf()
1642 }
5869c6ff 1643 #[inline]
cc61c64b
XL
1644 fn clone_into(&self, target: &mut PathBuf) {
1645 self.inner.clone_into(&mut target.inner);
1646 }
85aaf69f
SL
1647}
1648
c34b1796 1649#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1650impl cmp::PartialEq for PathBuf {
5869c6ff 1651 #[inline]
85aaf69f
SL
1652 fn eq(&self, other: &PathBuf) -> bool {
1653 self.components() == other.components()
1654 }
1655}
1656
92a42be0
SL
1657#[stable(feature = "rust1", since = "1.0.0")]
1658impl Hash for PathBuf {
1659 fn hash<H: Hasher>(&self, h: &mut H) {
1660 self.as_path().hash(h)
1661 }
1662}
1663
c34b1796 1664#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1665impl cmp::Eq for PathBuf {}
1666
c34b1796 1667#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1668impl cmp::PartialOrd for PathBuf {
5869c6ff 1669 #[inline]
85aaf69f 1670 fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
e9174d1e 1671 self.components().partial_cmp(other.components())
85aaf69f
SL
1672 }
1673}
1674
c34b1796 1675#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1676impl cmp::Ord for PathBuf {
5869c6ff 1677 #[inline]
85aaf69f 1678 fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
e9174d1e 1679 self.components().cmp(other.components())
85aaf69f
SL
1680 }
1681}
1682
c34b1796
AL
1683#[stable(feature = "rust1", since = "1.0.0")]
1684impl AsRef<OsStr> for PathBuf {
5869c6ff 1685 #[inline]
c34b1796
AL
1686 fn as_ref(&self) -> &OsStr {
1687 &self.inner[..]
1688 }
1689}
1690
9e0c209e 1691/// A slice of a path (akin to [`str`]).
85aaf69f
SL
1692///
1693/// This type supports a number of operations for inspecting a path, including
041b39d2
XL
1694/// breaking the path into its components (separated by `/` on Unix and by either
1695/// `/` or `\` on Windows), extracting the file name, determining whether the path
1696/// is absolute, and so on.
85aaf69f 1697///
d9579d0f 1698/// This is an *unsized* type, meaning that it must always be used behind a
c30ab7b3
SL
1699/// pointer like `&` or [`Box`]. For an owned version of this type,
1700/// see [`PathBuf`].
9e0c209e 1701///
c30ab7b3 1702/// More details about the overall approach can be found in
29967ef6 1703/// the [module documentation](self).
85aaf69f 1704///
c34b1796 1705/// # Examples
85aaf69f 1706///
c34b1796 1707/// ```
85aaf69f 1708/// use std::path::Path;
476ff2be 1709/// use std::ffi::OsStr;
85aaf69f 1710///
041b39d2
XL
1711/// // Note: this example does work on Windows
1712/// let path = Path::new("./foo/bar.txt");
476ff2be
SL
1713///
1714/// let parent = path.parent();
041b39d2 1715/// assert_eq!(parent, Some(Path::new("./foo")));
476ff2be
SL
1716///
1717/// let file_stem = path.file_stem();
1718/// assert_eq!(file_stem, Some(OsStr::new("bar")));
1719///
85aaf69f 1720/// let extension = path.extension();
476ff2be 1721/// assert_eq!(extension, Some(OsStr::new("txt")));
85aaf69f 1722/// ```
6a06907d 1723#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
c34b1796 1724#[stable(feature = "rust1", since = "1.0.0")]
416331ca
XL
1725// FIXME:
1726// `Path::new` current implementation relies
1727// on `Path` being layout-compatible with `OsStr`.
1728// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`.
1729// Anyway, `Path` representation and layout are considered implementation detail, are
1730// not documented and must not be relied upon.
85aaf69f 1731pub struct Path {
92a42be0 1732 inner: OsStr,
85aaf69f
SL
1733}
1734
29967ef6 1735/// An error returned from [`Path::strip_prefix`] if the prefix was not found.
cc61c64b
XL
1736///
1737/// This `struct` is created by the [`strip_prefix`] method on [`Path`].
1738/// See its documentation for more.
32a655c1 1739///
3dfed10e 1740/// [`strip_prefix`]: Path::strip_prefix
9cc50fc6
SL
1741#[derive(Debug, Clone, PartialEq, Eq)]
1742#[stable(since = "1.7.0", feature = "strip_prefix")]
1743pub struct StripPrefixError(());
1744
85aaf69f
SL
1745impl Path {
1746 // The following (private!) function allows construction of a path from a u8
1747 // slice, which is only safe when it is known to follow the OsStr encoding.
1748 unsafe fn from_u8_slice(s: &[u8]) -> &Path {
1b1a35ee 1749 unsafe { Path::new(u8_slice_as_os_str(s)) }
85aaf69f
SL
1750 }
1751 // The following (private!) function reveals the byte encoding used for OsStr.
1752 fn as_u8_slice(&self) -> &[u8] {
e9174d1e 1753 os_str_as_u8_slice(&self.inner)
85aaf69f
SL
1754 }
1755
cc61c64b 1756 /// Directly wraps a string slice as a `Path` slice.
85aaf69f
SL
1757 ///
1758 /// This is a cost-free conversion.
c34b1796
AL
1759 ///
1760 /// # Examples
1761 ///
1762 /// ```
1763 /// use std::path::Path;
1764 ///
1765 /// Path::new("foo.txt");
1766 /// ```
bd371182
AL
1767 ///
1768 /// You can create `Path`s from `String`s, or even other `Path`s:
1769 ///
1770 /// ```
1771 /// use std::path::Path;
1772 ///
62682a34
SL
1773 /// let string = String::from("foo.txt");
1774 /// let from_string = Path::new(&string);
1775 /// let from_path = Path::new(&from_string);
1776 /// assert_eq!(from_string, from_path);
bd371182 1777 /// ```
c34b1796
AL
1778 #[stable(feature = "rust1", since = "1.0.0")]
1779 pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
ea8adc8c 1780 unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
c34b1796
AL
1781 }
1782
9e0c209e
SL
1783 /// Yields the underlying [`OsStr`] slice.
1784 ///
c34b1796
AL
1785 /// # Examples
1786 ///
1787 /// ```
1788 /// use std::path::Path;
1789 ///
1790 /// let os_str = Path::new("foo.txt").as_os_str();
62682a34 1791 /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
c34b1796
AL
1792 /// ```
1793 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1794 #[inline]
c34b1796
AL
1795 pub fn as_os_str(&self) -> &OsStr {
1796 &self.inner
85aaf69f
SL
1797 }
1798
9e0c209e 1799 /// Yields a [`&str`] slice if the `Path` is valid unicode.
85aaf69f
SL
1800 ///
1801 /// This conversion may entail doing a check for UTF-8 validity.
416331ca
XL
1802 /// Note that validation is performed because non-UTF-8 strings are
1803 /// perfectly valid for some OS.
c34b1796 1804 ///
3dfed10e 1805 /// [`&str`]: str
9e0c209e 1806 ///
c34b1796
AL
1807 /// # Examples
1808 ///
1809 /// ```
1810 /// use std::path::Path;
1811 ///
32a655c1
SL
1812 /// let path = Path::new("foo.txt");
1813 /// assert_eq!(path.to_str(), Some("foo.txt"));
c34b1796
AL
1814 /// ```
1815 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1816 #[inline]
85aaf69f
SL
1817 pub fn to_str(&self) -> Option<&str> {
1818 self.inner.to_str()
1819 }
1820
9e0c209e 1821 /// Converts a `Path` to a [`Cow<str>`].
85aaf69f 1822 ///
b7449926
XL
1823 /// Any non-Unicode sequences are replaced with
1824 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
c34b1796 1825 ///
3dfed10e 1826 /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
9e0c209e 1827 ///
c34b1796
AL
1828 /// # Examples
1829 ///
32a655c1
SL
1830 /// Calling `to_string_lossy` on a `Path` with valid unicode:
1831 ///
c34b1796
AL
1832 /// ```
1833 /// use std::path::Path;
1834 ///
32a655c1
SL
1835 /// let path = Path::new("foo.txt");
1836 /// assert_eq!(path.to_string_lossy(), "foo.txt");
c34b1796 1837 /// ```
32a655c1 1838 ///
cc61c64b 1839 /// Had `path` contained invalid unicode, the `to_string_lossy` call might
32a655c1 1840 /// have returned `"fo�.txt"`.
c34b1796 1841 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1842 #[inline]
532ac7d7 1843 pub fn to_string_lossy(&self) -> Cow<'_, str> {
85aaf69f
SL
1844 self.inner.to_string_lossy()
1845 }
1846
9e0c209e
SL
1847 /// Converts a `Path` to an owned [`PathBuf`].
1848 ///
c34b1796
AL
1849 /// # Examples
1850 ///
1851 /// ```
1852 /// use std::path::Path;
1853 ///
62682a34
SL
1854 /// let path_buf = Path::new("foo.txt").to_path_buf();
1855 /// assert_eq!(path_buf, std::path::PathBuf::from("foo.txt"));
c34b1796 1856 /// ```
2c00a5a8 1857 #[rustc_conversion_suggestion]
c34b1796 1858 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 1859 pub fn to_path_buf(&self) -> PathBuf {
c34b1796 1860 PathBuf::from(self.inner.to_os_string())
85aaf69f
SL
1861 }
1862
0731742a 1863 /// Returns `true` if the `Path` is absolute, i.e., if it is independent of
cc61c64b 1864 /// the current directory.
85aaf69f
SL
1865 ///
1866 /// * On Unix, a path is absolute if it starts with the root, so
cc61c64b 1867 /// `is_absolute` and [`has_root`] are equivalent.
85aaf69f
SL
1868 ///
1869 /// * On Windows, a path is absolute if it has a prefix and starts with the
3157f602 1870 /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not.
c34b1796
AL
1871 ///
1872 /// # Examples
1873 ///
1874 /// ```
1875 /// use std::path::Path;
1876 ///
62682a34 1877 /// assert!(!Path::new("foo.txt").is_absolute());
c34b1796 1878 /// ```
cc61c64b 1879 ///
3dfed10e 1880 /// [`has_root`]: Path::has_root
c34b1796 1881 #[stable(feature = "rust1", since = "1.0.0")]
9cc50fc6 1882 #[allow(deprecated)]
85aaf69f 1883 pub fn is_absolute(&self) -> bool {
abe05a73 1884 if cfg!(target_os = "redox") {
3b2f2976 1885 // FIXME: Allow Redox prefixes
abe05a73
XL
1886 self.has_root() || has_redox_scheme(self.as_u8_slice())
1887 } else {
1b1a35ee 1888 self.has_root() && (cfg!(any(unix, target_os = "wasi")) || self.prefix().is_some())
3b2f2976 1889 }
85aaf69f
SL
1890 }
1891
0731742a 1892 /// Returns `true` if the `Path` is relative, i.e., not absolute.
cc61c64b
XL
1893 ///
1894 /// See [`is_absolute`]'s documentation for more details.
c34b1796
AL
1895 ///
1896 /// # Examples
1897 ///
1898 /// ```
1899 /// use std::path::Path;
1900 ///
1901 /// assert!(Path::new("foo.txt").is_relative());
1902 /// ```
cc61c64b 1903 ///
3dfed10e 1904 /// [`is_absolute`]: Path::is_absolute
c34b1796 1905 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1906 #[inline]
85aaf69f
SL
1907 pub fn is_relative(&self) -> bool {
1908 !self.is_absolute()
1909 }
1910
532ac7d7 1911 fn prefix(&self) -> Option<Prefix<'_>> {
c34b1796 1912 self.components().prefix
85aaf69f
SL
1913 }
1914
cc61c64b 1915 /// Returns `true` if the `Path` has a root.
85aaf69f
SL
1916 ///
1917 /// * On Unix, a path has a root if it begins with `/`.
1918 ///
1919 /// * On Windows, a path has a root if it:
0731742a
XL
1920 /// * has no prefix and begins with a separator, e.g., `\windows`
1921 /// * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows`
1922 /// * has any non-disk prefix, e.g., `\\server\share`
c34b1796
AL
1923 ///
1924 /// # Examples
1925 ///
1926 /// ```
1927 /// use std::path::Path;
1928 ///
1929 /// assert!(Path::new("/etc/passwd").has_root());
1930 /// ```
1931 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 1932 #[inline]
85aaf69f 1933 pub fn has_root(&self) -> bool {
92a42be0 1934 self.components().has_root()
85aaf69f
SL
1935 }
1936
cc61c64b 1937 /// Returns the `Path` without its final component, if there is one.
85aaf69f 1938 ///
32a655c1
SL
1939 /// Returns [`None`] if the path terminates in a root or prefix.
1940 ///
85aaf69f
SL
1941 /// # Examples
1942 ///
c34b1796 1943 /// ```
85aaf69f
SL
1944 /// use std::path::Path;
1945 ///
1946 /// let path = Path::new("/foo/bar");
62682a34
SL
1947 /// let parent = path.parent().unwrap();
1948 /// assert_eq!(parent, Path::new("/foo"));
c34b1796 1949 ///
62682a34
SL
1950 /// let grand_parent = parent.parent().unwrap();
1951 /// assert_eq!(grand_parent, Path::new("/"));
1952 /// assert_eq!(grand_parent.parent(), None);
85aaf69f 1953 /// ```
c34b1796 1954 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
1955 pub fn parent(&self) -> Option<&Path> {
1956 let mut comps = self.components();
1957 let comp = comps.next_back();
60c5eb7d
XL
1958 comp.and_then(|p| match p {
1959 Component::Normal(_) | Component::CurDir | Component::ParentDir => {
1960 Some(comps.as_path())
92a42be0 1961 }
60c5eb7d 1962 _ => None,
c34b1796 1963 })
85aaf69f
SL
1964 }
1965
0531ce1d
XL
1966 /// Produces an iterator over `Path` and its ancestors.
1967 ///
1968 /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
1969 /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
1970 /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
1971 /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
1972 /// namely `&self`.
1973 ///
1974 /// # Examples
1975 ///
1976 /// ```
0531ce1d
XL
1977 /// use std::path::Path;
1978 ///
1979 /// let mut ancestors = Path::new("/foo/bar").ancestors();
1980 /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
1981 /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
1982 /// assert_eq!(ancestors.next(), Some(Path::new("/")));
1983 /// assert_eq!(ancestors.next(), None);
3dfed10e
XL
1984 ///
1985 /// let mut ancestors = Path::new("../foo/bar").ancestors();
1986 /// assert_eq!(ancestors.next(), Some(Path::new("../foo/bar")));
1987 /// assert_eq!(ancestors.next(), Some(Path::new("../foo")));
1988 /// assert_eq!(ancestors.next(), Some(Path::new("..")));
1989 /// assert_eq!(ancestors.next(), Some(Path::new("")));
1990 /// assert_eq!(ancestors.next(), None);
0531ce1d
XL
1991 /// ```
1992 ///
3dfed10e 1993 /// [`parent`]: Path::parent
94b46f34 1994 #[stable(feature = "path_ancestors", since = "1.28.0")]
5869c6ff 1995 #[inline]
532ac7d7 1996 pub fn ancestors(&self) -> Ancestors<'_> {
60c5eb7d 1997 Ancestors { next: Some(&self) }
0531ce1d
XL
1998 }
1999
cc61c64b 2000 /// Returns the final component of the `Path`, if there is one.
85aaf69f 2001 ///
cc61c64b
XL
2002 /// If the path is a normal file, this is the file name. If it's the path of a directory, this
2003 /// is the directory name.
2004 ///
0531ce1d 2005 /// Returns [`None`] if the path terminates in `..`.
32a655c1 2006 ///
c34b1796
AL
2007 /// # Examples
2008 ///
2009 /// ```
2010 /// use std::path::Path;
62682a34 2011 /// use std::ffi::OsStr;
c34b1796 2012 ///
cc61c64b
XL
2013 /// assert_eq!(Some(OsStr::new("bin")), Path::new("/usr/bin/").file_name());
2014 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
5bcae85e
SL
2015 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
2016 /// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
2017 /// assert_eq!(None, Path::new("foo.txt/..").file_name());
cc61c64b 2018 /// assert_eq!(None, Path::new("/").file_name());
5bcae85e 2019 /// ```
c34b1796 2020 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2021 pub fn file_name(&self) -> Option<&OsStr> {
60c5eb7d 2022 self.components().next_back().and_then(|p| match p {
74b04a01 2023 Component::Normal(p) => Some(p),
60c5eb7d 2024 _ => None,
85aaf69f
SL
2025 })
2026 }
2027
9cc50fc6
SL
2028 /// Returns a path that, when joined onto `base`, yields `self`.
2029 ///
7453a54e
SL
2030 /// # Errors
2031 ///
0731742a 2032 /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
32a655c1
SL
2033 /// returns `false`), returns [`Err`].
2034 ///
3dfed10e 2035 /// [`starts_with`]: Path::starts_with
9e0c209e
SL
2036 ///
2037 /// # Examples
2038 ///
2039 /// ```
83c7162d 2040 /// use std::path::{Path, PathBuf};
9e0c209e
SL
2041 ///
2042 /// let path = Path::new("/test/haha/foo.txt");
2043 ///
2c00a5a8 2044 /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
9e0c209e 2045 /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
2c00a5a8
XL
2046 /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
2047 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
2048 /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
3dfed10e
XL
2049 ///
2050 /// assert!(path.strip_prefix("test").is_err());
2051 /// assert!(path.strip_prefix("/haha").is_err());
83c7162d
XL
2052 ///
2053 /// let prefix = PathBuf::from("/test/");
2054 /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
9e0c209e 2055 /// ```
9cc50fc6 2056 #[stable(since = "1.7.0", feature = "path_strip_prefix")]
60c5eb7d
XL
2057 pub fn strip_prefix<P>(&self, base: P) -> Result<&Path, StripPrefixError>
2058 where
2059 P: AsRef<Path>,
9cc50fc6
SL
2060 {
2061 self._strip_prefix(base.as_ref())
e9174d1e
SL
2062 }
2063
60c5eb7d 2064 fn _strip_prefix(&self, base: &Path) -> Result<&Path, StripPrefixError> {
9cc50fc6
SL
2065 iter_after(self.components(), base.components())
2066 .map(|c| c.as_path())
2067 .ok_or(StripPrefixError(()))
85aaf69f
SL
2068 }
2069
2070 /// Determines whether `base` is a prefix of `self`.
c34b1796 2071 ///
d9579d0f
AL
2072 /// Only considers whole path components to match.
2073 ///
c34b1796
AL
2074 /// # Examples
2075 ///
2076 /// ```
2077 /// use std::path::Path;
2078 ///
2079 /// let path = Path::new("/etc/passwd");
2080 ///
2081 /// assert!(path.starts_with("/etc"));
2c00a5a8
XL
2082 /// assert!(path.starts_with("/etc/"));
2083 /// assert!(path.starts_with("/etc/passwd"));
3dfed10e
XL
2084 /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay
2085 /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay
d9579d0f
AL
2086 ///
2087 /// assert!(!path.starts_with("/e"));
3dfed10e
XL
2088 /// assert!(!path.starts_with("/etc/passwd.txt"));
2089 ///
2090 /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo"));
c34b1796
AL
2091 /// ```
2092 #[stable(feature = "rust1", since = "1.0.0")]
2093 pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
e9174d1e
SL
2094 self._starts_with(base.as_ref())
2095 }
2096
2097 fn _starts_with(&self, base: &Path) -> bool {
2098 iter_after(self.components(), base.components()).is_some()
85aaf69f
SL
2099 }
2100
c34b1796
AL
2101 /// Determines whether `child` is a suffix of `self`.
2102 ///
d9579d0f
AL
2103 /// Only considers whole path components to match.
2104 ///
c34b1796
AL
2105 /// # Examples
2106 ///
2107 /// ```
2108 /// use std::path::Path;
2109 ///
3dfed10e 2110 /// let path = Path::new("/etc/resolv.conf");
c34b1796 2111 ///
3dfed10e
XL
2112 /// assert!(path.ends_with("resolv.conf"));
2113 /// assert!(path.ends_with("etc/resolv.conf"));
2114 /// assert!(path.ends_with("/etc/resolv.conf"));
2115 ///
2116 /// assert!(!path.ends_with("/resolv.conf"));
2117 /// assert!(!path.ends_with("conf")); // use .extension() instead
c34b1796
AL
2118 /// ```
2119 #[stable(feature = "rust1", since = "1.0.0")]
2120 pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
e9174d1e
SL
2121 self._ends_with(child.as_ref())
2122 }
2123
2124 fn _ends_with(&self, child: &Path) -> bool {
2125 iter_after(self.components().rev(), child.components().rev()).is_some()
85aaf69f
SL
2126 }
2127
cc61c64b 2128 /// Extracts the stem (non-extension) portion of [`self.file_name`].
9e0c209e 2129 ///
3dfed10e 2130 /// [`self.file_name`]: Path::file_name
85aaf69f
SL
2131 ///
2132 /// The stem is:
2133 ///
32a655c1 2134 /// * [`None`], if there is no file name;
85aaf69f
SL
2135 /// * The entire file name if there is no embedded `.`;
2136 /// * The entire file name if the file name begins with `.` and has no other `.`s within;
2137 /// * Otherwise, the portion of the file name before the final `.`
c34b1796
AL
2138 ///
2139 /// # Examples
2140 ///
2141 /// ```
2142 /// use std::path::Path;
2143 ///
3dfed10e
XL
2144 /// assert_eq!("foo", Path::new("foo.rs").file_stem().unwrap());
2145 /// assert_eq!("foo.tar", Path::new("foo.tar.gz").file_stem().unwrap());
c34b1796
AL
2146 /// ```
2147 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
2148 pub fn file_stem(&self) -> Option<&OsStr> {
2149 self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
2150 }
2151
cc61c64b 2152 /// Extracts the extension of [`self.file_name`], if possible.
9e0c209e 2153 ///
85aaf69f
SL
2154 /// The extension is:
2155 ///
32a655c1
SL
2156 /// * [`None`], if there is no file name;
2157 /// * [`None`], if there is no embedded `.`;
2158 /// * [`None`], if the file name begins with `.` and has no other `.`s within;
85aaf69f 2159 /// * Otherwise, the portion of the file name after the final `.`
c34b1796 2160 ///
3dfed10e 2161 /// [`self.file_name`]: Path::file_name
32a655c1 2162 ///
c34b1796
AL
2163 /// # Examples
2164 ///
2165 /// ```
2166 /// use std::path::Path;
2167 ///
3dfed10e
XL
2168 /// assert_eq!("rs", Path::new("foo.rs").extension().unwrap());
2169 /// assert_eq!("gz", Path::new("foo.tar.gz").extension().unwrap());
c34b1796
AL
2170 /// ```
2171 #[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
2172 pub fn extension(&self) -> Option<&OsStr> {
2173 self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
2174 }
2175
9e0c209e
SL
2176 /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
2177 ///
2178 /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
85aaf69f 2179 ///
c34b1796
AL
2180 /// # Examples
2181 ///
2182 /// ```
62682a34 2183 /// use std::path::{Path, PathBuf};
c34b1796 2184 ///
62682a34 2185 /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
c34b1796
AL
2186 /// ```
2187 #[stable(feature = "rust1", since = "1.0.0")]
e74abb32 2188 #[must_use]
c34b1796 2189 pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
e9174d1e
SL
2190 self._join(path.as_ref())
2191 }
2192
2193 fn _join(&self, path: &Path) -> PathBuf {
85aaf69f
SL
2194 let mut buf = self.to_path_buf();
2195 buf.push(path);
2196 buf
2197 }
2198
9e0c209e
SL
2199 /// Creates an owned [`PathBuf`] like `self` but with the given file name.
2200 ///
2201 /// See [`PathBuf::set_file_name`] for more details.
85aaf69f 2202 ///
c34b1796
AL
2203 /// # Examples
2204 ///
2205 /// ```
62682a34 2206 /// use std::path::{Path, PathBuf};
c34b1796 2207 ///
62682a34
SL
2208 /// let path = Path::new("/tmp/foo.txt");
2209 /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
cc61c64b
XL
2210 ///
2211 /// let path = Path::new("/tmp");
2212 /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
c34b1796
AL
2213 /// ```
2214 #[stable(feature = "rust1", since = "1.0.0")]
2215 pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
e9174d1e
SL
2216 self._with_file_name(file_name.as_ref())
2217 }
2218
2219 fn _with_file_name(&self, file_name: &OsStr) -> PathBuf {
85aaf69f
SL
2220 let mut buf = self.to_path_buf();
2221 buf.set_file_name(file_name);
2222 buf
2223 }
2224
9e0c209e 2225 /// Creates an owned [`PathBuf`] like `self` but with the given extension.
85aaf69f 2226 ///
9e0c209e
SL
2227 /// See [`PathBuf::set_extension`] for more details.
2228 ///
c34b1796
AL
2229 /// # Examples
2230 ///
2231 /// ```
9346a6ac 2232 /// use std::path::{Path, PathBuf};
c34b1796 2233 ///
62682a34
SL
2234 /// let path = Path::new("foo.rs");
2235 /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
3dfed10e
XL
2236 ///
2237 /// let path = Path::new("foo.tar.gz");
2238 /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
2239 /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz"));
2240 /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt"));
c34b1796
AL
2241 /// ```
2242 #[stable(feature = "rust1", since = "1.0.0")]
2243 pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
e9174d1e
SL
2244 self._with_extension(extension.as_ref())
2245 }
2246
2247 fn _with_extension(&self, extension: &OsStr) -> PathBuf {
85aaf69f
SL
2248 let mut buf = self.to_path_buf();
2249 buf.set_extension(extension);
2250 buf
2251 }
2252
cc61c64b
XL
2253 /// Produces an iterator over the [`Component`]s of the path.
2254 ///
2255 /// When parsing the path, there is a small amount of normalization:
2256 ///
2257 /// * Repeated separators are ignored, so `a/b` and `a//b` both have
2258 /// `a` and `b` as components.
2259 ///
3b2f2976 2260 /// * Occurrences of `.` are normalized away, except if they are at the
cc61c64b
XL
2261 /// beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
2262 /// `a/b` all have `a` and `b` as components, but `./a/b` starts with
2263 /// an additional [`CurDir`] component.
2264 ///
0731742a
XL
2265 /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
2266 ///
cc61c64b
XL
2267 /// Note that no other normalization takes place; in particular, `a/c`
2268 /// and `a/b/../c` are distinct, to account for the possibility that `b`
2269 /// is a symbolic link (so its parent isn't `a`).
c34b1796
AL
2270 ///
2271 /// # Examples
2272 ///
2273 /// ```
62682a34
SL
2274 /// use std::path::{Path, Component};
2275 /// use std::ffi::OsStr;
c34b1796 2276 ///
62682a34 2277 /// let mut components = Path::new("/tmp/foo.txt").components();
c34b1796 2278 ///
62682a34
SL
2279 /// assert_eq!(components.next(), Some(Component::RootDir));
2280 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("tmp"))));
2281 /// assert_eq!(components.next(), Some(Component::Normal(OsStr::new("foo.txt"))));
2282 /// assert_eq!(components.next(), None)
c34b1796 2283 /// ```
cc61c64b 2284 ///
3dfed10e 2285 /// [`CurDir`]: Component::CurDir
c34b1796 2286 #[stable(feature = "rust1", since = "1.0.0")]
532ac7d7 2287 pub fn components(&self) -> Components<'_> {
85aaf69f
SL
2288 let prefix = parse_prefix(self.as_os_str());
2289 Components {
2290 path: self.as_u8_slice(),
3b2f2976 2291 prefix,
60c5eb7d
XL
2292 has_physical_root: has_physical_root(self.as_u8_slice(), prefix)
2293 || has_redox_scheme(self.as_u8_slice()),
85aaf69f 2294 front: State::Prefix,
c34b1796 2295 back: State::Body,
85aaf69f
SL
2296 }
2297 }
2298
cc61c64b
XL
2299 /// Produces an iterator over the path's components viewed as [`OsStr`]
2300 /// slices.
2301 ///
2302 /// For more information about the particulars of how the path is separated
2303 /// into components, see [`components`].
9e0c209e 2304 ///
3dfed10e 2305 /// [`components`]: Path::components
c34b1796
AL
2306 ///
2307 /// # Examples
2308 ///
2309 /// ```
62682a34
SL
2310 /// use std::path::{self, Path};
2311 /// use std::ffi::OsStr;
2312 ///
2313 /// let mut it = Path::new("/tmp/foo.txt").iter();
2314 /// assert_eq!(it.next(), Some(OsStr::new(&path::MAIN_SEPARATOR.to_string())));
2315 /// assert_eq!(it.next(), Some(OsStr::new("tmp")));
2316 /// assert_eq!(it.next(), Some(OsStr::new("foo.txt")));
2317 /// assert_eq!(it.next(), None)
c34b1796
AL
2318 /// ```
2319 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 2320 #[inline]
532ac7d7 2321 pub fn iter(&self) -> Iter<'_> {
85aaf69f
SL
2322 Iter { inner: self.components() }
2323 }
2324
9e0c209e 2325 /// Returns an object that implements [`Display`] for safely printing paths
6a06907d
XL
2326 /// that may contain non-Unicode data. This may perform lossy conversion,
2327 /// depending on the platform. If you would like an implementation which
2328 /// escapes the path please use [`Debug`] instead.
c34b1796 2329 ///
3dfed10e 2330 /// [`Display`]: fmt::Display
9e0c209e 2331 ///
c34b1796
AL
2332 /// # Examples
2333 ///
2334 /// ```
2335 /// use std::path::Path;
2336 ///
2337 /// let path = Path::new("/tmp/foo.rs");
2338 ///
2339 /// println!("{}", path.display());
2340 /// ```
2341 #[stable(feature = "rust1", since = "1.0.0")]
5869c6ff 2342 #[inline]
532ac7d7 2343 pub fn display(&self) -> Display<'_> {
85aaf69f
SL
2344 Display { path: self }
2345 }
b039eaaf 2346
cc61c64b 2347 /// Queries the file system to get information about a file, directory, etc.
b039eaaf 2348 ///
7453a54e
SL
2349 /// This function will traverse symbolic links to query information about the
2350 /// destination file.
b039eaaf 2351 ///
3157f602
XL
2352 /// This is an alias to [`fs::metadata`].
2353 ///
32a655c1
SL
2354 /// # Examples
2355 ///
2356 /// ```no_run
2357 /// use std::path::Path;
2358 ///
2359 /// let path = Path::new("/Minas/tirith");
2360 /// let metadata = path.metadata().expect("metadata call failed");
2361 /// println!("{:?}", metadata.file_type());
2362 /// ```
b039eaaf 2363 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2364 #[inline]
b039eaaf
SL
2365 pub fn metadata(&self) -> io::Result<fs::Metadata> {
2366 fs::metadata(self)
2367 }
2368
cc61c64b 2369 /// Queries the metadata about a file without following symlinks.
b039eaaf 2370 ///
3157f602
XL
2371 /// This is an alias to [`fs::symlink_metadata`].
2372 ///
32a655c1
SL
2373 /// # Examples
2374 ///
2375 /// ```no_run
2376 /// use std::path::Path;
2377 ///
2378 /// let path = Path::new("/Minas/tirith");
2379 /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
2380 /// println!("{:?}", metadata.file_type());
2381 /// ```
b039eaaf 2382 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2383 #[inline]
b039eaaf
SL
2384 pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
2385 fs::symlink_metadata(self)
2386 }
2387
94b46f34
XL
2388 /// Returns the canonical, absolute form of the path with all intermediate
2389 /// components normalized and symbolic links resolved.
b039eaaf 2390 ///
3157f602
XL
2391 /// This is an alias to [`fs::canonicalize`].
2392 ///
32a655c1
SL
2393 /// # Examples
2394 ///
2395 /// ```no_run
2396 /// use std::path::{Path, PathBuf};
2397 ///
2398 /// let path = Path::new("/foo/test/../test/bar.rs");
2399 /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
2400 /// ```
b039eaaf 2401 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2402 #[inline]
b039eaaf
SL
2403 pub fn canonicalize(&self) -> io::Result<PathBuf> {
2404 fs::canonicalize(self)
2405 }
2406
7453a54e 2407 /// Reads a symbolic link, returning the file that the link points to.
b039eaaf 2408 ///
3157f602
XL
2409 /// This is an alias to [`fs::read_link`].
2410 ///
32a655c1
SL
2411 /// # Examples
2412 ///
2413 /// ```no_run
2414 /// use std::path::Path;
2415 ///
2416 /// let path = Path::new("/laputa/sky_castle.rs");
2417 /// let path_link = path.read_link().expect("read_link call failed");
2418 /// ```
b039eaaf 2419 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2420 #[inline]
b039eaaf
SL
2421 pub fn read_link(&self) -> io::Result<PathBuf> {
2422 fs::read_link(self)
2423 }
2424
7453a54e 2425 /// Returns an iterator over the entries within a directory.
b039eaaf 2426 ///
3dfed10e 2427 /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New
9e0c209e 2428 /// errors may be encountered after an iterator is initially constructed.
7453a54e 2429 ///
3157f602
XL
2430 /// This is an alias to [`fs::read_dir`].
2431 ///
32a655c1
SL
2432 /// # Examples
2433 ///
2434 /// ```no_run
2435 /// use std::path::Path;
2436 ///
2437 /// let path = Path::new("/laputa");
2438 /// for entry in path.read_dir().expect("read_dir call failed") {
2439 /// if let Ok(entry) = entry {
2440 /// println!("{:?}", entry.path());
2441 /// }
2442 /// }
2443 /// ```
b039eaaf 2444 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2445 #[inline]
b039eaaf
SL
2446 pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
2447 fs::read_dir(self)
2448 }
2449
9fa01778 2450 /// Returns `true` if the path points at an existing entity.
7453a54e
SL
2451 ///
2452 /// This function will traverse symbolic links to query information about the
2453 /// destination file. In case of broken symbolic links this will return `false`.
2454 ///
0731742a 2455 /// If you cannot access the directory containing the file, e.g., because of a
041b39d2
XL
2456 /// permission error, this will return `false`.
2457 ///
7453a54e
SL
2458 /// # Examples
2459 ///
2460 /// ```no_run
2461 /// use std::path::Path;
3dfed10e 2462 /// assert!(!Path::new("does_not_exist.txt").exists());
7453a54e 2463 /// ```
041b39d2
XL
2464 ///
2465 /// # See Also
2466 ///
2467 /// This is a convenience function that coerces errors to false. If you want to
3dfed10e 2468 /// check errors, call [`fs::metadata`].
b039eaaf 2469 #[stable(feature = "path_ext", since = "1.5.0")]
5869c6ff 2470 #[inline]
b039eaaf
SL
2471 pub fn exists(&self) -> bool {
2472 fs::metadata(self).is_ok()
2473 }
2474
6a06907d
XL
2475 /// Returns `Ok(true)` if the path points at an existing entity.
2476 ///
2477 /// This function will traverse symbolic links to query information about the
2478 /// destination file. In case of broken symbolic links this will return `Ok(false)`.
2479 ///
2480 /// As opposed to the `exists()` method, this one doesn't silently ignore errors
2481 /// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
2482 /// denied on some of the parent directories.)
2483 ///
2484 /// # Examples
2485 ///
2486 /// ```no_run
2487 /// #![feature(path_try_exists)]
2488 ///
2489 /// use std::path::Path;
2490 /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
2491 /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
2492 /// ```
2493 // FIXME: stabilization should modify documentation of `exists()` to recommend this method
2494 // instead.
2495 #[unstable(feature = "path_try_exists", issue = "83186")]
2496 #[inline]
2497 pub fn try_exists(&self) -> io::Result<bool> {
2498 match fs::metadata(self) {
2499 Ok(_) => Ok(true),
2500 Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
2501 Err(error) => Err(error),
2502 }
2503 }
2504
9fa01778 2505 /// Returns `true` if the path exists on disk and is pointing at a regular file.
7453a54e
SL
2506 ///
2507 /// This function will traverse symbolic links to query information about the
2508 /// destination file. In case of broken symbolic links this will return `false`.
2509 ///
0731742a 2510 /// If you cannot access the directory containing the file, e.g., because of a
041b39d2
XL
2511 /// permission error, this will return `false`.
2512 ///
7453a54e
SL
2513 /// # Examples
2514 ///
2515 /// ```no_run
2516 /// use std::path::Path;
2517 /// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
2518 /// assert_eq!(Path::new("a_file.txt").is_file(), true);
2519 /// ```
041b39d2
XL
2520 ///
2521 /// # See Also
2522 ///
2523 /// This is a convenience function that coerces errors to false. If you want to
3dfed10e
XL
2524 /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
2525 /// [`fs::Metadata::is_file`] if it was [`Ok`].
f035d41b
XL
2526 ///
2527 /// When the goal is simply to read from (or write to) the source, the most
2528 /// reliable way to test the source can be read (or written to) is to open
2529 /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
3dfed10e
XL
2530 /// a Unix-like system for example. See [`fs::File::open`] or
2531 /// [`fs::OpenOptions::open`] for more information.
b039eaaf
SL
2532 #[stable(feature = "path_ext", since = "1.5.0")]
2533 pub fn is_file(&self) -> bool {
2534 fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
2535 }
2536
9fa01778 2537 /// Returns `true` if the path exists on disk and is pointing at a directory.
7453a54e
SL
2538 ///
2539 /// This function will traverse symbolic links to query information about the
2540 /// destination file. In case of broken symbolic links this will return `false`.
2541 ///
0731742a 2542 /// If you cannot access the directory containing the file, e.g., because of a
041b39d2
XL
2543 /// permission error, this will return `false`.
2544 ///
7453a54e
SL
2545 /// # Examples
2546 ///
2547 /// ```no_run
2548 /// use std::path::Path;
2549 /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
2550 /// assert_eq!(Path::new("a_file.txt").is_dir(), false);
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_dir`] if it was [`Ok`].
b039eaaf
SL
2558 #[stable(feature = "path_ext", since = "1.5.0")]
2559 pub fn is_dir(&self) -> bool {
2560 fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
2561 }
cc61c64b 2562
29967ef6 2563 /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
cc61c64b 2564 /// allocating.
041b39d2 2565 #[stable(feature = "into_boxed_path", since = "1.20.0")]
cc61c64b 2566 pub fn into_path_buf(self: Box<Path>) -> PathBuf {
ea8adc8c
XL
2567 let rw = Box::into_raw(self) as *mut OsStr;
2568 let inner = unsafe { Box::from_raw(rw) };
cc61c64b
XL
2569 PathBuf { inner: OsString::from(inner) }
2570 }
85aaf69f
SL
2571}
2572
c34b1796
AL
2573#[stable(feature = "rust1", since = "1.0.0")]
2574impl AsRef<OsStr> for Path {
5869c6ff 2575 #[inline]
c34b1796
AL
2576 fn as_ref(&self) -> &OsStr {
2577 &self.inner
2578 }
2579}
2580
c34b1796 2581#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2582impl fmt::Debug for Path {
532ac7d7 2583 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2 2584 fmt::Debug::fmt(&self.inner, formatter)
85aaf69f
SL
2585 }
2586}
2587
cc61c64b
XL
2588/// Helper struct for safely printing paths with [`format!`] and `{}`.
2589///
2590/// A [`Path`] might contain non-Unicode data. This `struct` implements the
2591/// [`Display`] trait in a way that mitigates that. It is created by the
6a06907d
XL
2592/// [`display`](Path::display) method on [`Path`]. This may perform lossy
2593/// conversion, depending on the platform. If you would like an implementation
2594/// which escapes the path please use [`Debug`] instead.
cc61c64b
XL
2595///
2596/// # Examples
2597///
2598/// ```
2599/// use std::path::Path;
2600///
2601/// let path = Path::new("/tmp/foo.rs");
2602///
2603/// println!("{}", path.display());
2604/// ```
2605///
3dfed10e
XL
2606/// [`Display`]: fmt::Display
2607/// [`format!`]: crate::format
c34b1796 2608#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2609pub struct Display<'a> {
92a42be0 2610 path: &'a Path,
85aaf69f
SL
2611}
2612
c34b1796 2613#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 2614impl fmt::Debug for Display<'_> {
532ac7d7 2615 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2 2616 fmt::Debug::fmt(&self.path, f)
85aaf69f
SL
2617 }
2618}
2619
c34b1796 2620#[stable(feature = "rust1", since = "1.0.0")]
9fa01778 2621impl fmt::Display for Display<'_> {
532ac7d7 2622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
041b39d2 2623 self.path.inner.display(f)
85aaf69f
SL
2624 }
2625}
2626
c34b1796 2627#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2628impl cmp::PartialEq for Path {
5869c6ff 2629 #[inline]
85aaf69f 2630 fn eq(&self, other: &Path) -> bool {
e9174d1e 2631 self.components().eq(other.components())
85aaf69f
SL
2632 }
2633}
2634
92a42be0
SL
2635#[stable(feature = "rust1", since = "1.0.0")]
2636impl Hash for Path {
2637 fn hash<H: Hasher>(&self, h: &mut H) {
2638 for component in self.components() {
2639 component.hash(h);
2640 }
2641 }
2642}
2643
c34b1796 2644#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f
SL
2645impl cmp::Eq for Path {}
2646
c34b1796 2647#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2648impl cmp::PartialOrd for Path {
5869c6ff 2649 #[inline]
85aaf69f 2650 fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
e9174d1e 2651 self.components().partial_cmp(other.components())
85aaf69f
SL
2652 }
2653}
2654
c34b1796 2655#[stable(feature = "rust1", since = "1.0.0")]
85aaf69f 2656impl cmp::Ord for Path {
5869c6ff 2657 #[inline]
85aaf69f 2658 fn cmp(&self, other: &Path) -> cmp::Ordering {
e9174d1e 2659 self.components().cmp(other.components())
85aaf69f
SL
2660 }
2661}
2662
c34b1796
AL
2663#[stable(feature = "rust1", since = "1.0.0")]
2664impl AsRef<Path> for Path {
5869c6ff 2665 #[inline]
92a42be0
SL
2666 fn as_ref(&self) -> &Path {
2667 self
2668 }
c34b1796
AL
2669}
2670
2671#[stable(feature = "rust1", since = "1.0.0")]
2672impl AsRef<Path> for OsStr {
5869c6ff 2673 #[inline]
92a42be0
SL
2674 fn as_ref(&self) -> &Path {
2675 Path::new(self)
2676 }
c34b1796
AL
2677}
2678
7453a54e 2679#[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
9fa01778 2680impl AsRef<Path> for Cow<'_, OsStr> {
5869c6ff 2681 #[inline]
7453a54e
SL
2682 fn as_ref(&self) -> &Path {
2683 Path::new(self)
2684 }
2685}
2686
c34b1796
AL
2687#[stable(feature = "rust1", since = "1.0.0")]
2688impl AsRef<Path> for OsString {
5869c6ff 2689 #[inline]
92a42be0
SL
2690 fn as_ref(&self) -> &Path {
2691 Path::new(self)
2692 }
c34b1796
AL
2693}
2694
2695#[stable(feature = "rust1", since = "1.0.0")]
2696impl AsRef<Path> for str {
dfeec247 2697 #[inline]
92a42be0
SL
2698 fn as_ref(&self) -> &Path {
2699 Path::new(self)
2700 }
c34b1796
AL
2701}
2702
2703#[stable(feature = "rust1", since = "1.0.0")]
2704impl AsRef<Path> for String {
5869c6ff 2705 #[inline]
92a42be0
SL
2706 fn as_ref(&self) -> &Path {
2707 Path::new(self)
2708 }
c34b1796
AL
2709}
2710
2711#[stable(feature = "rust1", since = "1.0.0")]
2712impl AsRef<Path> for PathBuf {
dfeec247 2713 #[inline]
92a42be0
SL
2714 fn as_ref(&self) -> &Path {
2715 self
2716 }
2717}
2718
2719#[stable(feature = "path_into_iter", since = "1.6.0")]
2720impl<'a> IntoIterator for &'a PathBuf {
2721 type Item = &'a OsStr;
2722 type IntoIter = Iter<'a>;
5869c6ff 2723 #[inline]
60c5eb7d
XL
2724 fn into_iter(self) -> Iter<'a> {
2725 self.iter()
2726 }
92a42be0
SL
2727}
2728
2729#[stable(feature = "path_into_iter", since = "1.6.0")]
2730impl<'a> IntoIterator for &'a Path {
2731 type Item = &'a OsStr;
2732 type IntoIter = Iter<'a>;
5869c6ff 2733 #[inline]
60c5eb7d
XL
2734 fn into_iter(self) -> Iter<'a> {
2735 self.iter()
2736 }
92a42be0
SL
2737}
2738
7453a54e 2739macro_rules! impl_cmp {
92a42be0
SL
2740 ($lhs:ty, $rhs: ty) => {
2741 #[stable(feature = "partialeq_path", since = "1.6.0")]
2742 impl<'a, 'b> PartialEq<$rhs> for $lhs {
2743 #[inline]
60c5eb7d
XL
2744 fn eq(&self, other: &$rhs) -> bool {
2745 <Path as PartialEq>::eq(self, other)
2746 }
92a42be0
SL
2747 }
2748
2749 #[stable(feature = "partialeq_path", since = "1.6.0")]
2750 impl<'a, 'b> PartialEq<$lhs> for $rhs {
2751 #[inline]
60c5eb7d
XL
2752 fn eq(&self, other: &$lhs) -> bool {
2753 <Path as PartialEq>::eq(self, other)
2754 }
92a42be0
SL
2755 }
2756
7453a54e
SL
2757 #[stable(feature = "cmp_path", since = "1.8.0")]
2758 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
2759 #[inline]
2760 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
2761 <Path as PartialOrd>::partial_cmp(self, other)
2762 }
2763 }
2764
2765 #[stable(feature = "cmp_path", since = "1.8.0")]
2766 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
2767 #[inline]
2768 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
2769 <Path as PartialOrd>::partial_cmp(self, other)
2770 }
2771 }
60c5eb7d 2772 };
7453a54e
SL
2773}
2774
2775impl_cmp!(PathBuf, Path);
2776impl_cmp!(PathBuf, &'a Path);
2777impl_cmp!(Cow<'a, Path>, Path);
2778impl_cmp!(Cow<'a, Path>, &'b Path);
2779impl_cmp!(Cow<'a, Path>, PathBuf);
2780
2781macro_rules! impl_cmp_os_str {
2782 ($lhs:ty, $rhs: ty) => {
2783 #[stable(feature = "cmp_path", since = "1.8.0")]
2784 impl<'a, 'b> PartialEq<$rhs> for $lhs {
2785 #[inline]
60c5eb7d
XL
2786 fn eq(&self, other: &$rhs) -> bool {
2787 <Path as PartialEq>::eq(self, other.as_ref())
2788 }
7453a54e
SL
2789 }
2790
2791 #[stable(feature = "cmp_path", since = "1.8.0")]
2792 impl<'a, 'b> PartialEq<$lhs> for $rhs {
2793 #[inline]
60c5eb7d
XL
2794 fn eq(&self, other: &$lhs) -> bool {
2795 <Path as PartialEq>::eq(self.as_ref(), other)
2796 }
7453a54e
SL
2797 }
2798
2799 #[stable(feature = "cmp_path", since = "1.8.0")]
2800 impl<'a, 'b> PartialOrd<$rhs> for $lhs {
2801 #[inline]
2802 fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
2803 <Path as PartialOrd>::partial_cmp(self, other.as_ref())
2804 }
2805 }
2806
2807 #[stable(feature = "cmp_path", since = "1.8.0")]
2808 impl<'a, 'b> PartialOrd<$lhs> for $rhs {
2809 #[inline]
2810 fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
2811 <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
2812 }
2813 }
60c5eb7d 2814 };
c34b1796
AL
2815}
2816
7453a54e
SL
2817impl_cmp_os_str!(PathBuf, OsStr);
2818impl_cmp_os_str!(PathBuf, &'a OsStr);
2819impl_cmp_os_str!(PathBuf, Cow<'a, OsStr>);
2820impl_cmp_os_str!(PathBuf, OsString);
2821impl_cmp_os_str!(Path, OsStr);
2822impl_cmp_os_str!(Path, &'a OsStr);
2823impl_cmp_os_str!(Path, Cow<'a, OsStr>);
2824impl_cmp_os_str!(Path, OsString);
2825impl_cmp_os_str!(&'a Path, OsStr);
2826impl_cmp_os_str!(&'a Path, Cow<'b, OsStr>);
2827impl_cmp_os_str!(&'a Path, OsString);
2828impl_cmp_os_str!(Cow<'a, Path>, OsStr);
2829impl_cmp_os_str!(Cow<'a, Path>, &'b OsStr);
2830impl_cmp_os_str!(Cow<'a, Path>, OsString);
92a42be0 2831
9cc50fc6
SL
2832#[stable(since = "1.7.0", feature = "strip_prefix")]
2833impl fmt::Display for StripPrefixError {
dfeec247 2834 #[allow(deprecated, deprecated_in_future)]
532ac7d7 2835 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9cc50fc6
SL
2836 self.description().fmt(f)
2837 }
2838}
2839
2840#[stable(since = "1.7.0", feature = "strip_prefix")]
2841impl Error for StripPrefixError {
dfeec247 2842 #[allow(deprecated)]
60c5eb7d
XL
2843 fn description(&self) -> &str {
2844 "prefix not found"
2845 }
9cc50fc6 2846}