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