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