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