library/std/src/path.rs RUST 4,126 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 4,126.
1//! Cross-platform path manipulation.2//!3//! This module provides two types, [`PathBuf`] and [`Path`] (akin to [`String`]4//! and [`str`]), for working with paths abstractly. These types are thin wrappers5//! around [`OsString`] and [`OsStr`] respectively, meaning that they work directly6//! on strings according to the local platform's path syntax.7//!8//! Paths can be parsed into [`Component`]s by iterating over the structure9//! returned by the [`components`] method on [`Path`]. [`Component`]s roughly10//! correspond to the substrings between path separators (`/` or `\`). You can11//! reconstruct an equivalent path from components with the [`push`] method on12//! [`PathBuf`]; note that the paths may differ syntactically by the13//! normalization described in the documentation for the [`components`] method.14//!15//! ## Case sensitivity16//!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 no19//! matter the platform or filesystem. An exception to this is made for Windows20//! drive letters.21//!22//! ## Path normalization23//!24//! Several methods in this module perform basic path normalization by disregarding25//! repeated separators, non-leading `.` components, and trailing separators. These include:26//! - Methods for iteration, such as [`Path::components`] and [`Path::iter`]27//! - Methods for inspection, such as [`Path::has_root`]28//! - Comparisons using [`PartialEq`], [`PartialOrd`], and [`Ord`]29//!30//! [`Path::join`] and [`PathBuf::push`] also disregard trailing slashes.31//!32// FIXME(normalize_lexically): mention normalize_lexically once stable33//! These methods **do not** resolve `..` components or symlinks. For full normalization34//! including `..` resolution, use [`Path::canonicalize`] (which does access the filesystem).35//!36//! ## Simple usage37//!38//! Path manipulation includes both parsing components from slices and building39//! new owned paths.40//!41//! To parse a path, you can create a [`Path`] slice from a [`str`]42//! slice and start asking questions:43//!44//! ```45//! use std::path::Path;46//! use std::ffi::OsStr;47//!48//! let path = Path::new("/tmp/foo/bar.txt");49//!50//! let parent = path.parent();51//! assert_eq!(parent, Some(Path::new("/tmp/foo")));52//!53//! let file_stem = path.file_stem();54//! assert_eq!(file_stem, Some(OsStr::new("bar")));55//!56//! let extension = path.extension();57//! assert_eq!(extension, Some(OsStr::new("txt")));58//! ```59//!60//! To build or modify paths, use [`PathBuf`]:61//!62//! ```63//! use std::path::PathBuf;64//!65//! // This way works...66//! let mut path = PathBuf::from("c:\\");67//!68//! path.push("windows");69//! path.push("system32");70//!71//! path.set_extension("dll");72//!73//! // ... but push is best used if you don't know everything up74//! // front. If you do, this way is better:75//! let path: PathBuf = ["c:\\", "windows", "system32.dll"].iter().collect();76//! ```77//!78//! [`components`]: Path::components79//! [`push`]: PathBuf::push8081#![stable(feature = "rust1", since = "1.0.0")]82#![deny(unsafe_op_in_unsafe_fn)]8384use core::clone::CloneToUninit;8586use crate::borrow::{Borrow, Cow};87use crate::collections::TryReserveError;88use crate::error::Error;89use crate::ffi::{OsStr, OsString, os_str};90use crate::hash::{Hash, Hasher};91use crate::iter::FusedIterator;92use crate::ops::{self, Deref};93use crate::rc::Rc;94use crate::str::FromStr;95use crate::sync::Arc;96use crate::sys::path::{HAS_PREFIXES, is_sep_byte, is_verbatim_sep, parse_prefix};97use crate::{cmp, fmt, fs, io, sys};9899////////////////////////////////////////////////////////////////////////////////100// GENERAL NOTES101////////////////////////////////////////////////////////////////////////////////102//103// Parsing in this module is done by directly transmuting OsStr to [u8] slices,104// taking advantage of the fact that OsStr always encodes ASCII characters105// as-is.  Eventually, this transmutation should be replaced by direct uses of106// OsStr APIs for parsing, but it will take a while for those to become107// available.108109////////////////////////////////////////////////////////////////////////////////110// Windows Prefixes111////////////////////////////////////////////////////////////////////////////////112113/// Windows path prefixes, e.g., `C:` or `\\server\share`.114///115/// Windows uses a variety of path prefix styles, including references to drive116/// volumes (like `C:`), network shared folders (like `\\server\share`), and117/// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with118/// `\\?\`), in which case `/` is *not* treated as a separator and essentially119/// no normalization is performed.120///121/// # Examples122///123/// ```124/// use std::path::{Component, Path, Prefix};125/// use std::path::Prefix::*;126/// use std::ffi::OsStr;127///128/// fn get_path_prefix(s: &str) -> Prefix<'_> {129///     let path = Path::new(s);130///     match path.components().next().unwrap() {131///         Component::Prefix(prefix_component) => prefix_component.kind(),132///         _ => panic!(),133///     }134/// }135///136/// # if cfg!(windows) {137/// assert_eq!(Verbatim(OsStr::new("pictures")),138///            get_path_prefix(r"\\?\pictures\kittens"));139/// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")),140///            get_path_prefix(r"\\?\UNC\server\share"));141/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\"));142/// assert_eq!(DeviceNS(OsStr::new("BrainInterface")),143///            get_path_prefix(r"\\.\BrainInterface"));144/// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")),145///            get_path_prefix(r"\\server\share"));146/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));147/// # }148/// ```149#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]150#[stable(feature = "rust1", since = "1.0.0")]151pub enum Prefix<'a> {152    /// Verbatim prefix, e.g., `\\?\cat_pics`.153    ///154    /// Verbatim prefixes consist of `\\?\` immediately followed by the given155    /// component.156    #[stable(feature = "rust1", since = "1.0.0")]157    Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),158159    /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_,160    /// e.g., `\\?\UNC\server\share`.161    ///162    /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the163    /// server's hostname and a share name.164    #[stable(feature = "rust1", since = "1.0.0")]165    VerbatimUNC(166        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,167        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,168    ),169170    /// Verbatim disk prefix, e.g., `\\?\C:`.171    ///172    /// Verbatim disk prefixes consist of `\\?\` immediately followed by the173    /// drive letter and `:`.174    #[stable(feature = "rust1", since = "1.0.0")]175    VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),176177    /// Device namespace prefix, e.g., `\\.\COM42`.178    ///179    /// Device namespace prefixes consist of `\\.\` (possibly using `/`180    /// instead of `\`), immediately followed by the device name.181    #[stable(feature = "rust1", since = "1.0.0")]182    DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),183184    /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g.185    /// `\\server\share`.186    ///187    /// UNC prefixes consist of the server's hostname and a share name.188    #[stable(feature = "rust1", since = "1.0.0")]189    UNC(190        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,191        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,192    ),193194    /// Prefix `C:` for the given disk drive.195    #[stable(feature = "rust1", since = "1.0.0")]196    Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),197}198199impl<'a> Prefix<'a> {200    #[inline]201    fn len(&self) -> usize {202        use self::Prefix::*;203        fn os_str_len(s: &OsStr) -> usize {204            s.as_encoded_bytes().len()205        }206        match *self {207            Verbatim(x) => 4 + os_str_len(x),208            VerbatimUNC(x, y) => {209                8 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 }210            }211            VerbatimDisk(_) => 6,212            UNC(x, y) => 2 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 },213            DeviceNS(x) => 4 + os_str_len(x),214            Disk(_) => 2,215        }216    }217218    /// Determines if the prefix is verbatim, i.e., begins with `\\?\`.219    ///220    /// # Examples221    ///222    /// ```223    /// use std::path::Prefix::*;224    /// use std::ffi::OsStr;225    ///226    /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim());227    /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());228    /// assert!(VerbatimDisk(b'C').is_verbatim());229    /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim());230    /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());231    /// assert!(!Disk(b'C').is_verbatim());232    /// ```233    #[inline]234    #[must_use]235    #[stable(feature = "rust1", since = "1.0.0")]236    pub fn is_verbatim(&self) -> bool {237        use self::Prefix::*;238        matches!(*self, Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..))239    }240241    #[inline]242    fn is_drive(&self) -> bool {243        matches!(*self, Prefix::Disk(_))244    }245246    #[inline]247    fn has_implicit_root(&self) -> bool {248        !self.is_drive()249    }250}251252////////////////////////////////////////////////////////////////////////////////253// Exposed parsing helpers254////////////////////////////////////////////////////////////////////////////////255256/// Determines whether the character is one of the permitted path257/// separators for the current platform.258///259/// # Examples260///261/// ```262/// use std::path;263///264/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows265/// assert!(!path::is_separator('❤'));266/// ```267#[must_use]268#[stable(feature = "rust1", since = "1.0.0")]269#[rustc_const_unstable(feature = "const_path_separators", issue = "153106")]270pub const fn is_separator(c: char) -> bool {271    c.is_ascii() && is_sep_byte(c as u8)272}273274/// All path separators recognized on the current platform, represented as [`char`]s; for example,275/// this is `&['/'][..]` on Unix and `&['\\', '/'][..]` on Windows. The [primary276/// separator](MAIN_SEPARATOR) is always element 0 of the slice.277#[unstable(feature = "const_path_separators", issue = "153106")]278pub const SEPARATORS: &[char] = crate::sys::path::SEPARATORS;279280/// All path separators recognized on the current platform, represented as [`&str`]s; for example,281/// this is `&["/"][..]` on Unix and `&["\\", "/"][..]` on Windows. The [primary282/// separator](MAIN_SEPARATOR_STR) is always element 0 of the slice.283#[unstable(feature = "const_path_separators", issue = "153106")]284pub const SEPARATORS_STR: &[&str] = crate::sys::path::SEPARATORS_STR;285286/// The primary separator of path components for the current platform, represented as a [`char`];287/// for example, this is `'/'` on Unix and `'\\'` on Windows.288#[stable(feature = "rust1", since = "1.0.0")]289#[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")]290pub const MAIN_SEPARATOR: char = SEPARATORS[0];291292/// The primary separator of path components for the current platform, represented as a [`&str`];293/// for example, this is `"/"` on Unix and `"\\"` on Windows.294#[stable(feature = "main_separator_str", since = "1.68.0")]295pub const MAIN_SEPARATOR_STR: &str = SEPARATORS_STR[0];296297////////////////////////////////////////////////////////////////////////////////298// Misc helpers299////////////////////////////////////////////////////////////////////////////////300301// Iterate through `iter` while it matches `prefix`; return `None` if `prefix`302// is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving303// `iter` after having exhausted `prefix`.304fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>305where306    I: Iterator<Item = Component<'a>> + Clone,307    J: Iterator<Item = Component<'b>>,308{309    loop {310        let mut iter_next = iter.clone();311        match (iter_next.next(), prefix.next()) {312            (Some(ref x), Some(ref y)) if x == y => (),313            (Some(_), Some(_)) => return None,314            (Some(_), None) => return Some(iter),315            (None, None) => return Some(iter),316            (None, Some(_)) => return None,317        }318        iter = iter_next;319    }320}321322////////////////////////////////////////////////////////////////////////////////323// Cross-platform, iterator-independent parsing324////////////////////////////////////////////////////////////////////////////////325326/// Says whether the first byte after the prefix is a separator.327fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {328    let path = if let Some(p) = prefix { &s[p.len()..] } else { s };329    !path.is_empty() && is_sep_byte(path[0])330}331332// basic workhorse for splitting stem and extension333fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {334    if file.as_encoded_bytes() == b".." {335        return (Some(file), None);336    }337338    // The unsafety here stems from converting between &OsStr and &[u8]339    // and back. This is safe to do because (1) we only look at ASCII340    // contents of the encoding and (2) new &OsStr values are produced341    // only from ASCII-bounded slices of existing &OsStr values.342    let mut iter = file.as_encoded_bytes().rsplitn(2, |b| *b == b'.');343    let after = iter.next();344    let before = iter.next();345    if before == Some(b"") {346        (Some(file), None)347    } else {348        unsafe {349            (350                before.map(|s| OsStr::from_encoded_bytes_unchecked(s)),351                after.map(|s| OsStr::from_encoded_bytes_unchecked(s)),352            )353        }354    }355}356357fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {358    let slice = file.as_encoded_bytes();359    if slice == b".." {360        return (file, None);361    }362363    // The unsafety here stems from converting between &OsStr and &[u8]364    // and back. This is safe to do because (1) we only look at ASCII365    // contents of the encoding and (2) new &OsStr values are produced366    // only from ASCII-bounded slices of existing &OsStr values.367    let i = match slice[1..].iter().position(|b| *b == b'.') {368        Some(i) => i + 1,369        None => return (file, None),370    };371    let before = &slice[..i];372    let after = &slice[i + 1..];373    unsafe {374        (375            OsStr::from_encoded_bytes_unchecked(before),376            Some(OsStr::from_encoded_bytes_unchecked(after)),377        )378    }379}380381/// Checks whether the string is valid as a file extension, or panics otherwise.382fn validate_extension(extension: &OsStr) {383    for &b in extension.as_encoded_bytes() {384        if is_sep_byte(b) {385            panic!("extension cannot contain path separators: {extension:?}");386        }387    }388}389390////////////////////////////////////////////////////////////////////////////////391// The core iterators392////////////////////////////////////////////////////////////////////////////////393394/// Component parsing works by a double-ended state machine; the cursors at the395/// front and back of the path each keep track of what parts of the path have396/// been consumed so far.397///398/// Going front to back, a path is made up of a prefix, a starting399/// directory component, and a body (of normal components)400#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]401enum State {402    Prefix = 0,   // c:403    StartDir = 1, // / or . or nothing404    Body = 2,     // foo/bar/baz405    Done = 3,406}407408/// A structure wrapping a Windows path prefix as well as its unparsed string409/// representation.410///411/// In addition to the parsed [`Prefix`] information returned by [`kind`],412/// `PrefixComponent` also holds the raw and unparsed [`OsStr`] slice,413/// returned by [`as_os_str`].414///415/// Instances of this `struct` can be obtained by matching against the416/// [`Prefix` variant] on [`Component`].417///418/// Does not occur on Unix.419///420/// # Examples421///422/// ```423/// # if cfg!(windows) {424/// use std::path::{Component, Path, Prefix};425/// use std::ffi::OsStr;426///427/// let path = Path::new(r"c:\you\later\");428/// match path.components().next().unwrap() {429///     Component::Prefix(prefix_component) => {430///         assert_eq!(Prefix::Disk(b'C'), prefix_component.kind());431///         assert_eq!(OsStr::new("c:"), prefix_component.as_os_str());432///     }433///     _ => unreachable!(),434/// }435/// # }436/// ```437///438/// [`as_os_str`]: PrefixComponent::as_os_str439/// [`kind`]: PrefixComponent::kind440/// [`Prefix` variant]: Component::Prefix441#[stable(feature = "rust1", since = "1.0.0")]442#[derive(Copy, Clone, Eq, Debug)]443pub struct PrefixComponent<'a> {444    /// The prefix as an unparsed `OsStr` slice.445    raw: &'a OsStr,446447    /// The parsed prefix data.448    parsed: Prefix<'a>,449}450451impl<'a> PrefixComponent<'a> {452    /// Returns the parsed prefix data.453    ///454    /// See [`Prefix`]'s documentation for more information on the different455    /// kinds of prefixes.456    #[stable(feature = "rust1", since = "1.0.0")]457    #[must_use]458    #[inline]459    pub fn kind(&self) -> Prefix<'a> {460        self.parsed461    }462463    /// Returns the raw [`OsStr`] slice for this prefix.464    #[stable(feature = "rust1", since = "1.0.0")]465    #[must_use]466    #[inline]467    pub fn as_os_str(&self) -> &'a OsStr {468        self.raw469    }470}471472#[stable(feature = "rust1", since = "1.0.0")]473impl<'a> PartialEq for PrefixComponent<'a> {474    #[inline]475    fn eq(&self, other: &PrefixComponent<'a>) -> bool {476        self.parsed == other.parsed477    }478}479480#[stable(feature = "rust1", since = "1.0.0")]481impl<'a> PartialOrd for PrefixComponent<'a> {482    #[inline]483    fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> {484        PartialOrd::partial_cmp(&self.parsed, &other.parsed)485    }486}487488#[stable(feature = "rust1", since = "1.0.0")]489impl Ord for PrefixComponent<'_> {490    #[inline]491    fn cmp(&self, other: &Self) -> cmp::Ordering {492        Ord::cmp(&self.parsed, &other.parsed)493    }494}495496#[stable(feature = "rust1", since = "1.0.0")]497impl Hash for PrefixComponent<'_> {498    fn hash<H: Hasher>(&self, h: &mut H) {499        self.parsed.hash(h);500    }501}502503/// A single component of a path.504///505/// A `Component` roughly corresponds to a substring between path separators506/// (`/` or `\`).507///508/// This `enum` is created by iterating over [`Components`], which in turn is509/// created by the [`components`](Path::components) method on [`Path`].510///511/// # Examples512///513/// ```rust514/// use std::path::{Component, Path};515///516/// let path = Path::new("/tmp/foo/bar.txt");517/// let components = path.components().collect::<Vec<_>>();518/// assert_eq!(&components, &[519///     Component::RootDir,520///     Component::Normal("tmp".as_ref()),521///     Component::Normal("foo".as_ref()),522///     Component::Normal("bar.txt".as_ref()),523/// ]);524/// ```525#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]526#[stable(feature = "rust1", since = "1.0.0")]527pub enum Component<'a> {528    /// A Windows path prefix, e.g., `C:` or `\\server\share`.529    ///530    /// There is a large variety of prefix types, see [`Prefix`]'s documentation531    /// for more.532    ///533    /// Does not occur on Unix.534    #[stable(feature = "rust1", since = "1.0.0")]535    Prefix(#[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>),536537    /// The root directory component, appears after any prefix and before anything else.538    ///539    /// It represents a separator that designates that a path starts from root.540    #[stable(feature = "rust1", since = "1.0.0")]541    RootDir,542543    /// A reference to the current directory, i.e., `.`.544    #[stable(feature = "rust1", since = "1.0.0")]545    CurDir,546547    /// A reference to the parent directory, i.e., `..`.548    #[stable(feature = "rust1", since = "1.0.0")]549    ParentDir,550551    /// A normal component, e.g., `a` and `b` in `a/b`.552    ///553    /// This variant is the most common one, it represents references to files554    /// or directories.555    #[stable(feature = "rust1", since = "1.0.0")]556    Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),557}558559impl<'a> Component<'a> {560    /// Extracts the underlying [`OsStr`] slice.561    ///562    /// # Examples563    ///564    /// ```565    /// use std::path::Path;566    ///567    /// let path = Path::new("./tmp/foo/bar.txt");568    /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();569    /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);570    /// ```571    #[must_use = "`self` will be dropped if the result is not used"]572    #[stable(feature = "rust1", since = "1.0.0")]573    pub fn as_os_str(self) -> &'a OsStr {574        match self {575            Component::Prefix(p) => p.as_os_str(),576            Component::RootDir => OsStr::new(MAIN_SEPARATOR_STR),577            Component::CurDir => OsStr::new("."),578            Component::ParentDir => OsStr::new(".."),579            Component::Normal(path) => path,580        }581    }582}583584#[stable(feature = "rust1", since = "1.0.0")]585impl AsRef<OsStr> for Component<'_> {586    #[inline]587    fn as_ref(&self) -> &OsStr {588        self.as_os_str()589    }590}591592#[stable(feature = "path_component_asref", since = "1.25.0")]593impl AsRef<Path> for Component<'_> {594    #[inline]595    fn as_ref(&self) -> &Path {596        self.as_os_str().as_ref()597    }598}599600/// An iterator over the [`Component`]s of a [`Path`].601///602/// This `struct` is created by the [`components`] method on [`Path`].603/// See its documentation for more.604///605/// # Examples606///607/// ```608/// use std::path::Path;609///610/// let path = Path::new("/tmp/foo/bar.txt");611///612/// for component in path.components() {613///     println!("{component:?}");614/// }615/// ```616///617/// [`components`]: Path::components618#[derive(Clone)]619#[must_use = "iterators are lazy and do nothing unless consumed"]620#[stable(feature = "rust1", since = "1.0.0")]621pub struct Components<'a> {622    // The path left to parse components from623    path: &'a [u8],624625    // The prefix as it was originally parsed, if any626    prefix: Option<Prefix<'a>>,627628    // true if path *physically* has a root separator; for most Windows629    // prefixes, it may have a "logical" root separator for the purposes of630    // normalization, e.g., \\server\share == \\server\share\.631    has_physical_root: bool,632633    // The iterator is double-ended, and these two states keep track of what has634    // been produced from either end635    front: State,636    back: State,637}638639/// An iterator over the [`Component`]s of a [`Path`], as [`OsStr`] slices.640///641/// This `struct` is created by the [`iter`] method on [`Path`].642/// See its documentation for more.643///644/// [`iter`]: Path::iter645#[derive(Clone)]646#[must_use = "iterators are lazy and do nothing unless consumed"]647#[stable(feature = "rust1", since = "1.0.0")]648pub struct Iter<'a> {649    inner: Components<'a>,650}651652#[stable(feature = "path_components_debug", since = "1.13.0")]653impl fmt::Debug for Components<'_> {654    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {655        struct DebugHelper<'a>(&'a Path);656657        impl fmt::Debug for DebugHelper<'_> {658            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {659                f.debug_list().entries(self.0.components()).finish()660            }661        }662663        f.debug_tuple("Components").field(&DebugHelper(self.as_path())).finish()664    }665}666667impl<'a> Components<'a> {668    // how long is the prefix, if any?669    #[inline]670    fn prefix_len(&self) -> usize {671        if !HAS_PREFIXES {672            return 0;673        }674        self.prefix.as_ref().map(Prefix::len).unwrap_or(0)675    }676677    #[inline]678    fn prefix_verbatim(&self) -> bool {679        if !HAS_PREFIXES {680            return false;681        }682        self.prefix.as_ref().map(Prefix::is_verbatim).unwrap_or(false)683    }684685    /// how much of the prefix is left from the point of view of iteration?686    #[inline]687    fn prefix_remaining(&self) -> usize {688        if !HAS_PREFIXES {689            return 0;690        }691        if self.front == State::Prefix { self.prefix_len() } else { 0 }692    }693694    // Given the iteration so far, how much of the pre-State::Body path is left?695    #[inline]696    fn len_before_body(&self) -> usize {697        let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 };698        let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 };699        self.prefix_remaining() + root + cur_dir700    }701702    // is the iteration complete?703    #[inline]704    fn finished(&self) -> bool {705        self.front == State::Done || self.back == State::Done || self.front > self.back706    }707708    #[inline]709    fn is_sep_byte(&self, b: u8) -> bool {710        if self.prefix_verbatim() { is_verbatim_sep(b) } else { is_sep_byte(b) }711    }712713    /// Extracts a slice corresponding to the portion of the path remaining for iteration.714    ///715    /// # Examples716    ///717    /// ```718    /// use std::path::Path;719    ///720    /// let mut components = Path::new("/tmp/foo/bar.txt").components();721    /// components.next();722    /// components.next();723    ///724    /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());725    /// ```726    #[must_use]727    #[stable(feature = "rust1", since = "1.0.0")]728    pub fn as_path(&self) -> &'a Path {729        let mut comps = self.clone();730        if comps.front == State::Body {731            comps.trim_left();732        }733        if comps.back == State::Body {734            comps.trim_right();735        }736        unsafe { Path::from_u8_slice(comps.path) }737    }738739    /// Is the *original* path rooted?740    fn has_root(&self) -> bool {741        if self.has_physical_root {742            return true;743        }744        if HAS_PREFIXES && let Some(p) = self.prefix {745            if p.has_implicit_root() {746                return true;747            }748        }749        false750    }751752    /// Should the normalized path include a leading . ?753    fn include_cur_dir(&self) -> bool {754        if self.has_root() {755            return false;756        }757        let slice = &self.path[self.prefix_remaining()..];758        match slice {759            [b'.'] => true,760            [b'.', b, ..] => self.is_sep_byte(*b),761            _ => false,762        }763    }764765    // parse a given byte sequence following the OsStr encoding into the766    // corresponding path component767    unsafe fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {768        match comp {769            b"." if HAS_PREFIXES && self.prefix_verbatim() => Some(Component::CurDir),770            b"." => None, // . components are normalized away, except at771            // the beginning of a path, which is treated772            // separately via `include_cur_dir`773            b".." => Some(Component::ParentDir),774            b"" => None,775            _ => Some(Component::Normal(unsafe { OsStr::from_encoded_bytes_unchecked(comp) })),776        }777    }778779    // parse a component from the left, saying how many bytes to consume to780    // remove the component781    fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {782        debug_assert!(self.front == State::Body);783        let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) {784            None => (0, self.path),785            Some(i) => (1, &self.path[..i]),786        };787        // SAFETY: `comp` is a valid substring, since it is split on a separator.788        (comp.len() + extra, unsafe { self.parse_single_component(comp) })789    }790791    // parse a component from the right, saying how many bytes to consume to792    // remove the component793    fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {794        debug_assert!(self.back == State::Body);795        let start = self.len_before_body();796        let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) {797            None => (0, &self.path[start..]),798            Some(i) => (1, &self.path[start + i + 1..]),799        };800        // SAFETY: `comp` is a valid substring, since it is split on a separator.801        (comp.len() + extra, unsafe { self.parse_single_component(comp) })802    }803804    // trim away repeated separators (i.e., empty components) on the left805    fn trim_left(&mut self) {806        while !self.path.is_empty() {807            let (size, comp) = self.parse_next_component();808            if comp.is_some() {809                return;810            } else {811                self.path = &self.path[size..];812            }813        }814    }815816    // trim away repeated separators (i.e., empty components) on the right817    fn trim_right(&mut self) {818        while self.path.len() > self.len_before_body() {819            let (size, comp) = self.parse_next_component_back();820            if comp.is_some() {821                return;822            } else {823                self.path = &self.path[..self.path.len() - size];824            }825        }826    }827}828829#[stable(feature = "rust1", since = "1.0.0")]830impl AsRef<Path> for Components<'_> {831    #[inline]832    fn as_ref(&self) -> &Path {833        self.as_path()834    }835}836837#[stable(feature = "rust1", since = "1.0.0")]838impl AsRef<OsStr> for Components<'_> {839    #[inline]840    fn as_ref(&self) -> &OsStr {841        self.as_path().as_os_str()842    }843}844845#[stable(feature = "path_iter_debug", since = "1.13.0")]846impl fmt::Debug for Iter<'_> {847    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {848        struct DebugHelper<'a>(&'a Path);849850        impl fmt::Debug for DebugHelper<'_> {851            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {852                f.debug_list().entries(self.0.iter()).finish()853            }854        }855856        f.debug_tuple("Iter").field(&DebugHelper(self.as_path())).finish()857    }858}859860impl<'a> Iter<'a> {861    /// Extracts a slice corresponding to the portion of the path remaining for iteration.862    ///863    /// # Examples864    ///865    /// ```866    /// use std::path::Path;867    ///868    /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();869    /// iter.next();870    /// iter.next();871    ///872    /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());873    /// ```874    #[stable(feature = "rust1", since = "1.0.0")]875    #[must_use]876    #[inline]877    pub fn as_path(&self) -> &'a Path {878        self.inner.as_path()879    }880}881882#[stable(feature = "rust1", since = "1.0.0")]883impl AsRef<Path> for Iter<'_> {884    #[inline]885    fn as_ref(&self) -> &Path {886        self.as_path()887    }888}889890#[stable(feature = "rust1", since = "1.0.0")]891impl AsRef<OsStr> for Iter<'_> {892    #[inline]893    fn as_ref(&self) -> &OsStr {894        self.as_path().as_os_str()895    }896}897898#[stable(feature = "rust1", since = "1.0.0")]899impl<'a> Iterator for Iter<'a> {900    type Item = &'a OsStr;901902    #[inline]903    fn next(&mut self) -> Option<&'a OsStr> {904        self.inner.next().map(Component::as_os_str)905    }906}907908#[stable(feature = "rust1", since = "1.0.0")]909impl<'a> DoubleEndedIterator for Iter<'a> {910    #[inline]911    fn next_back(&mut self) -> Option<&'a OsStr> {912        self.inner.next_back().map(Component::as_os_str)913    }914}915916#[stable(feature = "fused", since = "1.26.0")]917impl FusedIterator for Iter<'_> {}918919#[stable(feature = "rust1", since = "1.0.0")]920impl<'a> Iterator for Components<'a> {921    type Item = Component<'a>;922923    fn next(&mut self) -> Option<Component<'a>> {924        while !self.finished() {925            match self.front {926                // most likely case first927                State::Body if !self.path.is_empty() => {928                    let (size, comp) = self.parse_next_component();929                    self.path = &self.path[size..];930                    if comp.is_some() {931                        return comp;932                    }933                }934                State::Body => {935                    self.front = State::Done;936                }937                State::StartDir => {938                    self.front = State::Body;939                    if self.has_physical_root {940                        debug_assert!(!self.path.is_empty());941                        self.path = &self.path[1..];942                        return Some(Component::RootDir);943                    } else if HAS_PREFIXES && let Some(p) = self.prefix {944                        if p.has_implicit_root() && !p.is_verbatim() {945                            return Some(Component::RootDir);946                        }947                    } else if self.include_cur_dir() {948                        debug_assert!(!self.path.is_empty());949                        self.path = &self.path[1..];950                        return Some(Component::CurDir);951                    }952                }953                _ if const { !HAS_PREFIXES } => unreachable!(),954                State::Prefix if self.prefix_len() == 0 => {955                    self.front = State::StartDir;956                }957                State::Prefix => {958                    self.front = State::StartDir;959                    debug_assert!(self.prefix_len() <= self.path.len());960                    let raw = &self.path[..self.prefix_len()];961                    self.path = &self.path[self.prefix_len()..];962                    return Some(Component::Prefix(PrefixComponent {963                        raw: unsafe { OsStr::from_encoded_bytes_unchecked(raw) },964                        parsed: self.prefix.unwrap(),965                    }));966                }967                State::Done => unreachable!(),968            }969        }970        None971    }972}973974#[stable(feature = "rust1", since = "1.0.0")]975impl<'a> DoubleEndedIterator for Components<'a> {976    fn next_back(&mut self) -> Option<Component<'a>> {977        while !self.finished() {978            match self.back {979                State::Body if self.path.len() > self.len_before_body() => {980                    let (size, comp) = self.parse_next_component_back();981                    self.path = &self.path[..self.path.len() - size];982                    if comp.is_some() {983                        return comp;984                    }985                }986                State::Body => {987                    self.back = State::StartDir;988                }989                State::StartDir => {990                    self.back = if HAS_PREFIXES { State::Prefix } else { State::Done };991                    if self.has_physical_root {992                        self.path = &self.path[..self.path.len() - 1];993                        return Some(Component::RootDir);994                    } else if HAS_PREFIXES && let Some(p) = self.prefix {995                        if p.has_implicit_root() && !p.is_verbatim() {996                            return Some(Component::RootDir);997                        }998                    } else if self.include_cur_dir() {999                        self.path = &self.path[..self.path.len() - 1];1000                        return Some(Component::CurDir);1001                    }1002                }1003                _ if !HAS_PREFIXES => unreachable!(),1004                State::Prefix if self.prefix_len() > 0 => {1005                    self.back = State::Done;1006                    return Some(Component::Prefix(PrefixComponent {1007                        raw: unsafe { OsStr::from_encoded_bytes_unchecked(self.path) },1008                        parsed: self.prefix.unwrap(),1009                    }));1010                }1011                State::Prefix => {1012                    self.back = State::Done;1013                    return None;1014                }1015                State::Done => unreachable!(),1016            }1017        }1018        None1019    }1020}10211022#[stable(feature = "fused", since = "1.26.0")]1023impl FusedIterator for Components<'_> {}10241025#[stable(feature = "rust1", since = "1.0.0")]1026impl<'a> PartialEq for Components<'a> {1027    #[inline]1028    fn eq(&self, other: &Components<'a>) -> bool {1029        let Components { path: _, front: _, back: _, has_physical_root: _, prefix: _ } = self;10301031        // Fast path for exact matches, e.g. for hashmap lookups.1032        // Don't explicitly compare the prefix or has_physical_root fields since they'll1033        // either be covered by the `path` buffer or are only relevant for `prefix_verbatim()`.1034        if self.path.len() == other.path.len()1035            && self.front == other.front1036            && self.back == State::Body1037            && other.back == State::Body1038            && self.prefix_verbatim() == other.prefix_verbatim()1039        {1040            // possible future improvement: this could bail out earlier if there were a1041            // reverse memcmp/bcmp comparing back to front1042            if self.path == other.path {1043                return true;1044            }1045        }10461047        // compare back to front since absolute paths often share long prefixes1048        Iterator::eq(self.clone().rev(), other.clone().rev())1049    }1050}10511052#[stable(feature = "rust1", since = "1.0.0")]1053impl Eq for Components<'_> {}10541055#[stable(feature = "rust1", since = "1.0.0")]1056impl<'a> PartialOrd for Components<'a> {1057    #[inline]1058    fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {1059        Some(compare_components(self.clone(), other.clone()))1060    }1061}10621063#[stable(feature = "rust1", since = "1.0.0")]1064impl Ord for Components<'_> {1065    #[inline]1066    fn cmp(&self, other: &Self) -> cmp::Ordering {1067        compare_components(self.clone(), other.clone())1068    }1069}10701071fn compare_components(mut left: Components<'_>, mut right: Components<'_>) -> cmp::Ordering {1072    // Fast path for long shared prefixes1073    //1074    // - compare raw bytes to find first mismatch1075    // - backtrack to find separator before mismatch to avoid ambiguous parsings of '.' or '..' characters1076    // - if found update state to only do a component-wise comparison on the remainder,1077    //   otherwise do it on the full path1078    //1079    // The fast path isn't taken for paths with a PrefixComponent to avoid backtracking into1080    // the middle of one1081    if left.prefix.is_none() && right.prefix.is_none() && left.front == right.front {1082        // possible future improvement: a [u8]::first_mismatch simd implementation1083        let first_difference = match left.path.iter().zip(right.path).position(|(&a, &b)| a != b) {1084            None if left.path.len() == right.path.len() => return cmp::Ordering::Equal,1085            None => left.path.len().min(right.path.len()),1086            Some(diff) => diff,1087        };10881089        if let Some(previous_sep) =1090            left.path[..first_difference].iter().rposition(|&b| left.is_sep_byte(b))1091        {1092            let mismatched_component_start = previous_sep + 1;1093            left.path = &left.path[mismatched_component_start..];1094            left.front = State::Body;1095            right.path = &right.path[mismatched_component_start..];1096            right.front = State::Body;1097        }1098    }10991100    Iterator::cmp(left, right)1101}11021103/// An iterator over [`Path`] and its ancestors.1104///1105/// This `struct` is created by the [`ancestors`] method on [`Path`].1106/// See its documentation for more.1107///1108/// # Examples1109///1110/// ```1111/// use std::path::Path;1112///1113/// let path = Path::new("/foo/bar");1114///1115/// for ancestor in path.ancestors() {1116///     println!("{}", ancestor.display());1117/// }1118/// ```1119///1120/// [`ancestors`]: Path::ancestors1121#[derive(Copy, Clone, Debug)]1122#[must_use = "iterators are lazy and do nothing unless consumed"]1123#[stable(feature = "path_ancestors", since = "1.28.0")]1124pub struct Ancestors<'a> {1125    next: Option<&'a Path>,1126}11271128#[stable(feature = "path_ancestors", since = "1.28.0")]1129impl<'a> Iterator for Ancestors<'a> {1130    type Item = &'a Path;11311132    #[inline]1133    fn next(&mut self) -> Option<Self::Item> {1134        let next = self.next;1135        self.next = next.and_then(Path::parent);1136        next1137    }1138}11391140#[stable(feature = "path_ancestors", since = "1.28.0")]1141impl FusedIterator for Ancestors<'_> {}11421143////////////////////////////////////////////////////////////////////////////////1144// Basic types and traits1145////////////////////////////////////////////////////////////////////////////////11461147/// An owned, mutable path (akin to [`String`]).1148///1149/// This type provides methods like [`push`] and [`set_extension`] that mutate1150/// the path in place. It also implements [`Deref`] to [`Path`], meaning that1151/// all methods on [`Path`] slices are available on `PathBuf` values as well.1152///1153/// [`push`]: PathBuf::push1154/// [`set_extension`]: PathBuf::set_extension1155///1156/// More details about the overall approach can be found in1157/// the [module documentation](self).1158///1159/// # Examples1160///1161/// You can use [`push`] to build up a `PathBuf` from1162/// components:1163///1164/// ```1165/// use std::path::PathBuf;1166///1167/// let mut path = PathBuf::new();1168///1169/// path.push(r"C:\");1170/// path.push("windows");1171/// path.push("system32");1172///1173/// path.set_extension("dll");1174/// ```1175///1176/// However, [`push`] is best used for dynamic situations. This is a better way1177/// to do this when you know all of the components ahead of time:1178///1179/// ```1180/// use std::path::PathBuf;1181///1182/// let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();1183/// ```1184///1185/// We can still do better than this! Since these are all strings, we can use1186/// `From::from`:1187///1188/// ```1189/// use std::path::PathBuf;1190///1191/// let path = PathBuf::from(r"C:\windows\system32.dll");1192/// ```1193///1194/// Which method works best depends on what kind of situation you're in.1195///1196/// Note that `PathBuf` does not always sanitize arguments, for example1197/// [`push`] allows paths built from strings which include separators:1198///1199/// ```1200/// use std::path::PathBuf;1201///1202/// let mut path = PathBuf::new();1203///1204/// path.push(r"C:\");1205/// path.push("windows");1206/// path.push(r"..\otherdir");1207/// path.push("system32");1208/// ```1209///1210/// The behavior of `PathBuf` may be changed to a panic on such inputs1211/// in the future. [`Extend::extend`] should be used to add multi-part paths.1212#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]1213#[stable(feature = "rust1", since = "1.0.0")]1214pub struct PathBuf {1215    inner: OsString,1216}12171218impl PathBuf {1219    /// Allocates an empty `PathBuf`.1220    ///1221    /// # Examples1222    ///1223    /// ```1224    /// use std::path::PathBuf;1225    ///1226    /// let path = PathBuf::new();1227    /// ```1228    #[stable(feature = "rust1", since = "1.0.0")]1229    #[must_use]1230    #[inline]1231    #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")]1232    pub const fn new() -> PathBuf {1233        PathBuf { inner: OsString::new() }1234    }12351236    /// Creates a new `PathBuf` with a given capacity used to create the1237    /// internal [`OsString`]. See [`with_capacity`] defined on [`OsString`].1238    ///1239    /// # Examples1240    ///1241    /// ```1242    /// use std::path::PathBuf;1243    ///1244    /// let mut path = PathBuf::with_capacity(10);1245    /// let capacity = path.capacity();1246    ///1247    /// // This push is done without reallocating1248    /// path.push(r"C:\");1249    ///1250    /// assert_eq!(capacity, path.capacity());1251    /// ```1252    ///1253    /// [`with_capacity`]: OsString::with_capacity1254    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1255    #[must_use]1256    #[inline]1257    pub fn with_capacity(capacity: usize) -> PathBuf {1258        PathBuf { inner: OsString::with_capacity(capacity) }1259    }12601261    /// Coerces to a [`Path`] slice.1262    ///1263    /// # Examples1264    ///1265    /// ```1266    /// use std::path::{Path, PathBuf};1267    ///1268    /// let p = PathBuf::from("/test");1269    /// assert_eq!(Path::new("/test"), p.as_path());1270    /// ```1271    #[cfg_attr(not(test), rustc_diagnostic_item = "pathbuf_as_path")]1272    #[stable(feature = "rust1", since = "1.0.0")]1273    #[must_use]1274    #[inline]1275    pub fn as_path(&self) -> &Path {1276        self1277    }12781279    /// Consumes and leaks the `PathBuf`, returning a mutable reference to the contents,1280    /// `&'a mut Path`.1281    ///1282    /// The caller has free choice over the returned lifetime, including 'static.1283    /// Indeed, this function is ideally used for data that lives for the remainder of1284    /// the program's life, as dropping the returned reference will cause a memory leak.1285    ///1286    /// It does not reallocate or shrink the `PathBuf`, so the leaked allocation may include1287    /// unused capacity that is not part of the returned slice. If you want to discard excess1288    /// capacity, call [`into_boxed_path`], and then [`Box::leak`] instead.1289    /// However, keep in mind that trimming the capacity may result in a reallocation and copy.1290    ///1291    /// [`into_boxed_path`]: Self::into_boxed_path1292    #[stable(feature = "os_string_pathbuf_leak", since = "1.89.0")]1293    #[inline]1294    pub fn leak<'a>(self) -> &'a mut Path {1295        Path::from_inner_mut(self.inner.leak())1296    }12971298    /// Extends `self` with `path`.1299    ///1300    /// If `path` is absolute, it replaces the current path.1301    ///1302    /// On Windows:1303    ///1304    /// * if `path` has a root but no prefix (e.g., `\windows`), it1305    ///   replaces everything except for the prefix (if any) of `self`.1306    /// * if `path` has a prefix but no root, it replaces `self`.1307    /// * if `self` has a verbatim prefix (e.g. `\\?\C:\windows`)1308    ///   and `path` is not empty, the new path is normalized: all references1309    ///   to `.` and `..` are removed.1310    ///1311    /// Consider using [`Path::join`] if you need a new `PathBuf` instead of1312    /// using this function on a cloned `PathBuf`.1313    ///1314    /// # Examples1315    ///1316    /// Pushing a relative path extends the existing path:1317    ///1318    /// ```1319    /// use std::path::PathBuf;1320    ///1321    /// let mut path = PathBuf::from("/tmp");1322    /// path.push("file.bk");1323    /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));1324    /// ```1325    ///1326    /// Pushing an absolute path replaces the existing path:1327    ///1328    /// ```1329    /// use std::path::PathBuf;1330    ///1331    /// let mut path = PathBuf::from("/tmp");1332    /// path.push("/etc");1333    /// assert_eq!(path, PathBuf::from("/etc"));1334    /// ```1335    #[stable(feature = "rust1", since = "1.0.0")]1336    #[rustc_confusables("append", "put")]1337    pub fn push<P: AsRef<Path>>(&mut self, path: P) {1338        self._push(path.as_ref())1339    }13401341    fn _push(&mut self, path: &Path) {1342        // in general, a separator is needed if the rightmost byte is not a separator1343        let buf = self.inner.as_encoded_bytes();1344        let mut need_sep = buf.last().map(|c| !is_sep_byte(*c)).unwrap_or(false);13451346        // in the special case of `C:` on Windows, do *not* add a separator1347        let comps = self.components();13481349        if comps.prefix_len() > 01350            && comps.prefix_len() == comps.path.len()1351            && comps.prefix.unwrap().is_drive()1352        {1353            need_sep = false1354        }13551356        let need_clear = if cfg!(target_os = "cygwin") {1357            // If path is absolute and its prefix is none, it is like `/foo`,1358            // and will be handled below.1359            path.prefix().is_some()1360        } else {1361            // On Unix: prefix is always None.1362            path.is_absolute() || path.prefix().is_some()1363        };13641365        // absolute `path` replaces `self`1366        if need_clear {1367            self.inner.clear();13681369        // verbatim paths need . and .. removed1370        } else if comps.prefix_verbatim() && !path.inner.is_empty() {1371            let mut buf: Vec<_> = comps.collect();1372            for c in path.components() {1373                match c {1374                    Component::RootDir => {1375                        buf.truncate(1);1376                        buf.push(c);1377                    }1378                    Component::CurDir => (),1379                    Component::ParentDir => {1380                        if let Some(Component::Normal(_)) = buf.last() {1381                            buf.pop();1382                        }1383                    }1384                    _ => buf.push(c),1385                }1386            }13871388            let mut res = OsString::new();1389            let mut need_sep = false;13901391            for c in buf {1392                if need_sep && c != Component::RootDir {1393                    res.push(MAIN_SEPARATOR_STR);1394                }1395                res.push(c.as_os_str());13961397                need_sep = match c {1398                    Component::RootDir => false,1399                    Component::Prefix(prefix) => {1400                        !prefix.parsed.is_drive() && prefix.parsed.len() > 01401                    }1402                    _ => true,1403                }1404            }14051406            self.inner = res;1407            return;14081409        // `path` has a root but no prefix, e.g., `\windows` (Windows only)1410        } else if path.has_root() {1411            let prefix_len = self.components().prefix_remaining();1412            self.inner.truncate(prefix_len);14131414        // `path` is a pure relative path1415        } else if need_sep {1416            self.inner.push(MAIN_SEPARATOR_STR);1417        }14181419        self.inner.push(path);1420    }14211422    /// Truncates `self` to [`self.parent`].1423    ///1424    /// Returns `false` and does nothing if [`self.parent`] is [`None`].1425    /// Otherwise, returns `true`.1426    ///1427    /// [`self.parent`]: Path::parent1428    ///1429    /// # Examples1430    ///1431    /// ```1432    /// use std::path::{Path, PathBuf};1433    ///1434    /// let mut p = PathBuf::from("/spirited/away.rs");1435    ///1436    /// p.pop();1437    /// assert_eq!(Path::new("/spirited"), p);1438    /// p.pop();1439    /// assert_eq!(Path::new("/"), p);1440    /// ```1441    #[stable(feature = "rust1", since = "1.0.0")]1442    pub fn pop(&mut self) -> bool {1443        match self.parent().map(|p| p.as_u8_slice().len()) {1444            Some(len) => {1445                self.inner.truncate(len);1446                true1447            }1448            None => false,1449        }1450    }14511452    /// Sets whether the path has a trailing [separator](MAIN_SEPARATOR).1453    ///1454    /// The value returned by [`has_trailing_sep`](Path::has_trailing_sep) will be equivalent to1455    /// the provided value if possible.1456    ///1457    /// # Examples1458    ///1459    /// ```1460    /// #![feature(path_trailing_sep)]1461    /// use std::path::PathBuf;1462    ///1463    /// let mut p = PathBuf::from("dir");1464    ///1465    /// assert!(!p.has_trailing_sep());1466    /// p.set_trailing_sep(false);1467    /// assert!(!p.has_trailing_sep());1468    /// p.set_trailing_sep(true);1469    /// assert!(p.has_trailing_sep());1470    /// p.set_trailing_sep(false);1471    /// assert!(!p.has_trailing_sep());1472    ///1473    /// p = PathBuf::from("/");1474    /// assert!(p.has_trailing_sep());1475    /// p.set_trailing_sep(false);1476    /// assert!(p.has_trailing_sep());1477    /// ```1478    #[unstable(feature = "path_trailing_sep", issue = "142503")]1479    pub fn set_trailing_sep(&mut self, trailing_sep: bool) {1480        if trailing_sep { self.push_trailing_sep() } else { self.pop_trailing_sep() }1481    }14821483    /// Adds a trailing [separator](MAIN_SEPARATOR) to the path.1484    ///1485    /// This acts similarly to [`Path::with_trailing_sep`], but mutates the underlying `PathBuf`.1486    ///1487    /// # Examples1488    ///1489    /// ```1490    /// #![feature(path_trailing_sep)]1491    /// use std::ffi::OsStr;1492    /// use std::path::PathBuf;1493    ///1494    /// let mut p = PathBuf::from("dir");1495    ///1496    /// assert!(!p.has_trailing_sep());1497    /// p.push_trailing_sep();1498    /// assert!(p.has_trailing_sep());1499    /// p.push_trailing_sep();1500    /// assert!(p.has_trailing_sep());1501    ///1502    /// p = PathBuf::from("dir/");1503    /// p.push_trailing_sep();1504    /// assert_eq!(p.as_os_str(), OsStr::new("dir/"));1505    /// ```1506    #[unstable(feature = "path_trailing_sep", issue = "142503")]1507    pub fn push_trailing_sep(&mut self) {1508        if !self.has_trailing_sep() {1509            self.push("");1510        }1511    }15121513    /// Removes a trailing [separator](MAIN_SEPARATOR) from the path, if possible.1514    ///1515    /// This acts similarly to [`Path::trim_trailing_sep`], but mutates the underlying `PathBuf`.1516    ///1517    /// # Examples1518    ///1519    /// ```1520    /// #![feature(path_trailing_sep)]1521    /// use std::ffi::OsStr;1522    /// use std::path::PathBuf;1523    ///1524    /// let mut p = PathBuf::from("dir//");1525    ///1526    /// assert!(p.has_trailing_sep());1527    /// assert_eq!(p.as_os_str(), OsStr::new("dir//"));1528    /// p.pop_trailing_sep();1529    /// assert!(!p.has_trailing_sep());1530    /// assert_eq!(p.as_os_str(), OsStr::new("dir"));1531    /// p.pop_trailing_sep();1532    /// assert!(!p.has_trailing_sep());1533    /// assert_eq!(p.as_os_str(), OsStr::new("dir"));1534    ///1535    /// p = PathBuf::from("/");1536    /// assert!(p.has_trailing_sep());1537    /// p.pop_trailing_sep();1538    /// assert!(p.has_trailing_sep());1539    /// ```1540    #[unstable(feature = "path_trailing_sep", issue = "142503")]1541    pub fn pop_trailing_sep(&mut self) {1542        self.inner.truncate(self.trim_trailing_sep().as_os_str().len());1543    }15441545    /// Updates [`self.file_name`] to `file_name`.1546    ///1547    /// If [`self.file_name`] was [`None`], this is equivalent to pushing1548    /// `file_name`.1549    ///1550    /// Otherwise it is equivalent to calling [`pop`] and then pushing1551    /// `file_name`. The new path will be a sibling of the original path.1552    /// (That is, it will have the same parent.)1553    ///1554    /// The argument is not sanitized, so can include separators. This1555    /// behavior may be changed to a panic in the future.1556    ///1557    /// [`self.file_name`]: Path::file_name1558    /// [`pop`]: PathBuf::pop1559    ///1560    /// # Examples1561    ///1562    /// ```1563    /// use std::path::PathBuf;1564    ///1565    /// let mut buf = PathBuf::from("/");1566    /// assert!(buf.file_name() == None);1567    ///1568    /// buf.set_file_name("foo.txt");1569    /// assert!(buf == PathBuf::from("/foo.txt"));1570    /// assert!(buf.file_name().is_some());1571    ///1572    /// buf.set_file_name("bar.txt");1573    /// assert!(buf == PathBuf::from("/bar.txt"));1574    ///1575    /// buf.set_file_name("baz");1576    /// assert!(buf == PathBuf::from("/baz"));1577    ///1578    /// buf.set_file_name("../b/c.txt");1579    /// assert!(buf == PathBuf::from("/../b/c.txt"));1580    ///1581    /// buf.set_file_name("baz");1582    /// assert!(buf == PathBuf::from("/../b/baz"));1583    /// ```1584    #[stable(feature = "rust1", since = "1.0.0")]1585    pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {1586        self._set_file_name(file_name.as_ref())1587    }15881589    fn _set_file_name(&mut self, file_name: &OsStr) {1590        if self.file_name().is_some() {1591            let popped = self.pop();1592            debug_assert!(popped);1593        }1594        self.push(file_name);1595    }15961597    /// Updates [`self.extension`] to `Some(extension)` or to `None` if1598    /// `extension` is empty.1599    ///1600    /// Returns `false` and does nothing if [`self.file_name`] is [`None`],1601    /// returns `true` and updates the extension otherwise.1602    ///1603    /// If [`self.extension`] is [`None`], the extension is added; otherwise1604    /// it is replaced.1605    ///1606    /// If `extension` is the empty string, [`self.extension`] will be [`None`]1607    /// afterwards, not `Some("")`.1608    ///1609    /// # Panics1610    ///1611    /// Panics if the passed extension contains a path separator (see1612    /// [`is_separator`]).1613    ///1614    /// # Caveats1615    ///1616    /// The new `extension` may contain dots and will be used in its entirety,1617    /// but only the part after the final dot will be reflected in1618    /// [`self.extension`].1619    ///1620    /// If the file stem contains internal dots and `extension` is empty, part1621    /// of the old file stem will be considered the new [`self.extension`].1622    ///1623    /// See the examples below.1624    ///1625    /// [`self.file_name`]: Path::file_name1626    /// [`self.extension`]: Path::extension1627    ///1628    /// # Examples1629    ///1630    /// ```1631    /// use std::path::{Path, PathBuf};1632    ///1633    /// let mut p = PathBuf::from("/feel/the");1634    ///1635    /// p.set_extension("force");1636    /// assert_eq!(Path::new("/feel/the.force"), p.as_path());1637    ///1638    /// p.set_extension("dark.side");1639    /// assert_eq!(Path::new("/feel/the.dark.side"), p.as_path());1640    ///1641    /// p.set_extension("cookie");1642    /// assert_eq!(Path::new("/feel/the.dark.cookie"), p.as_path());1643    ///1644    /// p.set_extension("");1645    /// assert_eq!(Path::new("/feel/the.dark"), p.as_path());1646    ///1647    /// p.set_extension("");1648    /// assert_eq!(Path::new("/feel/the"), p.as_path());1649    ///1650    /// p.set_extension("");1651    /// assert_eq!(Path::new("/feel/the"), p.as_path());1652    /// ```1653    #[stable(feature = "rust1", since = "1.0.0")]1654    pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {1655        self._set_extension(extension.as_ref())1656    }16571658    fn _set_extension(&mut self, extension: &OsStr) -> bool {1659        validate_extension(extension);16601661        let file_stem = match self.file_stem() {1662            None => return false,1663            Some(f) => f.as_encoded_bytes(),1664        };16651666        // truncate until right after the file stem1667        let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr();1668        let start = self.inner.as_encoded_bytes().as_ptr().addr();1669        self.inner.truncate(end_file_stem.wrapping_sub(start));16701671        // add the new extension, if any1672        let new = extension.as_encoded_bytes();1673        if !new.is_empty() {1674            self.inner.reserve_exact(new.len() + 1);1675            self.inner.push(".");1676            // SAFETY: Since a UTF-8 string was just pushed, it is not possible1677            // for the buffer to end with a surrogate half.1678            unsafe { self.inner.extend_from_slice_unchecked(new) };1679        }16801681        true1682    }16831684    /// Append [`self.extension`] with `extension`.1685    ///1686    /// Returns `false` and does nothing if [`self.file_name`] is [`None`],1687    /// returns `true` and updates the extension otherwise.1688    ///1689    /// # Panics1690    ///1691    /// Panics if the passed extension contains a path separator (see1692    /// [`is_separator`]).1693    ///1694    /// # Caveats1695    ///1696    /// The appended `extension` may contain dots and will be used in its entirety,1697    /// but only the part after the final dot will be reflected in1698    /// [`self.extension`].1699    ///1700    /// See the examples below.1701    ///1702    /// [`self.file_name`]: Path::file_name1703    /// [`self.extension`]: Path::extension1704    ///1705    /// # Examples1706    ///1707    /// ```1708    /// use std::path::{Path, PathBuf};1709    ///1710    /// let mut p = PathBuf::from("/feel/the");1711    ///1712    /// p.add_extension("formatted");1713    /// assert_eq!(Path::new("/feel/the.formatted"), p.as_path());1714    ///1715    /// p.add_extension("dark.side");1716    /// assert_eq!(Path::new("/feel/the.formatted.dark.side"), p.as_path());1717    ///1718    /// p.set_extension("cookie");1719    /// assert_eq!(Path::new("/feel/the.formatted.dark.cookie"), p.as_path());1720    ///1721    /// p.set_extension("");1722    /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());1723    ///1724    /// p.add_extension("");1725    /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());1726    /// ```1727    #[stable(feature = "path_add_extension", since = "1.91.0")]1728    pub fn add_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {1729        self._add_extension(extension.as_ref())1730    }17311732    fn _add_extension(&mut self, extension: &OsStr) -> bool {1733        validate_extension(extension);17341735        let file_name = match self.file_name() {1736            None => return false,1737            Some(f) => f.as_encoded_bytes(),1738        };17391740        let new = extension.as_encoded_bytes();1741        if !new.is_empty() {1742            // truncate until right after the file name1743            // this is necessary for trimming the trailing separator1744            let end_file_name = file_name[file_name.len()..].as_ptr().addr();1745            let start = self.inner.as_encoded_bytes().as_ptr().addr();1746            self.inner.truncate(end_file_name.wrapping_sub(start));17471748            // append the new extension1749            self.inner.reserve_exact(new.len() + 1);1750            self.inner.push(".");1751            // SAFETY: Since a UTF-8 string was just pushed, it is not possible1752            // for the buffer to end with a surrogate half.1753            unsafe { self.inner.extend_from_slice_unchecked(new) };1754        }17551756        true1757    }17581759    /// Yields a mutable reference to the underlying [`OsString`] instance.1760    ///1761    /// # Examples1762    ///1763    /// ```1764    /// use std::path::{Path, PathBuf};1765    ///1766    /// let mut path = PathBuf::from("/foo");1767    ///1768    /// path.push("bar");1769    /// assert_eq!(path, Path::new("/foo/bar"));1770    ///1771    /// // OsString's `push` does not add a separator.1772    /// path.as_mut_os_string().push("baz");1773    /// assert_eq!(path, Path::new("/foo/barbaz"));1774    /// ```1775    #[stable(feature = "path_as_mut_os_str", since = "1.70.0")]1776    #[must_use]1777    #[inline]1778    pub fn as_mut_os_string(&mut self) -> &mut OsString {1779        &mut self.inner1780    }17811782    /// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.1783    ///1784    /// # Examples1785    ///1786    /// ```1787    /// use std::path::PathBuf;1788    ///1789    /// let p = PathBuf::from("/the/head");1790    /// let os_str = p.into_os_string();1791    /// ```1792    #[stable(feature = "rust1", since = "1.0.0")]1793    #[must_use = "`self` will be dropped if the result is not used"]1794    #[inline]1795    pub fn into_os_string(self) -> OsString {1796        self.inner1797    }17981799    /// Converts this `PathBuf` into a [boxed](Box) [`Path`].1800    #[stable(feature = "into_boxed_path", since = "1.20.0")]1801    #[must_use = "`self` will be dropped if the result is not used"]1802    #[inline]1803    pub fn into_boxed_path(self) -> Box<Path> {1804        let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;1805        unsafe { Box::from_raw(rw) }1806    }18071808    /// Invokes [`capacity`] on the underlying instance of [`OsString`].1809    ///1810    /// [`capacity`]: OsString::capacity1811    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1812    #[must_use]1813    #[inline]1814    pub fn capacity(&self) -> usize {1815        self.inner.capacity()1816    }18171818    /// Invokes [`clear`] on the underlying instance of [`OsString`].1819    ///1820    /// [`clear`]: OsString::clear1821    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1822    #[inline]1823    pub fn clear(&mut self) {1824        self.inner.clear()1825    }18261827    /// Invokes [`reserve`] on the underlying instance of [`OsString`].1828    ///1829    /// [`reserve`]: OsString::reserve1830    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1831    #[inline]1832    pub fn reserve(&mut self, additional: usize) {1833        self.inner.reserve(additional)1834    }18351836    /// Invokes [`try_reserve`] on the underlying instance of [`OsString`].1837    ///1838    /// [`try_reserve`]: OsString::try_reserve1839    #[stable(feature = "try_reserve_2", since = "1.63.0")]1840    #[inline]1841    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {1842        self.inner.try_reserve(additional)1843    }18441845    /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].1846    ///1847    /// [`reserve_exact`]: OsString::reserve_exact1848    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1849    #[inline]1850    pub fn reserve_exact(&mut self, additional: usize) {1851        self.inner.reserve_exact(additional)1852    }18531854    /// Invokes [`try_reserve_exact`] on the underlying instance of [`OsString`].1855    ///1856    /// [`try_reserve_exact`]: OsString::try_reserve_exact1857    #[stable(feature = "try_reserve_2", since = "1.63.0")]1858    #[inline]1859    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {1860        self.inner.try_reserve_exact(additional)1861    }18621863    /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].1864    ///1865    /// [`shrink_to_fit`]: OsString::shrink_to_fit1866    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1867    #[inline]1868    pub fn shrink_to_fit(&mut self) {1869        self.inner.shrink_to_fit()1870    }18711872    /// Invokes [`shrink_to`] on the underlying instance of [`OsString`].1873    ///1874    /// [`shrink_to`]: OsString::shrink_to1875    #[stable(feature = "shrink_to", since = "1.56.0")]1876    #[inline]1877    pub fn shrink_to(&mut self, min_capacity: usize) {1878        self.inner.shrink_to(min_capacity)1879    }1880}18811882#[stable(feature = "rust1", since = "1.0.0")]1883impl Clone for PathBuf {1884    #[inline]1885    fn clone(&self) -> Self {1886        PathBuf { inner: self.inner.clone() }1887    }18881889    /// Clones the contents of `source` into `self`.1890    ///1891    /// This method is preferred over simply assigning `source.clone()` to `self`,1892    /// as it avoids reallocation if possible.1893    #[inline]1894    fn clone_from(&mut self, source: &Self) {1895        self.inner.clone_from(&source.inner)1896    }1897}18981899#[stable(feature = "box_from_path", since = "1.17.0")]1900impl From<&Path> for Box<Path> {1901    /// Creates a boxed [`Path`] from a reference.1902    ///1903    /// This will allocate and clone `path` to it.1904    fn from(path: &Path) -> Box<Path> {1905        Box::clone_from_ref(path)1906    }1907}19081909#[stable(feature = "box_from_mut_slice", since = "1.84.0")]1910impl From<&mut Path> for Box<Path> {1911    /// Creates a boxed [`Path`] from a reference.1912    ///1913    /// This will allocate and clone `path` to it.1914    fn from(path: &mut Path) -> Box<Path> {1915        Self::from(&*path)1916    }1917}19181919#[stable(feature = "box_from_cow", since = "1.45.0")]1920impl From<Cow<'_, Path>> for Box<Path> {1921    /// Creates a boxed [`Path`] from a clone-on-write pointer.1922    ///1923    /// Converting from a `Cow::Owned` does not clone or allocate.1924    #[inline]1925    fn from(cow: Cow<'_, Path>) -> Box<Path> {1926        match cow {1927            Cow::Borrowed(path) => Box::from(path),1928            Cow::Owned(path) => Box::from(path),1929        }1930    }1931}19321933#[stable(feature = "path_buf_from_box", since = "1.18.0")]1934impl From<Box<Path>> for PathBuf {1935    /// Converts a <code>[Box]&lt;[Path]&gt;</code> into a [`PathBuf`].1936    ///1937    /// This conversion does not allocate or copy memory.1938    #[inline]1939    fn from(boxed: Box<Path>) -> PathBuf {1940        boxed.into_path_buf()1941    }1942}19431944#[stable(feature = "box_from_path_buf", since = "1.20.0")]1945impl From<PathBuf> for Box<Path> {1946    /// Converts a [`PathBuf`] into a <code>[Box]&lt;[Path]&gt;</code>.1947    ///1948    /// This conversion currently should not allocate memory,1949    /// but this behavior is not guaranteed on all platforms or in all future versions.1950    #[inline]1951    fn from(p: PathBuf) -> Box<Path> {1952        p.into_boxed_path()1953    }1954}19551956#[stable(feature = "more_box_slice_clone", since = "1.29.0")]1957impl Clone for Box<Path> {1958    #[inline]1959    fn clone(&self) -> Self {1960        self.to_path_buf().into_boxed_path()1961    }1962}19631964#[stable(feature = "rust1", since = "1.0.0")]1965impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {1966    /// Converts a borrowed [`OsStr`] to a [`PathBuf`].1967    ///1968    /// Allocates a [`PathBuf`] and copies the data into it.1969    #[inline]1970    fn from(s: &T) -> PathBuf {1971        PathBuf::from(s.as_ref().to_os_string())1972    }1973}19741975#[stable(feature = "rust1", since = "1.0.0")]1976impl From<OsString> for PathBuf {1977    /// Converts an [`OsString`] into a [`PathBuf`].1978    ///1979    /// This conversion does not allocate or copy memory.1980    #[inline]1981    fn from(s: OsString) -> PathBuf {1982        PathBuf { inner: s }1983    }1984}19851986#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")]1987impl From<PathBuf> for OsString {1988    /// Converts a [`PathBuf`] into an [`OsString`]1989    ///1990    /// This conversion does not allocate or copy memory.1991    #[inline]1992    fn from(path_buf: PathBuf) -> OsString {1993        path_buf.inner1994    }1995}19961997#[stable(feature = "rust1", since = "1.0.0")]1998impl From<String> for PathBuf {1999    /// Converts a [`String`] into a [`PathBuf`]2000    ///

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.