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]<[Path]></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]<[Path]></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.