library/std/src/path.rs RUST 4,156 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 4,156.
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::alloc::Allocator;87use crate::borrow::{Borrow, Cow};88use crate::collections::TryReserveError;89use crate::error::Error;90use crate::ffi::{OsStr, OsString, os_str};91use crate::hash::{Hash, Hasher};92use crate::iter::FusedIterator;93use crate::ops::{self, Deref};94use crate::rc::Rc;95use crate::str::FromStr;96use crate::sync::Arc;97use crate::sys::path::{HAS_PREFIXES, is_sep_byte, is_verbatim_sep, parse_prefix};98use crate::{cmp, fmt, fs, io, sys};99100////////////////////////////////////////////////////////////////////////////////101// GENERAL NOTES102////////////////////////////////////////////////////////////////////////////////103//104// Parsing in this module is done by directly transmuting OsStr to [u8] slices,105// taking advantage of the fact that OsStr always encodes ASCII characters106// as-is.  Eventually, this transmutation should be replaced by direct uses of107// OsStr APIs for parsing, but it will take a while for those to become108// available.109110////////////////////////////////////////////////////////////////////////////////111// Windows Prefixes112////////////////////////////////////////////////////////////////////////////////113114/// Windows path prefixes, e.g., `C:` or `\\server\share`.115///116/// Windows uses a variety of path prefix styles, including references to drive117/// volumes (like `C:`), network shared folders (like `\\server\share`), and118/// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with119/// `\\?\`), in which case `/` is *not* treated as a separator and essentially120/// no normalization is performed.121///122/// # Examples123///124/// ```125/// use std::path::{Component, Path, Prefix};126/// use std::path::Prefix::*;127/// use std::ffi::OsStr;128///129/// fn get_path_prefix(s: &str) -> Prefix<'_> {130///     let path = Path::new(s);131///     match path.components().next().unwrap() {132///         Component::Prefix(prefix_component) => prefix_component.kind(),133///         _ => panic!(),134///     }135/// }136///137/// # if cfg!(windows) {138/// assert_eq!(Verbatim(OsStr::new("pictures")),139///            get_path_prefix(r"\\?\pictures\kittens"));140/// assert_eq!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")),141///            get_path_prefix(r"\\?\UNC\server\share"));142/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\"));143/// assert_eq!(DeviceNS(OsStr::new("BrainInterface")),144///            get_path_prefix(r"\\.\BrainInterface"));145/// assert_eq!(UNC(OsStr::new("server"), OsStr::new("share")),146///            get_path_prefix(r"\\server\share"));147/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));148/// # }149/// ```150#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]151#[stable(feature = "rust1", since = "1.0.0")]152pub enum Prefix<'a> {153    /// Verbatim prefix, e.g., `\\?\cat_pics`.154    ///155    /// Verbatim prefixes consist of `\\?\` immediately followed by the given156    /// component.157    #[stable(feature = "rust1", since = "1.0.0")]158    Verbatim(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),159160    /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_,161    /// e.g., `\\?\UNC\server\share`.162    ///163    /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the164    /// server's hostname and a share name.165    #[stable(feature = "rust1", since = "1.0.0")]166    VerbatimUNC(167        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,168        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,169    ),170171    /// Verbatim disk prefix, e.g., `\\?\C:`.172    ///173    /// Verbatim disk prefixes consist of `\\?\` immediately followed by the174    /// drive letter and `:`.175    #[stable(feature = "rust1", since = "1.0.0")]176    VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8),177178    /// Device namespace prefix, e.g., `\\.\COM42`.179    ///180    /// Device namespace prefixes consist of `\\.\` (possibly using `/`181    /// instead of `\`), immediately followed by the device name.182    #[stable(feature = "rust1", since = "1.0.0")]183    DeviceNS(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),184185    /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g.186    /// `\\server\share`.187    ///188    /// UNC prefixes consist of the server's hostname and a share name.189    #[stable(feature = "rust1", since = "1.0.0")]190    UNC(191        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,192        #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr,193    ),194195    /// Prefix `C:` for the given disk drive.196    #[stable(feature = "rust1", since = "1.0.0")]197    Disk(#[stable(feature = "rust1", since = "1.0.0")] u8),198}199200impl<'a> Prefix<'a> {201    #[inline]202    fn len(&self) -> usize {203        use self::Prefix::*;204        fn os_str_len(s: &OsStr) -> usize {205            s.as_encoded_bytes().len()206        }207        match *self {208            Verbatim(x) => 4 + os_str_len(x),209            VerbatimUNC(x, y) => {210                8 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 }211            }212            VerbatimDisk(_) => 6,213            UNC(x, y) => 2 + os_str_len(x) + if os_str_len(y) > 0 { 1 + os_str_len(y) } else { 0 },214            DeviceNS(x) => 4 + os_str_len(x),215            Disk(_) => 2,216        }217    }218219    /// Determines if the prefix is verbatim, i.e., begins with `\\?\`.220    ///221    /// # Examples222    ///223    /// ```224    /// use std::path::Prefix::*;225    /// use std::ffi::OsStr;226    ///227    /// assert!(Verbatim(OsStr::new("pictures")).is_verbatim());228    /// assert!(VerbatimUNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());229    /// assert!(VerbatimDisk(b'C').is_verbatim());230    /// assert!(!DeviceNS(OsStr::new("BrainInterface")).is_verbatim());231    /// assert!(!UNC(OsStr::new("server"), OsStr::new("share")).is_verbatim());232    /// assert!(!Disk(b'C').is_verbatim());233    /// ```234    #[inline]235    #[must_use]236    #[stable(feature = "rust1", since = "1.0.0")]237    pub fn is_verbatim(&self) -> bool {238        use self::Prefix::*;239        matches!(*self, Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..))240    }241242    #[inline]243    fn is_drive(&self) -> bool {244        matches!(*self, Prefix::Disk(_))245    }246247    #[inline]248    fn has_implicit_root(&self) -> bool {249        !self.is_drive()250    }251}252253////////////////////////////////////////////////////////////////////////////////254// Exposed parsing helpers255////////////////////////////////////////////////////////////////////////////////256257/// Determines whether the character is one of the permitted path258/// separators for the current platform.259///260/// # Examples261///262/// ```263/// use std::path;264///265/// assert!(path::is_separator('/')); // '/' works for both Unix and Windows266/// assert!(!path::is_separator('❤'));267/// ```268#[must_use]269#[stable(feature = "rust1", since = "1.0.0")]270#[rustc_const_unstable(feature = "const_path_separators", issue = "153106")]271pub const fn is_separator(c: char) -> bool {272    c.is_ascii() && is_sep_byte(c as u8)273}274275/// All path separators recognized on the current platform, represented as [`char`]s; for example,276/// this is `&['/'][..]` on Unix and `&['\\', '/'][..]` on Windows. The [primary277/// separator](MAIN_SEPARATOR) is always element 0 of the slice.278#[unstable(feature = "const_path_separators", issue = "153106")]279pub const SEPARATORS: &[char] = crate::sys::path::SEPARATORS;280281/// All path separators recognized on the current platform, represented as [`&str`]s; for example,282/// this is `&["/"][..]` on Unix and `&["\\", "/"][..]` on Windows. The [primary283/// separator](MAIN_SEPARATOR_STR) is always element 0 of the slice.284#[unstable(feature = "const_path_separators", issue = "153106")]285pub const SEPARATORS_STR: &[&str] = crate::sys::path::SEPARATORS_STR;286287/// The primary separator of path components for the current platform, represented as a [`char`];288/// for example, this is `'/'` on Unix and `'\\'` on Windows.289#[stable(feature = "rust1", since = "1.0.0")]290#[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")]291pub const MAIN_SEPARATOR: char = SEPARATORS[0];292293/// The primary separator of path components for the current platform, represented as a [`&str`];294/// for example, this is `"/"` on Unix and `"\\"` on Windows.295#[stable(feature = "main_separator_str", since = "1.68.0")]296pub const MAIN_SEPARATOR_STR: &str = SEPARATORS_STR[0];297298////////////////////////////////////////////////////////////////////////////////299// Misc helpers300////////////////////////////////////////////////////////////////////////////////301302// Iterate through `iter` while it matches `prefix`; return `None` if `prefix`303// is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving304// `iter` after having exhausted `prefix`.305fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>306where307    I: Iterator<Item = Component<'a>> + Clone,308    J: Iterator<Item = Component<'b>>,309{310    loop {311        let mut iter_next = iter.clone();312        match (iter_next.next(), prefix.next()) {313            (Some(ref x), Some(ref y)) if x == y => (),314            (Some(_), Some(_)) => return None,315            (Some(_), None) => return Some(iter),316            (None, None) => return Some(iter),317            (None, Some(_)) => return None,318        }319        iter = iter_next;320    }321}322323////////////////////////////////////////////////////////////////////////////////324// Cross-platform, iterator-independent parsing325////////////////////////////////////////////////////////////////////////////////326327/// Says whether the first byte after the prefix is a separator.328fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {329    let path = if let Some(p) = prefix { &s[p.len()..] } else { s };330    !path.is_empty() && is_sep_byte(path[0])331}332333// basic workhorse for splitting stem and extension334fn rsplit_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {335    if file.as_encoded_bytes() == b".." {336        return (Some(file), None);337    }338339    // The unsafety here stems from converting between &OsStr and &[u8]340    // and back. This is safe to do because (1) we only look at ASCII341    // contents of the encoding and (2) new &OsStr values are produced342    // only from ASCII-bounded slices of existing &OsStr values.343    let mut iter = file.as_encoded_bytes().rsplitn(2, |b| *b == b'.');344    let after = iter.next();345    let before = iter.next();346    if before == Some(b"") {347        (Some(file), None)348    } else {349        unsafe {350            (351                before.map(|s| OsStr::from_encoded_bytes_unchecked(s)),352                after.map(|s| OsStr::from_encoded_bytes_unchecked(s)),353            )354        }355    }356}357358fn split_file_at_dot(file: &OsStr) -> (&OsStr, Option<&OsStr>) {359    let slice = file.as_encoded_bytes();360    if slice == b".." {361        return (file, None);362    }363364    // The unsafety here stems from converting between &OsStr and &[u8]365    // and back. This is safe to do because (1) we only look at ASCII366    // contents of the encoding and (2) new &OsStr values are produced367    // only from ASCII-bounded slices of existing &OsStr values.368    let i = match slice[1..].iter().position(|b| *b == b'.') {369        Some(i) => i + 1,370        None => return (file, None),371    };372    let before = &slice[..i];373    let after = &slice[i + 1..];374    unsafe {375        (376            OsStr::from_encoded_bytes_unchecked(before),377            Some(OsStr::from_encoded_bytes_unchecked(after)),378        )379    }380}381382/// Checks whether the string is valid as a file extension, or panics otherwise.383fn validate_extension(extension: &OsStr) {384    for &b in extension.as_encoded_bytes() {385        if is_sep_byte(b) {386            panic!("extension cannot contain path separators: {extension:?}");387        }388    }389}390391////////////////////////////////////////////////////////////////////////////////392// The core iterators393////////////////////////////////////////////////////////////////////////////////394395/// Component parsing works by a double-ended state machine; the cursors at the396/// front and back of the path each keep track of what parts of the path have397/// been consumed so far.398///399/// Going front to back, a path is made up of a prefix, a starting400/// directory component, and a body (of normal components)401#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]402enum State {403    Prefix = 0,   // c:404    StartDir = 1, // / or . or nothing405    Body = 2,     // foo/bar/baz406    Done = 3,407}408409/// A structure wrapping a Windows path prefix as well as its unparsed string410/// representation.411///412/// In addition to the parsed [`Prefix`] information returned by [`kind`],413/// `PrefixComponent` also holds the raw and unparsed [`OsStr`] slice,414/// returned by [`as_os_str`].415///416/// Instances of this `struct` can be obtained by matching against the417/// [`Prefix` variant] on [`Component`].418///419/// Does not occur on Unix.420///421/// # Examples422///423/// ```424/// # if cfg!(windows) {425/// use std::path::{Component, Path, Prefix};426/// use std::ffi::OsStr;427///428/// let path = Path::new(r"c:\you\later\");429/// match path.components().next().unwrap() {430///     Component::Prefix(prefix_component) => {431///         assert_eq!(Prefix::Disk(b'C'), prefix_component.kind());432///         assert_eq!(OsStr::new("c:"), prefix_component.as_os_str());433///     }434///     _ => unreachable!(),435/// }436/// # }437/// ```438///439/// [`as_os_str`]: PrefixComponent::as_os_str440/// [`kind`]: PrefixComponent::kind441/// [`Prefix` variant]: Component::Prefix442#[stable(feature = "rust1", since = "1.0.0")]443#[derive(Copy, Clone, Eq, Debug)]444pub struct PrefixComponent<'a> {445    /// The prefix as an unparsed `OsStr` slice.446    raw: &'a OsStr,447448    /// The parsed prefix data.449    parsed: Prefix<'a>,450}451452impl<'a> PrefixComponent<'a> {453    /// Returns the parsed prefix data.454    ///455    /// See [`Prefix`]'s documentation for more information on the different456    /// kinds of prefixes.457    #[stable(feature = "rust1", since = "1.0.0")]458    #[must_use]459    #[inline]460    pub fn kind(&self) -> Prefix<'a> {461        self.parsed462    }463464    /// Returns the raw [`OsStr`] slice for this prefix.465    #[stable(feature = "rust1", since = "1.0.0")]466    #[must_use]467    #[inline]468    pub fn as_os_str(&self) -> &'a OsStr {469        self.raw470    }471}472473#[stable(feature = "rust1", since = "1.0.0")]474impl<'a> PartialEq for PrefixComponent<'a> {475    #[inline]476    fn eq(&self, other: &PrefixComponent<'a>) -> bool {477        self.parsed == other.parsed478    }479}480481#[stable(feature = "rust1", since = "1.0.0")]482impl<'a> PartialOrd for PrefixComponent<'a> {483    #[inline]484    fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> {485        PartialOrd::partial_cmp(&self.parsed, &other.parsed)486    }487}488489#[stable(feature = "rust1", since = "1.0.0")]490impl Ord for PrefixComponent<'_> {491    #[inline]492    fn cmp(&self, other: &Self) -> cmp::Ordering {493        Ord::cmp(&self.parsed, &other.parsed)494    }495}496497#[stable(feature = "rust1", since = "1.0.0")]498impl Hash for PrefixComponent<'_> {499    fn hash<H: Hasher>(&self, h: &mut H) {500        self.parsed.hash(h);501    }502}503504/// A single component of a path.505///506/// A `Component` roughly corresponds to a substring between path separators507/// (`/` or `\`).508///509/// This `enum` is created by iterating over [`Components`], which in turn is510/// created by the [`components`](Path::components) method on [`Path`].511///512/// # Examples513///514/// ```rust515/// use std::path::{Component, Path};516///517/// let path = Path::new("/tmp/foo/bar.txt");518/// let components = path.components().collect::<Vec<_>>();519/// assert_eq!(&components, &[520///     Component::RootDir,521///     Component::Normal("tmp".as_ref()),522///     Component::Normal("foo".as_ref()),523///     Component::Normal("bar.txt".as_ref()),524/// ]);525/// ```526#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]527#[stable(feature = "rust1", since = "1.0.0")]528pub enum Component<'a> {529    /// A Windows path prefix, e.g., `C:` or `\\server\share`.530    ///531    /// There is a large variety of prefix types, see [`Prefix`]'s documentation532    /// for more.533    ///534    /// Does not occur on Unix.535    #[stable(feature = "rust1", since = "1.0.0")]536    Prefix(#[stable(feature = "rust1", since = "1.0.0")] PrefixComponent<'a>),537538    /// The root directory component, appears after any prefix and before anything else.539    ///540    /// It represents a separator that designates that a path starts from root.541    #[stable(feature = "rust1", since = "1.0.0")]542    RootDir,543544    /// A reference to the current directory, i.e., `.`.545    #[stable(feature = "rust1", since = "1.0.0")]546    CurDir,547548    /// A reference to the parent directory, i.e., `..`.549    #[stable(feature = "rust1", since = "1.0.0")]550    ParentDir,551552    /// A normal component, e.g., `a` and `b` in `a/b`.553    ///554    /// This variant is the most common one, it represents references to files555    /// or directories.556    #[stable(feature = "rust1", since = "1.0.0")]557    Normal(#[stable(feature = "rust1", since = "1.0.0")] &'a OsStr),558}559560impl<'a> Component<'a> {561    /// Extracts the underlying [`OsStr`] slice.562    ///563    /// # Examples564    ///565    /// ```566    /// use std::path::Path;567    ///568    /// let path = Path::new("./tmp/foo/bar.txt");569    /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();570    /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);571    /// ```572    #[must_use = "`self` will be dropped if the result is not used"]573    #[stable(feature = "rust1", since = "1.0.0")]574    pub fn as_os_str(self) -> &'a OsStr {575        match self {576            Component::Prefix(p) => p.as_os_str(),577            Component::RootDir => OsStr::new(MAIN_SEPARATOR_STR),578            Component::CurDir => OsStr::new("."),579            Component::ParentDir => OsStr::new(".."),580            Component::Normal(path) => path,581        }582    }583}584585#[stable(feature = "rust1", since = "1.0.0")]586impl AsRef<OsStr> for Component<'_> {587    #[inline]588    fn as_ref(&self) -> &OsStr {589        self.as_os_str()590    }591}592593#[stable(feature = "path_component_asref", since = "1.25.0")]594impl AsRef<Path> for Component<'_> {595    #[inline]596    fn as_ref(&self) -> &Path {597        self.as_os_str().as_ref()598    }599}600601/// An iterator over the [`Component`]s of a [`Path`].602///603/// This `struct` is created by the [`components`] method on [`Path`].604/// See its documentation for more.605///606/// # Examples607///608/// ```609/// use std::path::Path;610///611/// let path = Path::new("/tmp/foo/bar.txt");612///613/// for component in path.components() {614///     println!("{component:?}");615/// }616/// ```617///618/// [`components`]: Path::components619#[derive(Clone)]620#[must_use = "iterators are lazy and do nothing unless consumed"]621#[stable(feature = "rust1", since = "1.0.0")]622pub struct Components<'a> {623    // The path left to parse components from624    path: &'a [u8],625626    // The prefix as it was originally parsed, if any627    prefix: Option<Prefix<'a>>,628629    // true if path *physically* has a root separator; for most Windows630    // prefixes, it may have a "logical" root separator for the purposes of631    // normalization, e.g., \\server\share == \\server\share\.632    has_physical_root: bool,633634    // The iterator is double-ended, and these two states keep track of what has635    // been produced from either end636    front: State,637    back: State,638}639640/// An iterator over the [`Component`]s of a [`Path`], as [`OsStr`] slices.641///642/// This `struct` is created by the [`iter`] method on [`Path`].643/// See its documentation for more.644///645/// [`iter`]: Path::iter646#[derive(Clone)]647#[must_use = "iterators are lazy and do nothing unless consumed"]648#[stable(feature = "rust1", since = "1.0.0")]649pub struct Iter<'a> {650    inner: Components<'a>,651}652653#[stable(feature = "path_components_debug", since = "1.13.0")]654impl fmt::Debug for Components<'_> {655    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {656        struct DebugHelper<'a>(&'a Path);657658        impl fmt::Debug for DebugHelper<'_> {659            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {660                f.debug_list().entries(self.0.components()).finish()661            }662        }663664        f.debug_tuple("Components").field(&DebugHelper(self.as_path())).finish()665    }666}667668impl<'a> Components<'a> {669    // how long is the prefix, if any?670    #[inline]671    fn prefix_len(&self) -> usize {672        if !HAS_PREFIXES {673            return 0;674        }675        self.prefix.as_ref().map(Prefix::len).unwrap_or(0)676    }677678    #[inline]679    fn prefix_verbatim(&self) -> bool {680        if !HAS_PREFIXES {681            return false;682        }683        self.prefix.as_ref().map(Prefix::is_verbatim).unwrap_or(false)684    }685686    /// how much of the prefix is left from the point of view of iteration?687    #[inline]688    fn prefix_remaining(&self) -> usize {689        if !HAS_PREFIXES {690            return 0;691        }692        if self.front == State::Prefix { self.prefix_len() } else { 0 }693    }694695    // Given the iteration so far, how much of the pre-State::Body path is left?696    #[inline]697    fn len_before_body(&self) -> usize {698        let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 };699        let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 };700        self.prefix_remaining() + root + cur_dir701    }702703    // is the iteration complete?704    #[inline]705    fn finished(&self) -> bool {706        self.front == State::Done || self.back == State::Done || self.front > self.back707    }708709    #[inline]710    fn is_sep_byte(&self, b: u8) -> bool {711        if self.prefix_verbatim() { is_verbatim_sep(b) } else { is_sep_byte(b) }712    }713714    /// Extracts a slice corresponding to the portion of the path remaining for iteration.715    ///716    /// # Examples717    ///718    /// ```719    /// use std::path::Path;720    ///721    /// let mut components = Path::new("/tmp/foo/bar.txt").components();722    /// components.next();723    /// components.next();724    ///725    /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());726    /// ```727    #[must_use]728    #[stable(feature = "rust1", since = "1.0.0")]729    pub fn as_path(&self) -> &'a Path {730        let mut comps = self.clone();731        if comps.front == State::Body {732            comps.trim_left();733        }734        if comps.back == State::Body {735            comps.trim_right();736        }737        unsafe { Path::from_u8_slice(comps.path) }738    }739740    /// Is the *original* path rooted?741    fn has_root(&self) -> bool {742        if self.has_physical_root {743            return true;744        }745        if HAS_PREFIXES && let Some(p) = self.prefix {746            if p.has_implicit_root() {747                return true;748            }749        }750        false751    }752753    /// Should the normalized path include a leading . ?754    fn include_cur_dir(&self) -> bool {755        if self.has_root() {756            return false;757        }758        let slice = &self.path[self.prefix_remaining()..];759        match slice {760            [b'.'] => true,761            [b'.', b, ..] => self.is_sep_byte(*b),762            _ => false,763        }764    }765766    // parse a given byte sequence following the OsStr encoding into the767    // corresponding path component768    unsafe fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {769        match comp {770            b"." if HAS_PREFIXES && self.prefix_verbatim() => Some(Component::CurDir),771            b"." => None, // . components are normalized away, except at772            // the beginning of a path, which is treated773            // separately via `include_cur_dir`774            b".." => Some(Component::ParentDir),775            b"" => None,776            _ => Some(Component::Normal(unsafe { OsStr::from_encoded_bytes_unchecked(comp) })),777        }778    }779780    // parse a component from the left, saying how many bytes to consume to781    // remove the component782    fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {783        debug_assert!(self.front == State::Body);784        let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) {785            None => (0, self.path),786            Some(i) => (1, &self.path[..i]),787        };788        // SAFETY: `comp` is a valid substring, since it is split on a separator.789        (comp.len() + extra, unsafe { self.parse_single_component(comp) })790    }791792    // parse a component from the right, saying how many bytes to consume to793    // remove the component794    fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {795        debug_assert!(self.back == State::Body);796        let start = self.len_before_body();797        let (extra, comp) = match self.path[start..].iter().rposition(|b| self.is_sep_byte(*b)) {798            None => (0, &self.path[start..]),799            Some(i) => (1, &self.path[start + i + 1..]),800        };801        // SAFETY: `comp` is a valid substring, since it is split on a separator.802        (comp.len() + extra, unsafe { self.parse_single_component(comp) })803    }804805    // trim away repeated separators (i.e., empty components) on the left806    fn trim_left(&mut self) {807        while !self.path.is_empty() {808            let (size, comp) = self.parse_next_component();809            if comp.is_some() {810                return;811            } else {812                self.path = &self.path[size..];813            }814        }815    }816817    // trim away repeated separators (i.e., empty components) on the right818    fn trim_right(&mut self) {819        while self.path.len() > self.len_before_body() {820            let (size, comp) = self.parse_next_component_back();821            if comp.is_some() {822                return;823            } else {824                self.path = &self.path[..self.path.len() - size];825            }826        }827    }828}829830#[stable(feature = "rust1", since = "1.0.0")]831impl AsRef<Path> for Components<'_> {832    #[inline]833    fn as_ref(&self) -> &Path {834        self.as_path()835    }836}837838#[stable(feature = "rust1", since = "1.0.0")]839impl AsRef<OsStr> for Components<'_> {840    #[inline]841    fn as_ref(&self) -> &OsStr {842        self.as_path().as_os_str()843    }844}845846#[stable(feature = "path_iter_debug", since = "1.13.0")]847impl fmt::Debug for Iter<'_> {848    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {849        struct DebugHelper<'a>(&'a Path);850851        impl fmt::Debug for DebugHelper<'_> {852            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {853                f.debug_list().entries(self.0.iter()).finish()854            }855        }856857        f.debug_tuple("Iter").field(&DebugHelper(self.as_path())).finish()858    }859}860861impl<'a> Iter<'a> {862    /// Extracts a slice corresponding to the portion of the path remaining for iteration.863    ///864    /// # Examples865    ///866    /// ```867    /// use std::path::Path;868    ///869    /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();870    /// iter.next();871    /// iter.next();872    ///873    /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());874    /// ```875    #[stable(feature = "rust1", since = "1.0.0")]876    #[must_use]877    #[inline]878    pub fn as_path(&self) -> &'a Path {879        self.inner.as_path()880    }881}882883#[stable(feature = "rust1", since = "1.0.0")]884impl AsRef<Path> for Iter<'_> {885    #[inline]886    fn as_ref(&self) -> &Path {887        self.as_path()888    }889}890891#[stable(feature = "rust1", since = "1.0.0")]892impl AsRef<OsStr> for Iter<'_> {893    #[inline]894    fn as_ref(&self) -> &OsStr {895        self.as_path().as_os_str()896    }897}898899#[stable(feature = "rust1", since = "1.0.0")]900impl<'a> Iterator for Iter<'a> {901    type Item = &'a OsStr;902903    #[inline]904    fn next(&mut self) -> Option<&'a OsStr> {905        self.inner.next().map(Component::as_os_str)906    }907}908909#[stable(feature = "rust1", since = "1.0.0")]910impl<'a> DoubleEndedIterator for Iter<'a> {911    #[inline]912    fn next_back(&mut self) -> Option<&'a OsStr> {913        self.inner.next_back().map(Component::as_os_str)914    }915}916917#[stable(feature = "fused", since = "1.26.0")]918impl FusedIterator for Iter<'_> {}919920#[stable(feature = "rust1", since = "1.0.0")]921impl<'a> Iterator for Components<'a> {922    type Item = Component<'a>;923924    fn next(&mut self) -> Option<Component<'a>> {925        while !self.finished() {926            match self.front {927                // most likely case first928                State::Body if !self.path.is_empty() => {929                    let (size, comp) = self.parse_next_component();930                    self.path = &self.path[size..];931                    if comp.is_some() {932                        return comp;933                    }934                }935                State::Body => {936                    self.front = State::Done;937                }938                State::StartDir => {939                    self.front = State::Body;940                    if self.has_physical_root {941                        debug_assert!(!self.path.is_empty());942                        self.path = &self.path[1..];943                        return Some(Component::RootDir);944                    } else if HAS_PREFIXES && let Some(p) = self.prefix {945                        if p.has_implicit_root() && !p.is_verbatim() {946                            return Some(Component::RootDir);947                        }948                    } else if self.include_cur_dir() {949                        debug_assert!(!self.path.is_empty());950                        self.path = &self.path[1..];951                        return Some(Component::CurDir);952                    }953                }954                _ if const { !HAS_PREFIXES } => unreachable!(),955                State::Prefix if self.prefix_len() == 0 => {956                    self.front = State::StartDir;957                }958                State::Prefix => {959                    self.front = State::StartDir;960                    debug_assert!(self.prefix_len() <= self.path.len());961                    let raw = &self.path[..self.prefix_len()];962                    self.path = &self.path[self.prefix_len()..];963                    return Some(Component::Prefix(PrefixComponent {964                        raw: unsafe { OsStr::from_encoded_bytes_unchecked(raw) },965                        parsed: self.prefix.unwrap(),966                    }));967                }968                State::Done => unreachable!(),969            }970        }971        None972    }973}974975#[stable(feature = "rust1", since = "1.0.0")]976impl<'a> DoubleEndedIterator for Components<'a> {977    fn next_back(&mut self) -> Option<Component<'a>> {978        while !self.finished() {979            match self.back {980                State::Body if self.path.len() > self.len_before_body() => {981                    let (size, comp) = self.parse_next_component_back();982                    self.path = &self.path[..self.path.len() - size];983                    if comp.is_some() {984                        return comp;985                    }986                }987                State::Body => {988                    self.back = State::StartDir;989                }990                State::StartDir => {991                    self.back = if HAS_PREFIXES { State::Prefix } else { State::Done };992                    if self.has_physical_root {993                        self.path = &self.path[..self.path.len() - 1];994                        return Some(Component::RootDir);995                    } else if HAS_PREFIXES && let Some(p) = self.prefix {996                        if p.has_implicit_root() && !p.is_verbatim() {997                            return Some(Component::RootDir);998                        }999                    } else if self.include_cur_dir() {1000                        self.path = &self.path[..self.path.len() - 1];1001                        return Some(Component::CurDir);1002                    }1003                }1004                _ if !HAS_PREFIXES => unreachable!(),1005                State::Prefix if self.prefix_len() > 0 => {1006                    self.back = State::Done;1007                    return Some(Component::Prefix(PrefixComponent {1008                        raw: unsafe { OsStr::from_encoded_bytes_unchecked(self.path) },1009                        parsed: self.prefix.unwrap(),1010                    }));1011                }1012                State::Prefix => {1013                    self.back = State::Done;1014                    return None;1015                }1016                State::Done => unreachable!(),1017            }1018        }1019        None1020    }1021}10221023#[stable(feature = "fused", since = "1.26.0")]1024impl FusedIterator for Components<'_> {}10251026#[stable(feature = "rust1", since = "1.0.0")]1027impl<'a> PartialEq for Components<'a> {1028    #[inline]1029    fn eq(&self, other: &Components<'a>) -> bool {1030        let Components { path: _, front: _, back: _, has_physical_root: _, prefix: _ } = self;10311032        // Fast path for exact matches, e.g. for hashmap lookups.1033        // Don't explicitly compare the prefix or has_physical_root fields since they'll1034        // either be covered by the `path` buffer or are only relevant for `prefix_verbatim()`.1035        if self.path.len() == other.path.len()1036            && self.front == other.front1037            && self.back == State::Body1038            && other.back == State::Body1039            && self.prefix_verbatim() == other.prefix_verbatim()1040        {1041            // possible future improvement: this could bail out earlier if there were a1042            // reverse memcmp/bcmp comparing back to front1043            if self.path == other.path {1044                return true;1045            }1046        }10471048        // compare back to front since absolute paths often share long prefixes1049        Iterator::eq(self.clone().rev(), other.clone().rev())1050    }1051}10521053#[stable(feature = "rust1", since = "1.0.0")]1054impl Eq for Components<'_> {}10551056#[stable(feature = "rust1", since = "1.0.0")]1057impl<'a> PartialOrd for Components<'a> {1058    #[inline]1059    fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {1060        Some(compare_components(self.clone(), other.clone()))1061    }1062}10631064#[stable(feature = "rust1", since = "1.0.0")]1065impl Ord for Components<'_> {1066    #[inline]1067    fn cmp(&self, other: &Self) -> cmp::Ordering {1068        compare_components(self.clone(), other.clone())1069    }1070}10711072fn compare_components(mut left: Components<'_>, mut right: Components<'_>) -> cmp::Ordering {1073    // Fast path for long shared prefixes1074    //1075    // - compare raw bytes to find first mismatch1076    // - backtrack to find separator before mismatch to avoid ambiguous parsings of '.' or '..' characters1077    // - if found update state to only do a component-wise comparison on the remainder,1078    //   otherwise do it on the full path1079    //1080    // The fast path isn't taken for paths with a PrefixComponent to avoid backtracking into1081    // the middle of one1082    if left.prefix.is_none() && right.prefix.is_none() && left.front == right.front {1083        // possible future improvement: a [u8]::first_mismatch simd implementation1084        let first_difference = match left.path.iter().zip(right.path).position(|(&a, &b)| a != b) {1085            None if left.path.len() == right.path.len() => return cmp::Ordering::Equal,1086            None => left.path.len().min(right.path.len()),1087            Some(diff) => diff,1088        };10891090        if let Some(previous_sep) =1091            left.path[..first_difference].iter().rposition(|&b| left.is_sep_byte(b))1092        {1093            let mismatched_component_start = previous_sep + 1;1094            left.path = &left.path[mismatched_component_start..];1095            left.front = State::Body;1096            right.path = &right.path[mismatched_component_start..];1097            right.front = State::Body;1098        }1099    }11001101    Iterator::cmp(left, right)1102}11031104/// An iterator over [`Path`] and its ancestors.1105///1106/// This `struct` is created by the [`ancestors`] method on [`Path`].1107/// See its documentation for more.1108///1109/// # Examples1110///1111/// ```1112/// use std::path::Path;1113///1114/// let path = Path::new("/foo/bar");1115///1116/// for ancestor in path.ancestors() {1117///     println!("{}", ancestor.display());1118/// }1119/// ```1120///1121/// [`ancestors`]: Path::ancestors1122#[derive(Copy, Clone, Debug)]1123#[must_use = "iterators are lazy and do nothing unless consumed"]1124#[stable(feature = "path_ancestors", since = "1.28.0")]1125pub struct Ancestors<'a> {1126    next: Option<&'a Path>,1127}11281129#[stable(feature = "path_ancestors", since = "1.28.0")]1130impl<'a> Iterator for Ancestors<'a> {1131    type Item = &'a Path;11321133    #[inline]1134    fn next(&mut self) -> Option<Self::Item> {1135        let next = self.next;1136        self.next = next.and_then(Path::parent);1137        next1138    }1139}11401141#[stable(feature = "path_ancestors", since = "1.28.0")]1142impl FusedIterator for Ancestors<'_> {}11431144////////////////////////////////////////////////////////////////////////////////1145// Basic types and traits1146////////////////////////////////////////////////////////////////////////////////11471148/// An owned, mutable path (akin to [`String`]).1149///1150/// This type provides methods like [`push`] and [`set_extension`] that mutate1151/// the path in place. It also implements [`Deref`] to [`Path`], meaning that1152/// all methods on [`Path`] slices are available on `PathBuf` values as well.1153///1154/// [`push`]: PathBuf::push1155/// [`set_extension`]: PathBuf::set_extension1156///1157/// More details about the overall approach can be found in1158/// the [module documentation](self).1159///1160/// # Examples1161///1162/// You can use [`push`] to build up a `PathBuf` from1163/// components:1164///1165/// ```1166/// use std::path::PathBuf;1167///1168/// let mut path = PathBuf::new();1169///1170/// path.push(r"C:\");1171/// path.push("windows");1172/// path.push("system32");1173///1174/// path.set_extension("dll");1175/// ```1176///1177/// However, [`push`] is best used for dynamic situations. This is a better way1178/// to do this when you know all of the components ahead of time:1179///1180/// ```1181/// use std::path::PathBuf;1182///1183/// let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();1184/// ```1185///1186/// We can still do better than this! Since these are all strings, we can use1187/// `From::from`:1188///1189/// ```1190/// use std::path::PathBuf;1191///1192/// let path = PathBuf::from(r"C:\windows\system32.dll");1193/// ```1194///1195/// Which method works best depends on what kind of situation you're in.1196///1197/// Note that `PathBuf` does not always sanitize arguments, for example1198/// [`push`] allows paths built from strings which include separators:1199///1200/// ```1201/// use std::path::PathBuf;1202///1203/// let mut path = PathBuf::new();1204///1205/// path.push(r"C:\");1206/// path.push("windows");1207/// path.push(r"..\otherdir");1208/// path.push("system32");1209/// ```1210///1211/// The behavior of `PathBuf` may be changed to a panic on such inputs1212/// in the future. [`Extend::extend`] should be used to add multi-part paths.1213#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]1214#[stable(feature = "rust1", since = "1.0.0")]1215pub struct PathBuf {1216    inner: OsString,1217}12181219impl PathBuf {1220    /// Allocates an empty `PathBuf`.1221    ///1222    /// # Examples1223    ///1224    /// ```1225    /// use std::path::PathBuf;1226    ///1227    /// let path = PathBuf::new();1228    /// ```1229    #[stable(feature = "rust1", since = "1.0.0")]1230    #[must_use]1231    #[inline]1232    #[rustc_const_stable(feature = "const_pathbuf_osstring_new", since = "1.91.0")]1233    pub const fn new() -> PathBuf {1234        PathBuf { inner: OsString::new() }1235    }12361237    /// Creates a new `PathBuf` with a given capacity used to create the1238    /// internal [`OsString`]. See [`with_capacity`] defined on [`OsString`].1239    ///1240    /// # Examples1241    ///1242    /// ```1243    /// use std::path::PathBuf;1244    ///1245    /// let mut path = PathBuf::with_capacity(10);1246    /// let capacity = path.capacity();1247    ///1248    /// // This push is done without reallocating1249    /// path.push(r"C:\");1250    ///1251    /// assert_eq!(capacity, path.capacity());1252    /// ```1253    ///1254    /// [`with_capacity`]: OsString::with_capacity1255    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1256    #[must_use]1257    #[inline]1258    pub fn with_capacity(capacity: usize) -> PathBuf {1259        PathBuf { inner: OsString::with_capacity(capacity) }1260    }12611262    /// Coerces to a [`Path`] slice.1263    ///1264    /// # Examples1265    ///1266    /// ```1267    /// use std::path::{Path, PathBuf};1268    ///1269    /// let p = PathBuf::from("/test");1270    /// assert_eq!(Path::new("/test"), p.as_path());1271    /// ```1272    #[cfg_attr(not(test), rustc_diagnostic_item = "pathbuf_as_path")]1273    #[stable(feature = "rust1", since = "1.0.0")]1274    #[must_use]1275    #[inline]1276    pub fn as_path(&self) -> &Path {1277        self1278    }12791280    /// Consumes and leaks the `PathBuf`, returning a mutable reference to the contents,1281    /// `&'a mut Path`.1282    ///1283    /// The caller has free choice over the returned lifetime, including 'static.1284    /// Indeed, this function is ideally used for data that lives for the remainder of1285    /// the program's life, as dropping the returned reference will cause a memory leak.1286    ///1287    /// It does not reallocate or shrink the `PathBuf`, so the leaked allocation may include1288    /// unused capacity that is not part of the returned slice. If you want to discard excess1289    /// capacity, call [`into_boxed_path`], and then [`Box::leak`] instead.1290    /// However, keep in mind that trimming the capacity may result in a reallocation and copy.1291    ///1292    /// [`into_boxed_path`]: Self::into_boxed_path1293    #[stable(feature = "os_string_pathbuf_leak", since = "1.89.0")]1294    #[inline]1295    pub fn leak<'a>(self) -> &'a mut Path {1296        Path::from_inner_mut(self.inner.leak())1297    }12981299    /// Extends `self` with `path`.1300    ///1301    /// If `path` is absolute, it replaces the current path.1302    ///1303    /// On Windows:1304    ///1305    /// * if `path` has a root but no prefix (e.g., `\windows`), it1306    ///   replaces everything except for the prefix (if any) of `self`.1307    /// * if `path` has a prefix but no root, it replaces `self`.1308    /// * if `self` has a verbatim prefix (e.g. `\\?\C:\windows`)1309    ///   and `path` is not empty, the new path is normalized: all references1310    ///   to `.` and `..` are removed.1311    ///1312    /// Consider using [`Path::join`] if you need a new `PathBuf` instead of1313    /// using this function on a cloned `PathBuf`.1314    ///1315    /// # Examples1316    ///1317    /// Pushing a relative path extends the existing path:1318    ///1319    /// ```1320    /// use std::path::PathBuf;1321    ///1322    /// let mut path = PathBuf::from("/tmp");1323    /// path.push("file.bk");1324    /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));1325    /// ```1326    ///1327    /// Pushing an absolute path replaces the existing path:1328    ///1329    /// ```1330    /// use std::path::PathBuf;1331    ///1332    /// let mut path = PathBuf::from("/tmp");1333    /// path.push("/etc");1334    /// assert_eq!(path, PathBuf::from("/etc"));1335    /// ```1336    #[stable(feature = "rust1", since = "1.0.0")]1337    #[rustc_confusables("append", "put")]1338    pub fn push<P: AsRef<Path>>(&mut self, path: P) {1339        self._push(path.as_ref())1340    }13411342    fn _push(&mut self, path: &Path) {1343        // in general, a separator is needed if the rightmost byte is not a separator1344        let buf = self.inner.as_encoded_bytes();1345        let mut need_sep = buf.last().map(|c| !is_sep_byte(*c)).unwrap_or(false);13461347        // in the special case of `C:` on Windows, do *not* add a separator1348        let comps = self.components();13491350        if comps.prefix_len() > 01351            && comps.prefix_len() == comps.path.len()1352            && comps.prefix.unwrap().is_drive()1353        {1354            need_sep = false1355        }13561357        let need_clear = if cfg!(target_os = "cygwin") {1358            // If path is absolute and its prefix is none, it is like `/foo`,1359            // and will be handled below.1360            path.prefix().is_some()1361        } else {1362            // On Unix: prefix is always None.1363            path.is_absolute() || path.prefix().is_some()1364        };13651366        // absolute `path` replaces `self`1367        if need_clear {1368            self.inner.clear();13691370        // verbatim paths need . and .. removed1371        } else if comps.prefix_verbatim() && !path.inner.is_empty() {1372            let mut buf: Vec<_> = comps.collect();1373            for c in path.components() {1374                match c {1375                    Component::RootDir => {1376                        buf.truncate(1);1377                        buf.push(c);1378                    }1379                    Component::CurDir => (),1380                    Component::ParentDir => {1381                        if let Some(Component::Normal(_)) = buf.last() {1382                            buf.pop();1383                        }1384                    }1385                    _ => buf.push(c),1386                }1387            }13881389            let mut res = OsString::new();1390            let mut need_sep = false;13911392            for c in buf {1393                if need_sep && c != Component::RootDir {1394                    res.push(MAIN_SEPARATOR_STR);1395                }1396                res.push(c.as_os_str());13971398                need_sep = match c {1399                    Component::RootDir => false,1400                    Component::Prefix(prefix) => {1401                        !prefix.parsed.is_drive() && prefix.parsed.len() > 01402                    }1403                    _ => true,1404                }1405            }14061407            self.inner = res;1408            return;14091410        // `path` has a root but no prefix, e.g., `\windows` (Windows only)1411        } else if path.has_root() {1412            let prefix_len = self.components().prefix_remaining();1413            self.inner.truncate(prefix_len);14141415        // `path` is a pure relative path1416        } else if need_sep {1417            self.inner.push(MAIN_SEPARATOR_STR);1418        }14191420        self.inner.push(path);1421    }14221423    /// Truncates `self` to [`self.parent`].1424    ///1425    /// Returns `false` and does nothing if [`self.parent`] is [`None`].1426    /// Otherwise, returns `true`.1427    ///1428    /// [`self.parent`]: Path::parent1429    ///1430    /// # Examples1431    ///1432    /// ```1433    /// use std::path::{Path, PathBuf};1434    ///1435    /// let mut p = PathBuf::from("/spirited/away.rs");1436    ///1437    /// p.pop();1438    /// assert_eq!(Path::new("/spirited"), p);1439    /// p.pop();1440    /// assert_eq!(Path::new("/"), p);1441    /// ```1442    #[stable(feature = "rust1", since = "1.0.0")]1443    pub fn pop(&mut self) -> bool {1444        match self.parent().map(|p| p.as_u8_slice().len()) {1445            Some(len) => {1446                self.inner.truncate(len);1447                true1448            }1449            None => false,1450        }1451    }14521453    /// Sets whether the path has a trailing [separator](MAIN_SEPARATOR).1454    ///1455    /// The value returned by [`has_trailing_sep`](Path::has_trailing_sep) will be equivalent to1456    /// the provided value if possible.1457    ///1458    /// # Examples1459    ///1460    /// ```1461    /// #![feature(path_trailing_sep)]1462    /// use std::path::PathBuf;1463    ///1464    /// let mut p = PathBuf::from("dir");1465    ///1466    /// assert!(!p.has_trailing_sep());1467    /// p.set_trailing_sep(false);1468    /// assert!(!p.has_trailing_sep());1469    /// p.set_trailing_sep(true);1470    /// assert!(p.has_trailing_sep());1471    /// p.set_trailing_sep(false);1472    /// assert!(!p.has_trailing_sep());1473    ///1474    /// p = PathBuf::from("/");1475    /// assert!(p.has_trailing_sep());1476    /// p.set_trailing_sep(false);1477    /// assert!(p.has_trailing_sep());1478    /// ```1479    #[unstable(feature = "path_trailing_sep", issue = "142503")]1480    pub fn set_trailing_sep(&mut self, trailing_sep: bool) {1481        if trailing_sep { self.push_trailing_sep() } else { self.pop_trailing_sep() }1482    }14831484    /// Adds a trailing [separator](MAIN_SEPARATOR) to the path.1485    ///1486    /// This acts similarly to [`Path::with_trailing_sep`], but mutates the underlying `PathBuf`.1487    ///1488    /// # Examples1489    ///1490    /// ```1491    /// #![feature(path_trailing_sep)]1492    /// use std::ffi::OsStr;1493    /// use std::path::PathBuf;1494    ///1495    /// let mut p = PathBuf::from("dir");1496    ///1497    /// assert!(!p.has_trailing_sep());1498    /// p.push_trailing_sep();1499    /// assert!(p.has_trailing_sep());1500    /// p.push_trailing_sep();1501    /// assert!(p.has_trailing_sep());1502    ///1503    /// p = PathBuf::from("dir/");1504    /// p.push_trailing_sep();1505    /// assert_eq!(p.as_os_str(), OsStr::new("dir/"));1506    /// ```1507    #[unstable(feature = "path_trailing_sep", issue = "142503")]1508    pub fn push_trailing_sep(&mut self) {1509        if !self.has_trailing_sep() {1510            self.push("");1511        }1512    }15131514    /// Removes a trailing [separator](MAIN_SEPARATOR) from the path, if possible.1515    ///1516    /// This acts similarly to [`Path::trim_trailing_sep`], but mutates the underlying `PathBuf`.1517    ///1518    /// # Examples1519    ///1520    /// ```1521    /// #![feature(path_trailing_sep)]1522    /// use std::ffi::OsStr;1523    /// use std::path::PathBuf;1524    ///1525    /// let mut p = PathBuf::from("dir//");1526    ///1527    /// assert!(p.has_trailing_sep());1528    /// assert_eq!(p.as_os_str(), OsStr::new("dir//"));1529    /// p.pop_trailing_sep();1530    /// assert!(!p.has_trailing_sep());1531    /// assert_eq!(p.as_os_str(), OsStr::new("dir"));1532    /// p.pop_trailing_sep();1533    /// assert!(!p.has_trailing_sep());1534    /// assert_eq!(p.as_os_str(), OsStr::new("dir"));1535    ///1536    /// p = PathBuf::from("/");1537    /// assert!(p.has_trailing_sep());1538    /// p.pop_trailing_sep();1539    /// assert!(p.has_trailing_sep());1540    /// ```1541    #[unstable(feature = "path_trailing_sep", issue = "142503")]1542    pub fn pop_trailing_sep(&mut self) {1543        self.inner.truncate(self.trim_trailing_sep().as_os_str().len());1544    }15451546    /// Updates [`self.file_name`] to `file_name`.1547    ///1548    /// If [`self.file_name`] was [`None`], this is equivalent to pushing1549    /// `file_name`.1550    ///1551    /// Otherwise it is equivalent to calling [`pop`] and then pushing1552    /// `file_name`. The new path will be a sibling of the original path.1553    /// (That is, it will have the same parent.)1554    ///1555    /// The argument is not sanitized, so can include separators. This1556    /// behavior may be changed to a panic in the future.1557    ///1558    /// [`self.file_name`]: Path::file_name1559    /// [`pop`]: PathBuf::pop1560    ///1561    /// # Examples1562    ///1563    /// ```1564    /// use std::path::PathBuf;1565    ///1566    /// let mut buf = PathBuf::from("/");1567    /// assert!(buf.file_name() == None);1568    ///1569    /// buf.set_file_name("foo.txt");1570    /// assert!(buf == PathBuf::from("/foo.txt"));1571    /// assert!(buf.file_name().is_some());1572    ///1573    /// buf.set_file_name("bar.txt");1574    /// assert!(buf == PathBuf::from("/bar.txt"));1575    ///1576    /// buf.set_file_name("baz");1577    /// assert!(buf == PathBuf::from("/baz"));1578    ///1579    /// buf.set_file_name("../b/c.txt");1580    /// assert!(buf == PathBuf::from("/../b/c.txt"));1581    ///1582    /// buf.set_file_name("baz");1583    /// assert!(buf == PathBuf::from("/../b/baz"));1584    /// ```1585    #[stable(feature = "rust1", since = "1.0.0")]1586    pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {1587        self._set_file_name(file_name.as_ref())1588    }15891590    fn _set_file_name(&mut self, file_name: &OsStr) {1591        if self.file_name().is_some() {1592            let popped = self.pop();1593            debug_assert!(popped);1594        }1595        self.push(file_name);1596    }15971598    /// Updates [`self.extension`] to `Some(extension)` or to `None` if1599    /// `extension` is empty.1600    ///1601    /// Returns `false` and does nothing if [`self.file_name`] is [`None`],1602    /// returns `true` and updates the extension otherwise.1603    ///1604    /// If [`self.extension`] is [`None`], the extension is added; otherwise1605    /// it is replaced.1606    ///1607    /// If `extension` is the empty string, [`self.extension`] will be [`None`]1608    /// afterwards, not `Some("")`.1609    ///1610    /// # Panics1611    ///1612    /// Panics if the passed extension contains a path separator (see1613    /// [`is_separator`]).1614    ///1615    /// # Caveats1616    ///1617    /// The new `extension` may contain dots and will be used in its entirety,1618    /// but only the part after the final dot will be reflected in1619    /// [`self.extension`].1620    ///1621    /// If the file stem contains internal dots and `extension` is empty, part1622    /// of the old file stem will be considered the new [`self.extension`].1623    ///1624    /// See the examples below.1625    ///1626    /// [`self.file_name`]: Path::file_name1627    /// [`self.extension`]: Path::extension1628    ///1629    /// # Examples1630    ///1631    /// ```1632    /// use std::path::{Path, PathBuf};1633    ///1634    /// let mut p = PathBuf::from("/feel/the");1635    ///1636    /// p.set_extension("force");1637    /// assert_eq!(Path::new("/feel/the.force"), p.as_path());1638    ///1639    /// p.set_extension("dark.side");1640    /// assert_eq!(Path::new("/feel/the.dark.side"), p.as_path());1641    ///1642    /// p.set_extension("cookie");1643    /// assert_eq!(Path::new("/feel/the.dark.cookie"), p.as_path());1644    ///1645    /// p.set_extension("");1646    /// assert_eq!(Path::new("/feel/the.dark"), p.as_path());1647    ///1648    /// p.set_extension("");1649    /// assert_eq!(Path::new("/feel/the"), p.as_path());1650    ///1651    /// p.set_extension("");1652    /// assert_eq!(Path::new("/feel/the"), p.as_path());1653    /// ```1654    #[stable(feature = "rust1", since = "1.0.0")]1655    pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {1656        self._set_extension(extension.as_ref())1657    }16581659    fn _set_extension(&mut self, extension: &OsStr) -> bool {1660        validate_extension(extension);16611662        let file_stem = match self.file_stem() {1663            None => return false,1664            Some(f) => f.as_encoded_bytes(),1665        };16661667        // truncate until right after the file stem1668        let end_file_stem = file_stem[file_stem.len()..].as_ptr().addr();1669        let start = self.inner.as_encoded_bytes().as_ptr().addr();1670        self.inner.truncate(end_file_stem.wrapping_sub(start));16711672        // add the new extension, if any1673        let new = extension.as_encoded_bytes();1674        if !new.is_empty() {1675            self.inner.reserve_exact(new.len() + 1);1676            self.inner.push(".");1677            // SAFETY: Since a UTF-8 string was just pushed, it is not possible1678            // for the buffer to end with a surrogate half.1679            unsafe { self.inner.extend_from_slice_unchecked(new) };1680        }16811682        true1683    }16841685    /// Append [`self.extension`] with `extension`.1686    ///1687    /// Returns `false` and does nothing if [`self.file_name`] is [`None`],1688    /// returns `true` and updates the extension otherwise.1689    ///1690    /// # Panics1691    ///1692    /// Panics if the passed extension contains a path separator (see1693    /// [`is_separator`]).1694    ///1695    /// # Caveats1696    ///1697    /// The appended `extension` may contain dots and will be used in its entirety,1698    /// but only the part after the final dot will be reflected in1699    /// [`self.extension`].1700    ///1701    /// See the examples below.1702    ///1703    /// [`self.file_name`]: Path::file_name1704    /// [`self.extension`]: Path::extension1705    ///1706    /// # Examples1707    ///1708    /// ```1709    /// use std::path::{Path, PathBuf};1710    ///1711    /// let mut p = PathBuf::from("/feel/the");1712    ///1713    /// p.add_extension("formatted");1714    /// assert_eq!(Path::new("/feel/the.formatted"), p.as_path());1715    ///1716    /// p.add_extension("dark.side");1717    /// assert_eq!(Path::new("/feel/the.formatted.dark.side"), p.as_path());1718    ///1719    /// p.set_extension("cookie");1720    /// assert_eq!(Path::new("/feel/the.formatted.dark.cookie"), p.as_path());1721    ///1722    /// p.set_extension("");1723    /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());1724    ///1725    /// p.add_extension("");1726    /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());1727    /// ```1728    #[stable(feature = "path_add_extension", since = "1.91.0")]1729    pub fn add_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {1730        self._add_extension(extension.as_ref())1731    }17321733    fn _add_extension(&mut self, extension: &OsStr) -> bool {1734        validate_extension(extension);17351736        let file_name = match self.file_name() {1737            None => return false,1738            Some(f) => f.as_encoded_bytes(),1739        };17401741        let new = extension.as_encoded_bytes();1742        if !new.is_empty() {1743            // truncate until right after the file name1744            // this is necessary for trimming the trailing separator1745            let end_file_name = file_name[file_name.len()..].as_ptr().addr();1746            let start = self.inner.as_encoded_bytes().as_ptr().addr();1747            self.inner.truncate(end_file_name.wrapping_sub(start));17481749            // append the new extension1750            self.inner.reserve_exact(new.len() + 1);1751            self.inner.push(".");1752            // SAFETY: Since a UTF-8 string was just pushed, it is not possible1753            // for the buffer to end with a surrogate half.1754            unsafe { self.inner.extend_from_slice_unchecked(new) };1755        }17561757        true1758    }17591760    /// Yields a mutable reference to the underlying [`OsString`] instance.1761    ///1762    /// # Examples1763    ///1764    /// ```1765    /// use std::path::{Path, PathBuf};1766    ///1767    /// let mut path = PathBuf::from("/foo");1768    ///1769    /// path.push("bar");1770    /// assert_eq!(path, Path::new("/foo/bar"));1771    ///1772    /// // OsString's `push` does not add a separator.1773    /// path.as_mut_os_string().push("baz");1774    /// assert_eq!(path, Path::new("/foo/barbaz"));1775    /// ```1776    #[stable(feature = "path_as_mut_os_str", since = "1.70.0")]1777    #[must_use]1778    #[inline]1779    pub fn as_mut_os_string(&mut self) -> &mut OsString {1780        &mut self.inner1781    }17821783    /// Consumes the `PathBuf`, yielding its internal [`OsString`] storage.1784    ///1785    /// # Examples1786    ///1787    /// ```1788    /// use std::path::PathBuf;1789    ///1790    /// let p = PathBuf::from("/the/head");1791    /// let os_str = p.into_os_string();1792    /// ```1793    #[stable(feature = "rust1", since = "1.0.0")]1794    #[must_use = "`self` will be dropped if the result is not used"]1795    #[inline]1796    pub fn into_os_string(self) -> OsString {1797        self.inner1798    }17991800    /// Converts the `PathBuf` into a `String` if it contains valid Unicode data.1801    ///1802    /// On failure, ownership of the original `PathBuf` is returned.1803    ///1804    /// # Examples1805    ///1806    /// ```1807    /// use std::path::PathBuf;1808    ///1809    /// let path_buf = PathBuf::from("foo");1810    /// let string = path_buf.into_string();1811    /// assert_eq!(string, Ok(String::from("foo")));1812    /// ```1813    #[stable(feature = "pathbuf_into_string", since = "1.98.0")]1814    pub fn into_string(self) -> Result<String, PathBuf> {1815        self.into_os_string().into_string().map_err(PathBuf::from)1816    }18171818    /// Converts this `PathBuf` into a [boxed](Box) [`Path`].1819    #[stable(feature = "into_boxed_path", since = "1.20.0")]1820    #[must_use = "`self` will be dropped if the result is not used"]1821    #[inline]1822    pub fn into_boxed_path(self) -> Box<Path> {1823        let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;1824        unsafe { Box::from_raw(rw) }1825    }18261827    /// Invokes [`capacity`] on the underlying instance of [`OsString`].1828    ///1829    /// [`capacity`]: OsString::capacity1830    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1831    #[must_use]1832    #[inline]1833    pub fn capacity(&self) -> usize {1834        self.inner.capacity()1835    }18361837    /// Invokes [`clear`] on the underlying instance of [`OsString`].1838    ///1839    /// [`clear`]: OsString::clear1840    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1841    #[inline]1842    pub fn clear(&mut self) {1843        self.inner.clear()1844    }18451846    /// Invokes [`reserve`] on the underlying instance of [`OsString`].1847    ///1848    /// [`reserve`]: OsString::reserve1849    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1850    #[inline]1851    pub fn reserve(&mut self, additional: usize) {1852        self.inner.reserve(additional)1853    }18541855    /// Invokes [`try_reserve`] on the underlying instance of [`OsString`].1856    ///1857    /// [`try_reserve`]: OsString::try_reserve1858    #[stable(feature = "try_reserve_2", since = "1.63.0")]1859    #[inline]1860    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {1861        self.inner.try_reserve(additional)1862    }18631864    /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].1865    ///1866    /// [`reserve_exact`]: OsString::reserve_exact1867    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1868    #[inline]1869    pub fn reserve_exact(&mut self, additional: usize) {1870        self.inner.reserve_exact(additional)1871    }18721873    /// Invokes [`try_reserve_exact`] on the underlying instance of [`OsString`].1874    ///1875    /// [`try_reserve_exact`]: OsString::try_reserve_exact1876    #[stable(feature = "try_reserve_2", since = "1.63.0")]1877    #[inline]1878    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {1879        self.inner.try_reserve_exact(additional)1880    }18811882    /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].1883    ///1884    /// [`shrink_to_fit`]: OsString::shrink_to_fit1885    #[stable(feature = "path_buf_capacity", since = "1.44.0")]1886    #[inline]1887    pub fn shrink_to_fit(&mut self) {1888        self.inner.shrink_to_fit()1889    }18901891    /// Invokes [`shrink_to`] on the underlying instance of [`OsString`].1892    ///1893    /// [`shrink_to`]: OsString::shrink_to1894    #[stable(feature = "shrink_to", since = "1.56.0")]1895    #[inline]1896    pub fn shrink_to(&mut self, min_capacity: usize) {1897        self.inner.shrink_to(min_capacity)1898    }1899}19001901#[stable(feature = "rust1", since = "1.0.0")]1902impl Clone for PathBuf {1903    #[inline]1904    fn clone(&self) -> Self {1905        PathBuf { inner: self.inner.clone() }1906    }19071908    /// Clones the contents of `source` into `self`.1909    ///1910    /// This method is preferred over simply assigning `source.clone()` to `self`,1911    /// as it avoids reallocation if possible.1912    #[inline]1913    fn clone_from(&mut self, source: &Self) {1914        self.inner.clone_from(&source.inner)1915    }1916}19171918#[stable(feature = "box_from_path", since = "1.17.0")]1919impl From<&Path> for Box<Path> {1920    /// Creates a boxed [`Path`] from a reference.1921    ///1922    /// This will allocate and clone `path` to it.1923    fn from(path: &Path) -> Box<Path> {1924        Box::clone_from_ref(path)1925    }1926}19271928#[stable(feature = "box_from_mut_slice", since = "1.84.0")]1929impl From<&mut Path> for Box<Path> {1930    /// Creates a boxed [`Path`] from a reference.1931    ///1932    /// This will allocate and clone `path` to it.1933    fn from(path: &mut Path) -> Box<Path> {1934        Self::from(&*path)1935    }1936}19371938#[stable(feature = "box_from_cow", since = "1.45.0")]1939impl From<Cow<'_, Path>> for Box<Path> {1940    /// Creates a boxed [`Path`] from a clone-on-write pointer.1941    ///1942    /// Converting from a `Cow::Owned` does not clone or allocate.1943    #[inline]1944    fn from(cow: Cow<'_, Path>) -> Box<Path> {1945        match cow {1946            Cow::Borrowed(path) => Box::from(path),1947            Cow::Owned(path) => Box::from(path),1948        }1949    }1950}19511952#[stable(feature = "path_buf_from_box", since = "1.18.0")]1953impl From<Box<Path>> for PathBuf {1954    /// Converts a <code>[Box]&lt;[Path]&gt;</code> into a [`PathBuf`].1955    ///1956    /// This conversion does not allocate or copy memory.1957    #[inline]1958    fn from(boxed: Box<Path>) -> PathBuf {1959        boxed.into_path_buf()1960    }1961}19621963#[stable(feature = "box_from_path_buf", since = "1.20.0")]1964impl From<PathBuf> for Box<Path> {1965    /// Converts a [`PathBuf`] into a <code>[Box]&lt;[Path]&gt;</code>.1966    ///1967    /// This conversion currently should not allocate memory,1968    /// but this behavior is not guaranteed on all platforms or in all future versions.1969    #[inline]1970    fn from(p: PathBuf) -> Box<Path> {1971        p.into_boxed_path()1972    }1973}19741975#[stable(feature = "more_box_slice_clone", since = "1.29.0")]1976impl<A: Allocator + Clone> Clone for Box<Path, A> {1977    #[inline]1978    fn clone(&self) -> Self {1979        Box::clone_from_ref_in(&**self, Self::allocator(self).clone())1980    }1981}19821983#[stable(feature = "rust1", since = "1.0.0")]1984impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {1985    /// Converts a borrowed [`OsStr`] to a [`PathBuf`].1986    ///1987    /// Allocates a [`PathBuf`] and copies the data into it.1988    #[inline]1989    fn from(s: &T) -> PathBuf {1990        PathBuf::from(s.as_ref().to_os_string())1991    }1992}19931994#[stable(feature = "rust1", since = "1.0.0")]1995impl From<OsString> for PathBuf {1996    /// Converts an [`OsString`] into a [`PathBuf`].1997    ///1998    /// This conversion does not allocate or copy memory.1999    #[inline]2000    fn from(s: OsString) -> PathBuf {

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.

Generated by searchcode.com · powered by code_get_file + code_get_findings