unix_path/
lib.rs

1//! Unix path manipulation.
2//!
3//! This crate provides two types, [`PathBuf`] and [`Path`] (akin to `String`
4//! and `str`), for working with paths abstractly. These types are thin wrappers
5//! around `UnixString` and `UnixStr` respectively, meaning that they work
6//! directly on strings independently from 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 (`/`). 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//! ## Simple usage
16//!
17//! Path manipulation includes both parsing components from slices and building
18//! new owned paths.
19//!
20//! To parse a path, you can create a [`Path`] slice from a `str`
21//! slice and start asking questions:
22//!
23//! ```
24//! use unix_path::Path;
25//! use unix_str::UnixStr;
26//!
27//! let path = Path::new("/tmp/foo/bar.txt");
28//!
29//! let parent = path.parent();
30//! assert_eq!(parent, Some(Path::new("/tmp/foo")));
31//!
32//! let file_stem = path.file_stem();
33//! assert_eq!(file_stem, Some(UnixStr::new("bar")));
34//!
35//! let extension = path.extension();
36//! assert_eq!(extension, Some(UnixStr::new("txt")));
37//! ```
38//!
39//! To build or modify paths, use [`PathBuf`]:
40//!
41//! ```
42//! use unix_path::PathBuf;
43//!
44//! // This way works...
45//! let mut path = PathBuf::from("/");
46//!
47//! path.push("feel");
48//! path.push("the");
49//!
50//! path.set_extension("force");
51//!
52//! // ... but push is best used if you don't know everything up
53//! // front. If you do, this way is better:
54//! let path: PathBuf = ["/", "feel", "the.force"].iter().collect();
55//! ```
56//!
57//! [`Component`]: enum.Component.html
58//! [`components`]:struct.Path.html#method.components
59//! [`PathBuf`]: struct.PathBuf.html
60//! [`Path`]: struct.Path.html
61//! [`push`]: struct.PathBuf.html#method.push
62
63#![cfg_attr(not(feature = "std"), no_std)]
64#![cfg_attr(feature = "shrink_to", feature(shrink_to))]
65
66#[cfg(feature = "alloc")]
67extern crate alloc;
68
69use unix_str::UnixStr;
70#[cfg(feature = "alloc")]
71use unix_str::UnixString;
72
73#[cfg(feature = "alloc")]
74use core::borrow::Borrow;
75use core::cmp;
76use core::fmt;
77use core::hash::{Hash, Hasher};
78#[cfg(feature = "alloc")]
79use core::iter;
80use core::iter::FusedIterator;
81#[cfg(feature = "alloc")]
82use core::ops::{self, Deref};
83
84#[cfg(feature = "alloc")]
85use alloc::{
86    borrow::{Cow, ToOwned},
87    boxed::Box,
88    rc::Rc,
89    str::FromStr,
90    string::String,
91    sync::Arc,
92    vec::Vec,
93};
94
95#[cfg(feature = "std")]
96use std::error::Error;
97
98mod lossy;
99
100////////////////////////////////////////////////////////////////////////////////
101// Exposed parsing helpers
102////////////////////////////////////////////////////////////////////////////////
103
104/// Determines whether the character is the permitted path separator for Unix,
105/// `/`.
106///
107/// # Examples
108///
109/// ```
110/// assert!(unix_path::is_separator('/'));
111/// assert!(!unix_path::is_separator('❤'));
112/// ```
113pub fn is_separator(c: char) -> bool {
114    c == '/'
115}
116
117/// The separator of path components for Unix, `/`.
118pub const MAIN_SEPARATOR: char = '/';
119
120////////////////////////////////////////////////////////////////////////////////
121// Misc helpers
122////////////////////////////////////////////////////////////////////////////////
123
124// Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
125// is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
126// `iter` after having exhausted `prefix`.
127fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
128where
129    I: Iterator<Item = Component<'a>> + Clone,
130    J: Iterator<Item = Component<'b>>,
131{
132    loop {
133        let mut iter_next = iter.clone();
134        match (iter_next.next(), prefix.next()) {
135            (Some(ref x), Some(ref y)) if x == y => (),
136            (Some(_), Some(_)) => return None,
137            (Some(_), None) => return Some(iter),
138            (None, None) => return Some(iter),
139            (None, Some(_)) => return None,
140        }
141        iter = iter_next;
142    }
143}
144
145fn unix_str_as_u8_slice(s: &UnixStr) -> &[u8] {
146    unsafe { &*(s as *const UnixStr as *const [u8]) }
147}
148unsafe fn u8_slice_as_unix_str(s: &[u8]) -> &UnixStr {
149    &*(s as *const [u8] as *const UnixStr)
150}
151
152////////////////////////////////////////////////////////////////////////////////
153// Cross-platform, iterator-independent parsing
154////////////////////////////////////////////////////////////////////////////////
155
156/// Says whether the first byte after the prefix is a separator.
157fn has_physical_root(path: &[u8]) -> bool {
158    !path.is_empty() && path[0] == b'/'
159}
160
161// basic workhorse for splitting stem and extension
162fn split_file_at_dot(file: &UnixStr) -> (Option<&UnixStr>, Option<&UnixStr>) {
163    unsafe {
164        if unix_str_as_u8_slice(file) == b".." {
165            return (Some(file), None);
166        }
167
168        // The unsafety here stems from converting between &OsStr and &[u8]
169        // and back. This is safe to do because (1) we only look at ASCII
170        // contents of the encoding and (2) new &OsStr values are produced
171        // only from ASCII-bounded slices of existing &OsStr values.
172
173        let mut iter = unix_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
174        let after = iter.next();
175        let before = iter.next();
176        if before == Some(b"") {
177            (Some(file), None)
178        } else {
179            (
180                before.map(|s| u8_slice_as_unix_str(s)),
181                after.map(|s| u8_slice_as_unix_str(s)),
182            )
183        }
184    }
185}
186
187////////////////////////////////////////////////////////////////////////////////
188// The core iterators
189////////////////////////////////////////////////////////////////////////////////
190
191/// Component parsing works by a double-ended state machine; the cursors at the
192/// front and back of the path each keep track of what parts of the path have
193/// been consumed so far.
194///
195/// Going front to back, a path is made up of a prefix, a starting
196/// directory component, and a body (of normal components)
197#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
198enum State {
199    Prefix = 0,
200    StartDir = 1, // / or . or nothing
201    Body = 2,     // foo/bar/baz
202    Done = 3,
203}
204
205/// A single component of a path.
206///
207/// A `Component` roughly corresponds to a substring between path separators
208/// (`/`).
209///
210/// This `enum` is created by iterating over [`Components`], which in turn is
211/// created by the [`components`][`Path::components`] method on [`Path`].
212///
213/// # Examples
214///
215/// ```rust
216/// use unix_path::{Component, Path};
217///
218/// let path = Path::new("/tmp/foo/bar.txt");
219/// let components = path.components().collect::<Vec<_>>();
220/// assert_eq!(&components, &[
221///     Component::RootDir,
222///     Component::Normal("tmp".as_ref()),
223///     Component::Normal("foo".as_ref()),
224///     Component::Normal("bar.txt".as_ref()),
225/// ]);
226/// ```
227///
228/// [`Components`]: struct.Components.html
229/// [`Path`]: struct.Path.html
230/// [`Path::components`]: struct.Path.html#method.components
231#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
232pub enum Component<'a> {
233    /// The root directory component, appears after any prefix and before anything else.
234    ///
235    /// It represents a separator that designates that a path starts from root.
236    RootDir,
237
238    /// A reference to the current directory, i.e., `.`.
239    CurDir,
240
241    /// A reference to the parent directory, i.e., `..`.
242    ParentDir,
243
244    /// A normal component, e.g., `a` and `b` in `a/b`.
245    ///
246    /// This variant is the most common one, it represents references to files
247    /// or directories.
248    Normal(&'a UnixStr),
249}
250
251impl<'a> Component<'a> {
252    /// Extracts the underlying `UnixStr` slice.
253    ///
254    /// # Examples
255    ///
256    /// ```
257    /// use unix_path::Path;
258    ///
259    /// let path = Path::new("./tmp/foo/bar.txt");
260    /// let components: Vec<_> = path.components().map(|comp| comp.as_unix_str()).collect();
261    /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
262    /// ```
263    pub fn as_unix_str(self) -> &'a UnixStr {
264        match self {
265            Component::RootDir => UnixStr::new("/"),
266            Component::CurDir => UnixStr::new("."),
267            Component::ParentDir => UnixStr::new(".."),
268            Component::Normal(path) => path,
269        }
270    }
271}
272
273impl AsRef<UnixStr> for Component<'_> {
274    fn as_ref(&self) -> &UnixStr {
275        self.as_unix_str()
276    }
277}
278
279impl AsRef<Path> for Component<'_> {
280    fn as_ref(&self) -> &Path {
281        self.as_unix_str().as_ref()
282    }
283}
284
285/// An iterator over the [`Component`]s of a [`Path`].
286///
287/// This `struct` is created by the [`components`] method on [`Path`].
288/// See its documentation for more.
289///
290/// # Examples
291///
292/// ```
293/// use unix_path::Path;
294///
295/// let path = Path::new("/tmp/foo/bar.txt");
296///
297/// for component in path.components() {
298///     println!("{:?}", component);
299/// }
300/// ```
301///
302/// [`Component`]: enum.Component.html
303/// [`components`]: struct.Path.html#method.components
304/// [`Path`]: struct.Path.html
305#[derive(Clone)]
306pub struct Components<'a> {
307    // The path left to parse components from
308    path: &'a [u8],
309
310    // true if path *physically* has a root separator;.
311    has_physical_root: bool,
312
313    // The iterator is double-ended, and these two states keep track of what has
314    // been produced from either end
315    front: State,
316    back: State,
317}
318
319/// An iterator over the [`Component`]s of a [`Path`], as `UnixStr` slices.
320///
321/// This `struct` is created by the [`iter`] method on [`Path`].
322/// See its documentation for more.
323///
324/// [`Component`]: enum.Component.html
325/// [`iter`]: struct.Path.html#method.iter
326/// [`Path`]: struct.Path.html
327#[derive(Clone)]
328pub struct Iter<'a> {
329    inner: Components<'a>,
330}
331
332impl fmt::Debug for Components<'_> {
333    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334        struct DebugHelper<'a>(&'a Path);
335
336        impl fmt::Debug for DebugHelper<'_> {
337            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338                f.debug_list().entries(self.0.components()).finish()
339            }
340        }
341
342        f.debug_tuple("Components")
343            .field(&DebugHelper(self.as_path()))
344            .finish()
345    }
346}
347
348impl<'a> Components<'a> {
349    // Given the iteration so far, how much of the pre-State::Body path is left?
350    #[inline]
351    fn len_before_body(&self) -> usize {
352        let root = if self.front <= State::StartDir && self.has_physical_root {
353            1
354        } else {
355            0
356        };
357        let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() {
358            1
359        } else {
360            0
361        };
362        root + cur_dir
363    }
364
365    // is the iteration complete?
366    #[inline]
367    fn finished(&self) -> bool {
368        self.front == State::Done || self.back == State::Done || self.front > self.back
369    }
370
371    #[inline]
372    fn is_sep_byte(&self, b: u8) -> bool {
373        b == b'/'
374    }
375
376    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
377    ///
378    /// # Examples
379    ///
380    /// ```
381    /// use unix_path::Path;
382    ///
383    /// let mut components = Path::new("/tmp/foo/bar.txt").components();
384    /// components.next();
385    /// components.next();
386    ///
387    /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());
388    /// ```
389    pub fn as_path(&self) -> &'a Path {
390        let mut comps = self.clone();
391        if comps.front == State::Body {
392            comps.trim_left();
393        }
394        if comps.back == State::Body {
395            comps.trim_right();
396        }
397        unsafe { Path::from_u8_slice(comps.path) }
398    }
399
400    /// Is the *original* path rooted?
401    fn has_root(&self) -> bool {
402        self.has_physical_root
403    }
404
405    /// Should the normalized path include a leading . ?
406    fn include_cur_dir(&self) -> bool {
407        if self.has_root() {
408            return false;
409        }
410        let mut iter = self.path[..].iter();
411        match (iter.next(), iter.next()) {
412            (Some(&b'.'), None) => true,
413            (Some(&b'.'), Some(&b)) => self.is_sep_byte(b),
414            _ => false,
415        }
416    }
417
418    // parse a given byte sequence into the corresponding path component
419    fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
420        match comp {
421            b"." => None, // . components are normalized away, except at
422            // the beginning of a path, which is treated
423            // separately via `include_cur_dir`
424            b".." => Some(Component::ParentDir),
425            b"" => None,
426            _ => Some(Component::Normal(unsafe { u8_slice_as_unix_str(comp) })),
427        }
428    }
429
430    // parse a component from the left, saying how many bytes to consume to
431    // remove the component
432    fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {
433        debug_assert!(self.front == State::Body);
434        let (extra, comp) = match self.path.iter().position(|b| self.is_sep_byte(*b)) {
435            None => (0, self.path),
436            Some(i) => (1, &self.path[..i]),
437        };
438        (comp.len() + extra, self.parse_single_component(comp))
439    }
440
441    // parse a component from the right, saying how many bytes to consume to
442    // remove the component
443    fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {
444        debug_assert!(self.back == State::Body);
445        let start = self.len_before_body();
446        let (extra, comp) = match self.path[start..]
447            .iter()
448            .rposition(|b| self.is_sep_byte(*b))
449        {
450            None => (0, &self.path[start..]),
451            Some(i) => (1, &self.path[start + i + 1..]),
452        };
453        (comp.len() + extra, self.parse_single_component(comp))
454    }
455
456    // trim away repeated separators (i.e., empty components) on the left
457    fn trim_left(&mut self) {
458        while !self.path.is_empty() {
459            let (size, comp) = self.parse_next_component();
460            if comp.is_some() {
461                return;
462            } else {
463                self.path = &self.path[size..];
464            }
465        }
466    }
467
468    // trim away repeated separators (i.e., empty components) on the right
469    fn trim_right(&mut self) {
470        while self.path.len() > self.len_before_body() {
471            let (size, comp) = self.parse_next_component_back();
472            if comp.is_some() {
473                return;
474            } else {
475                self.path = &self.path[..self.path.len() - size];
476            }
477        }
478    }
479}
480
481impl AsRef<Path> for Components<'_> {
482    fn as_ref(&self) -> &Path {
483        self.as_path()
484    }
485}
486
487impl AsRef<UnixStr> for Components<'_> {
488    fn as_ref(&self) -> &UnixStr {
489        self.as_path().as_unix_str()
490    }
491}
492
493impl fmt::Debug for Iter<'_> {
494    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
495        struct DebugHelper<'a>(&'a Path);
496
497        impl fmt::Debug for DebugHelper<'_> {
498            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
499                f.debug_list().entries(self.0.iter()).finish()
500            }
501        }
502
503        f.debug_tuple("Iter")
504            .field(&DebugHelper(self.as_path()))
505            .finish()
506    }
507}
508
509impl<'a> Iter<'a> {
510    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
511    ///
512    /// # Examples
513    ///
514    /// ```
515    /// use unix_path::Path;
516    ///
517    /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();
518    /// iter.next();
519    /// iter.next();
520    ///
521    /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());
522    /// ```
523    pub fn as_path(&self) -> &'a Path {
524        self.inner.as_path()
525    }
526}
527
528impl AsRef<Path> for Iter<'_> {
529    fn as_ref(&self) -> &Path {
530        self.as_path()
531    }
532}
533
534impl AsRef<UnixStr> for Iter<'_> {
535    fn as_ref(&self) -> &UnixStr {
536        self.as_path().as_unix_str()
537    }
538}
539
540impl<'a> Iterator for Iter<'a> {
541    type Item = &'a UnixStr;
542
543    fn next(&mut self) -> Option<Self::Item> {
544        self.inner.next().map(Component::as_unix_str)
545    }
546}
547
548impl<'a> DoubleEndedIterator for Iter<'a> {
549    fn next_back(&mut self) -> Option<Self::Item> {
550        self.inner.next_back().map(Component::as_unix_str)
551    }
552}
553
554impl FusedIterator for Iter<'_> {}
555
556impl<'a> Iterator for Components<'a> {
557    type Item = Component<'a>;
558
559    fn next(&mut self) -> Option<Component<'a>> {
560        while !self.finished() {
561            match self.front {
562                State::Prefix => {
563                    self.front = State::StartDir;
564                }
565                State::StartDir => {
566                    self.front = State::Body;
567                    if self.has_physical_root {
568                        debug_assert!(!self.path.is_empty());
569                        self.path = &self.path[1..];
570                        return Some(Component::RootDir);
571                    } else if self.include_cur_dir() {
572                        debug_assert!(!self.path.is_empty());
573                        self.path = &self.path[1..];
574                        return Some(Component::CurDir);
575                    }
576                }
577                State::Body if !self.path.is_empty() => {
578                    let (size, comp) = self.parse_next_component();
579                    self.path = &self.path[size..];
580                    if comp.is_some() {
581                        return comp;
582                    }
583                }
584                State::Body => {
585                    self.front = State::Done;
586                }
587                State::Done => unreachable!(),
588            }
589        }
590        None
591    }
592}
593
594impl<'a> DoubleEndedIterator for Components<'a> {
595    fn next_back(&mut self) -> Option<Component<'a>> {
596        while !self.finished() {
597            match self.back {
598                State::Body if self.path.len() > self.len_before_body() => {
599                    let (size, comp) = self.parse_next_component_back();
600                    self.path = &self.path[..self.path.len() - size];
601                    if comp.is_some() {
602                        return comp;
603                    }
604                }
605                State::Body => {
606                    self.back = State::StartDir;
607                }
608                State::StartDir => {
609                    self.back = State::Prefix;
610                    if self.has_physical_root {
611                        self.path = &self.path[..self.path.len() - 1];
612                        return Some(Component::RootDir);
613                    } else if self.include_cur_dir() {
614                        self.path = &self.path[..self.path.len() - 1];
615                        return Some(Component::CurDir);
616                    }
617                }
618                State::Prefix => {
619                    self.back = State::Done;
620                    return None;
621                }
622                State::Done => unreachable!(),
623            }
624        }
625        None
626    }
627}
628
629impl FusedIterator for Components<'_> {}
630
631impl<'a> cmp::PartialEq for Components<'a> {
632    fn eq(&self, other: &Components<'a>) -> bool {
633        Iterator::eq(self.clone(), other.clone())
634    }
635}
636
637impl cmp::Eq for Components<'_> {}
638
639impl<'a> cmp::PartialOrd for Components<'a> {
640    fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
641        Iterator::partial_cmp(self.clone(), other.clone())
642    }
643}
644
645impl cmp::Ord for Components<'_> {
646    fn cmp(&self, other: &Self) -> cmp::Ordering {
647        Iterator::cmp(self.clone(), other.clone())
648    }
649}
650
651/// An iterator over [`Path`] and its ancestors.
652///
653/// This `struct` is created by the [`ancestors`] method on [`Path`].
654/// See its documentation for more.
655///
656/// # Examples
657///
658/// ```
659/// use unix_path::Path;
660///
661/// let path = Path::new("/foo/bar");
662///
663/// for ancestor in path.ancestors() {
664///     println!("{:?}", ancestor);
665/// }
666/// ```
667///
668/// [`ancestors`]: struct.Path.html#method.ancestors
669/// [`Path`]: struct.Path.html
670#[derive(Copy, Clone, Debug)]
671pub struct Ancestors<'a> {
672    next: Option<&'a Path>,
673}
674
675impl<'a> Iterator for Ancestors<'a> {
676    type Item = &'a Path;
677
678    fn next(&mut self) -> Option<Self::Item> {
679        let next = self.next;
680        self.next = next.and_then(Path::parent);
681        next
682    }
683}
684
685impl FusedIterator for Ancestors<'_> {}
686
687////////////////////////////////////////////////////////////////////////////////
688// Basic types and traits
689////////////////////////////////////////////////////////////////////////////////
690
691/// An owned, mutable path (akin to `String`).
692///
693/// This type provides methods like [`push`] and [`set_extension`] that mutate
694/// the path in place. It also implements `Deref` to [`Path`], meaning that
695/// all methods on [`Path`] slices are available on `PathBuf` values as well.
696///
697/// [`Path`]: struct.Path.html
698/// [`push`]: struct.PathBuf.html#method.push
699/// [`set_extension`]: struct.PathBuf.html#method.set_extension
700///
701/// More details about the overall approach can be found in
702/// the [crate documentation](index.html).
703///
704/// # Examples
705///
706/// You can use [`push`] to build up a `PathBuf` from
707/// components:
708///
709/// ```
710/// use unix_path::PathBuf;
711///
712/// let mut path = PathBuf::new();
713///
714/// path.push("/");
715/// path.push("feel");
716/// path.push("the");
717///
718/// path.set_extension("force");
719/// ```
720///
721/// However, [`push`] is best used for dynamic situations. This is a better way
722/// to do this when you know all of the components ahead of time:
723///
724/// ```
725/// use unix_path::PathBuf;
726///
727/// let path: PathBuf = ["/", "feel", "the.force"].iter().collect();
728/// ```
729///
730/// We can still do better than this! Since these are all strings, we can use
731/// `From::from`:
732///
733/// ```
734/// use unix_path::PathBuf;
735///
736/// let path = PathBuf::from(r"/feel/the.force");
737/// ```
738///
739/// Which method works best depends on what kind of situation you're in.
740#[derive(Clone)]
741#[cfg(feature = "alloc")]
742pub struct PathBuf {
743    inner: UnixString,
744}
745
746#[cfg(feature = "alloc")]
747impl PathBuf {
748    fn as_mut_vec(&mut self) -> &mut Vec<u8> {
749        unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
750    }
751
752    /// Allocates an empty `PathBuf`.
753    ///
754    /// # Examples
755    ///
756    /// ```
757    /// use unix_path::PathBuf;
758    ///
759    /// let path = PathBuf::new();
760    /// ```
761    pub fn new() -> PathBuf {
762        PathBuf {
763            inner: UnixString::new(),
764        }
765    }
766
767    /// Creates a new `PathBuf` with a given capacity used to create the
768    /// internal `UnixString`. See `with_capacity` defined on `UnixString`.
769    ///
770    /// # Examples
771    ///
772    /// ```
773    /// use unix_path::PathBuf;
774    ///
775    /// let mut path = PathBuf::with_capacity(10);
776    /// let capacity = path.capacity();
777    ///
778    /// // This push is done without reallocating
779    /// path.push("/");
780    ///
781    /// assert_eq!(capacity, path.capacity());
782    /// ```
783    pub fn with_capacity(capacity: usize) -> PathBuf {
784        PathBuf {
785            inner: UnixString::with_capacity(capacity),
786        }
787    }
788
789    /// Coerces to a [`Path`] slice.
790    ///
791    /// [`Path`]: struct.Path.html
792    ///
793    /// # Examples
794    ///
795    /// ```
796    /// use unix_path::{Path, PathBuf};
797    ///
798    /// let p = PathBuf::from("/test");
799    /// assert_eq!(Path::new("/test"), p.as_path());
800    /// ```
801    pub fn as_path(&self) -> &Path {
802        self
803    }
804
805    /// Extends `self` with `path`.
806    ///
807    /// If `path` is absolute, it replaces the current path.
808    ///
809    /// # Examples
810    ///
811    /// Pushing a relative path extends the existing path:
812    ///
813    /// ```
814    /// use unix_path::PathBuf;
815    ///
816    /// let mut path = PathBuf::from("/tmp");
817    /// path.push("file.bk");
818    /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
819    /// ```
820    ///
821    /// Pushing an absolute path replaces the existing path:
822    ///
823    /// ```
824    /// use unix_path::PathBuf;
825    ///
826    /// let mut path = PathBuf::from("/tmp");
827    /// path.push("/etc");
828    /// assert_eq!(path, PathBuf::from("/etc"));
829    /// ```
830    pub fn push<P: AsRef<Path>>(&mut self, path: P) {
831        self._push(path.as_ref())
832    }
833
834    fn _push(&mut self, path: &Path) {
835        // in general, a separator is needed if the rightmost byte is not a separator
836        let need_sep = self
837            .as_mut_vec()
838            .last()
839            .map(|c| *c != b'/')
840            .unwrap_or(false);
841
842        // absolute `path` replaces `self`
843        if path.is_absolute() || path.has_root() {
844            self.as_mut_vec().truncate(0);
845        } else if need_sep {
846            self.inner.push("/");
847        }
848
849        self.inner.push(path.as_unix_str());
850    }
851
852    /// Truncates `self` to [`self.parent`].
853    ///
854    /// Returns `false` and does nothing if [`self.parent`] is `None`.
855    /// Otherwise, returns `true`.
856    ///
857    /// [`self.parent`]: struct.PathBuf.html#method.parent
858    ///
859    /// # Examples
860    ///
861    /// ```
862    /// use unix_path::{Path, PathBuf};
863    ///
864    /// let mut p = PathBuf::from("/test/test.rs");
865    ///
866    /// p.pop();
867    /// assert_eq!(Path::new("/test"), p);
868    /// p.pop();
869    /// assert_eq!(Path::new("/"), p);
870    /// ```
871    pub fn pop(&mut self) -> bool {
872        match self.parent().map(|p| p.as_unix_str().len()) {
873            Some(len) => {
874                self.as_mut_vec().truncate(len);
875                true
876            }
877            None => false,
878        }
879    }
880
881    /// Updates [`self.file_name`] to `file_name`.
882    ///
883    /// If [`self.file_name`] was `None`, this is equivalent to pushing
884    /// `file_name`.
885    ///
886    /// Otherwise it is equivalent to calling [`pop`] and then pushing
887    /// `file_name`. The new path will be a sibling of the original path.
888    /// (That is, it will have the same parent.)
889    ///
890    /// [`self.file_name`]: struct.PathBuf.html#method.file_name
891    /// [`pop`]: struct.PathBuf.html#method.pop
892    ///
893    /// # Examples
894    ///
895    /// ```
896    /// use unix_path::PathBuf;
897    ///
898    /// let mut buf = PathBuf::from("/");
899    /// assert!(buf.file_name() == None);
900    /// buf.set_file_name("bar");
901    /// assert!(buf == PathBuf::from("/bar"));
902    /// assert!(buf.file_name().is_some());
903    /// buf.set_file_name("baz.txt");
904    /// assert!(buf == PathBuf::from("/baz.txt"));
905    /// ```
906    pub fn set_file_name<S: AsRef<UnixStr>>(&mut self, file_name: S) {
907        self._set_file_name(file_name.as_ref())
908    }
909
910    fn _set_file_name(&mut self, file_name: &UnixStr) {
911        if self.file_name().is_some() {
912            let popped = self.pop();
913            debug_assert!(popped);
914        }
915        self.push(file_name);
916    }
917
918    /// Updates [`self.extension`] to `extension`.
919    ///
920    /// Returns `false` and does nothing if [`self.file_name`] is `None`,
921    /// returns `true` and updates the extension otherwise.
922    ///
923    /// If [`self.extension`] is `None`, the extension is added; otherwise
924    /// it is replaced.
925    ///
926    /// [`self.file_name`]: struct.PathBuf.html#method.file_name
927    /// [`self.extension`]: struct.PathBuf.html#method.extension
928    ///
929    /// # Examples
930    ///
931    /// ```
932    /// use unix_path::{Path, PathBuf};
933    ///
934    /// let mut p = PathBuf::from("/feel/the");
935    ///
936    /// p.set_extension("force");
937    /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
938    ///
939    /// p.set_extension("dark_side");
940    /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path());
941    /// ```
942
943    pub fn set_extension<S: AsRef<UnixStr>>(&mut self, extension: S) -> bool {
944        self._set_extension(extension.as_ref())
945    }
946
947    fn _set_extension(&mut self, extension: &UnixStr) -> bool {
948        let file_stem = match self.file_stem() {
949            None => return false,
950            Some(f) => unix_str_as_u8_slice(f),
951        };
952
953        // truncate until right after the file stem
954        let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
955        let start = unix_str_as_u8_slice(&self.inner).as_ptr() as usize;
956        let v = self.as_mut_vec();
957        v.truncate(end_file_stem.wrapping_sub(start));
958
959        // add the new extension, if any
960        let new = unix_str_as_u8_slice(extension);
961        if !new.is_empty() {
962            v.reserve_exact(new.len() + 1);
963            v.push(b'.');
964            v.extend_from_slice(new);
965        }
966
967        true
968    }
969
970    /// Consumes the `PathBuf`, yielding its internal `UnixString` storage.
971    ///
972    /// # Examples
973    ///
974    /// ```
975    /// use unix_path::PathBuf;
976    ///
977    /// let p = PathBuf::from("/the/head");
978    /// let bytes = p.into_unix_string();
979    /// ```
980    pub fn into_unix_string(self) -> UnixString {
981        self.inner
982    }
983
984    /// Converts this `PathBuf` into a boxed [`Path`].
985    ///
986    /// [`Path`]: struct.Path.html
987    pub fn into_boxed_path(self) -> Box<Path> {
988        let rw = Box::into_raw(self.inner.into_boxed_unix_str()) as *mut Path;
989        unsafe { Box::from_raw(rw) }
990    }
991
992    /// Invokes `capacity` on the underlying instance of `UnixString`.
993    pub fn capacity(&self) -> usize {
994        self.inner.capacity()
995    }
996
997    /// Invokes `clear` on the underlying instance of `UnixString`.
998    pub fn clear(&mut self) {
999        self.inner.clear()
1000    }
1001
1002    /// Invokes `reserve` on the underlying instance of `UnixString`.
1003    pub fn reserve(&mut self, additional: usize) {
1004        self.inner.reserve(additional)
1005    }
1006
1007    /// Invokes `reserve_exact` on the underlying instance of `UnixString`.
1008    pub fn reserve_exact(&mut self, additional: usize) {
1009        self.inner.reserve_exact(additional)
1010    }
1011
1012    /// Invokes `shrink_to_fit` on the underlying instance of `UnixString`.
1013    pub fn shrink_to_fit(&mut self) {
1014        self.inner.shrink_to_fit()
1015    }
1016
1017    /// Invokes `shrink_to` on the underlying instance of `UnixString`.
1018    #[cfg(feature = "shrink_to")]
1019    pub fn shrink_to(&mut self, min_capacity: usize) {
1020        self.inner.shrink_to(min_capacity)
1021    }
1022}
1023
1024#[cfg(feature = "alloc")]
1025impl From<&Path> for Box<Path> {
1026    fn from(path: &Path) -> Box<Path> {
1027        let boxed: Box<UnixStr> = path.inner.into();
1028        let rw = Box::into_raw(boxed) as *mut Path;
1029        unsafe { Box::from_raw(rw) }
1030    }
1031}
1032
1033#[cfg(feature = "alloc")]
1034impl From<Cow<'_, Path>> for Box<Path> {
1035    #[inline]
1036    fn from(cow: Cow<'_, Path>) -> Box<Path> {
1037        match cow {
1038            Cow::Borrowed(path) => Box::from(path),
1039            Cow::Owned(path) => Box::from(path),
1040        }
1041    }
1042}
1043
1044#[cfg(feature = "alloc")]
1045impl From<Box<Path>> for PathBuf {
1046    /// Converts a `Box<Path>` into a `PathBuf`
1047    ///
1048    /// This conversion does not allocate or copy memory.
1049    fn from(boxed: Box<Path>) -> PathBuf {
1050        boxed.into_path_buf()
1051    }
1052}
1053
1054#[cfg(feature = "alloc")]
1055impl From<PathBuf> for Box<Path> {
1056    /// Converts a `PathBuf` into a `Box<Path>`
1057    ///
1058    /// This conversion currently should not allocate memory,
1059    /// but this behavior is not guaranteed in all future versions.
1060    fn from(p: PathBuf) -> Self {
1061        p.into_boxed_path()
1062    }
1063}
1064
1065#[cfg(feature = "alloc")]
1066impl Clone for Box<Path> {
1067    #[inline]
1068    fn clone(&self) -> Self {
1069        self.to_path_buf().into_boxed_path()
1070    }
1071}
1072
1073#[cfg(feature = "alloc")]
1074impl<T: ?Sized + AsRef<UnixStr>> From<&T> for PathBuf {
1075    fn from(s: &T) -> Self {
1076        PathBuf::from(s.as_ref().to_unix_string())
1077    }
1078}
1079
1080#[cfg(feature = "alloc")]
1081impl From<UnixString> for PathBuf {
1082    /// Converts a `UnixString` into a `PathBuf`
1083    ///
1084    /// This conversion does not allocate or copy memory.
1085    #[inline]
1086    fn from(s: UnixString) -> Self {
1087        PathBuf { inner: s }
1088    }
1089}
1090
1091#[cfg(feature = "alloc")]
1092impl From<PathBuf> for UnixString {
1093    /// Converts a `PathBuf` into a `UnixString`
1094    ///
1095    /// This conversion does not allocate or copy memory.
1096    fn from(path_buf: PathBuf) -> Self {
1097        path_buf.inner
1098    }
1099}
1100
1101#[cfg(feature = "alloc")]
1102impl From<String> for PathBuf {
1103    /// Converts a `String` into a `PathBuf`
1104    ///
1105    /// This conversion does not allocate or copy memory.
1106    fn from(s: String) -> PathBuf {
1107        PathBuf::from(UnixString::from(s))
1108    }
1109}
1110
1111#[cfg(feature = "alloc")]
1112impl FromStr for PathBuf {
1113    type Err = core::convert::Infallible;
1114
1115    fn from_str(s: &str) -> Result<Self, Self::Err> {
1116        Ok(PathBuf::from(s))
1117    }
1118}
1119
1120#[cfg(feature = "alloc")]
1121impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
1122    fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
1123        let mut buf = PathBuf::new();
1124        buf.extend(iter);
1125        buf
1126    }
1127}
1128
1129#[cfg(feature = "alloc")]
1130impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
1131    fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
1132        iter.into_iter().for_each(move |p| self.push(p.as_ref()));
1133    }
1134}
1135
1136#[cfg(feature = "alloc")]
1137impl fmt::Debug for PathBuf {
1138    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1139        fmt::Debug::fmt(&**self, formatter)
1140    }
1141}
1142
1143#[cfg(feature = "alloc")]
1144impl ops::Deref for PathBuf {
1145    type Target = Path;
1146    #[inline]
1147    fn deref(&self) -> &Path {
1148        Path::new(&self.inner)
1149    }
1150}
1151
1152#[cfg(feature = "alloc")]
1153impl Borrow<Path> for PathBuf {
1154    fn borrow(&self) -> &Path {
1155        self.deref()
1156    }
1157}
1158
1159#[cfg(feature = "alloc")]
1160impl Default for PathBuf {
1161    fn default() -> Self {
1162        PathBuf::new()
1163    }
1164}
1165
1166#[cfg(feature = "alloc")]
1167impl<'a> From<&'a Path> for Cow<'a, Path> {
1168    #[inline]
1169    fn from(s: &'a Path) -> Cow<'a, Path> {
1170        Cow::Borrowed(s)
1171    }
1172}
1173
1174#[cfg(feature = "alloc")]
1175impl<'a> From<PathBuf> for Cow<'a, Path> {
1176    #[inline]
1177    fn from(s: PathBuf) -> Cow<'a, Path> {
1178        Cow::Owned(s)
1179    }
1180}
1181
1182#[cfg(feature = "alloc")]
1183impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
1184    #[inline]
1185    fn from(p: &'a PathBuf) -> Cow<'a, Path> {
1186        Cow::Borrowed(p.as_path())
1187    }
1188}
1189
1190#[cfg(feature = "alloc")]
1191impl<'a> From<Cow<'a, Path>> for PathBuf {
1192    #[inline]
1193    fn from(p: Cow<'a, Path>) -> Self {
1194        p.into_owned()
1195    }
1196}
1197
1198#[cfg(feature = "alloc")]
1199impl From<PathBuf> for Arc<Path> {
1200    /// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer.
1201    #[inline]
1202    fn from(s: PathBuf) -> Arc<Path> {
1203        let arc: Arc<UnixStr> = Arc::from(s.into_unix_string());
1204        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1205    }
1206}
1207
1208#[cfg(feature = "alloc")]
1209impl From<&Path> for Arc<Path> {
1210    /// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer.
1211    #[inline]
1212    fn from(s: &Path) -> Arc<Path> {
1213        let arc: Arc<UnixStr> = Arc::from(s.as_unix_str());
1214        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1215    }
1216}
1217
1218#[cfg(feature = "alloc")]
1219impl From<PathBuf> for Rc<Path> {
1220    /// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer.
1221    #[inline]
1222    fn from(s: PathBuf) -> Rc<Path> {
1223        let rc: Rc<UnixStr> = Rc::from(s.into_unix_string());
1224        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1225    }
1226}
1227
1228#[cfg(feature = "alloc")]
1229impl From<&Path> for Rc<Path> {
1230    /// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer.
1231    #[inline]
1232    fn from(s: &Path) -> Rc<Path> {
1233        let rc: Rc<UnixStr> = Rc::from(s.as_unix_str());
1234        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1235    }
1236}
1237
1238#[cfg(feature = "alloc")]
1239impl ToOwned for Path {
1240    type Owned = PathBuf;
1241    fn to_owned(&self) -> PathBuf {
1242        self.to_path_buf()
1243    }
1244}
1245
1246#[cfg(feature = "alloc")]
1247impl cmp::PartialEq for PathBuf {
1248    fn eq(&self, other: &PathBuf) -> bool {
1249        self.components() == other.components()
1250    }
1251}
1252
1253#[cfg(feature = "alloc")]
1254impl Hash for PathBuf {
1255    fn hash<H: Hasher>(&self, h: &mut H) {
1256        self.as_path().hash(h)
1257    }
1258}
1259
1260#[cfg(feature = "alloc")]
1261impl cmp::Eq for PathBuf {}
1262
1263#[cfg(feature = "alloc")]
1264impl cmp::PartialOrd for PathBuf {
1265    fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
1266        self.components().partial_cmp(other.components())
1267    }
1268}
1269
1270#[cfg(feature = "alloc")]
1271impl cmp::Ord for PathBuf {
1272    fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
1273        self.components().cmp(other.components())
1274    }
1275}
1276
1277#[cfg(feature = "alloc")]
1278impl AsRef<UnixStr> for PathBuf {
1279    fn as_ref(&self) -> &UnixStr {
1280        &self.inner[..]
1281    }
1282}
1283
1284/// A slice of a path (akin to `str`).
1285///
1286/// This type supports a number of operations for inspecting a path, including
1287/// breaking the path into its components (separated by `/` ), extracting the
1288/// file name, determining whether the path is absolute, and so on.
1289///
1290/// This is an *unsized* type, meaning that it must always be used behind a
1291/// pointer like `&` or `Box`. For an owned version of this type,
1292/// see [`PathBuf`].
1293///
1294/// [`PathBuf`]: struct.PathBuf.html
1295///
1296/// More details about the overall approach can be found in
1297/// the [crate documentation](index.html).
1298///
1299/// # Examples
1300///
1301/// ```
1302/// use unix_path::Path;
1303/// use unix_str::UnixStr;
1304///
1305/// let path = Path::new("./foo/bar.txt");
1306///
1307/// let parent = path.parent();
1308/// assert_eq!(parent, Some(Path::new("./foo")));
1309///
1310/// let file_stem = path.file_stem();
1311/// assert_eq!(file_stem, Some(UnixStr::new("bar")));
1312///
1313/// let extension = path.extension();
1314/// assert_eq!(extension, Some(UnixStr::new("txt")));
1315/// ```
1316pub struct Path {
1317    inner: UnixStr,
1318}
1319
1320/// An error returned from [`Path::strip_prefix`][`strip_prefix`] if the prefix
1321/// was not found.
1322///
1323/// This `struct` is created by the [`strip_prefix`] method on [`Path`].
1324/// See its documentation for more.
1325///
1326/// [`strip_prefix`]: struct.Path.html#method.strip_prefix
1327/// [`Path`]: struct.Path.html
1328#[derive(Debug, Clone, PartialEq, Eq)]
1329pub struct StripPrefixError(());
1330
1331impl Path {
1332    // The following (private!) function allows construction of a path from a u8
1333    // slice, which is only safe when it is known to follow the OsStr encoding.
1334    unsafe fn from_u8_slice(s: &[u8]) -> &Path {
1335        Path::new(u8_slice_as_unix_str(s))
1336    }
1337    // The following (private!) function reveals the byte encoding used for OsStr.
1338    fn as_u8_slice(&self) -> &[u8] {
1339        unix_str_as_u8_slice(&self.inner)
1340    }
1341
1342    /// Directly wraps a string slice as a `Path` slice.
1343    ///
1344    /// This is a cost-free conversion.
1345    ///
1346    /// # Examples
1347    ///
1348    /// ```
1349    /// use unix_path::Path;
1350    ///
1351    /// Path::new("foo.txt");
1352    /// ```
1353    ///
1354    /// You can create `Path`s from `String`s, or even other `Path`s:
1355    ///
1356    /// ```
1357    /// use unix_path::Path;
1358    ///
1359    /// let string = String::from("foo.txt");
1360    /// let from_string = Path::new(&string);
1361    /// let from_path = Path::new(&from_string);
1362    /// assert_eq!(from_string, from_path);
1363    /// ```
1364    pub fn new<S: AsRef<UnixStr> + ?Sized>(s: &S) -> &Path {
1365        unsafe { &*(s.as_ref() as *const UnixStr as *const Path) }
1366    }
1367
1368    /// Yields the underlying bytes.
1369    ///
1370    /// # Examples
1371    ///
1372    /// ```
1373    /// use unix_path::Path;
1374    /// use unix_str::UnixStr;
1375    ///
1376    /// let os_str = Path::new("foo.txt").as_unix_str();
1377    /// assert_eq!(os_str, UnixStr::new("foo.txt"));
1378    /// ```
1379    pub fn as_unix_str(&self) -> &UnixStr {
1380        &self.inner
1381    }
1382
1383    /// Yields a `&str` slice if the `Path` is valid unicode.
1384    ///
1385    /// This conversion may entail doing a check for UTF-8 validity.
1386    /// Note that validation is performed because non-UTF-8 strings are
1387    /// perfectly valid for some OS.
1388    ///
1389    /// # Examples
1390    ///
1391    /// ```
1392    /// use unix_path::Path;
1393    ///
1394    /// let path = Path::new("foo.txt");
1395    /// assert_eq!(path.to_str(), Some("foo.txt"));
1396    /// ```
1397    pub fn to_str(&self) -> Option<&str> {
1398        self.inner.to_str()
1399    }
1400
1401    /// Converts a `Path` to a `Cow<str>`.
1402    ///
1403    /// Any non-Unicode sequences are replaced with
1404    /// `U+FFFD REPLACEMENT CHARACTER`.
1405    ///
1406    ///
1407    /// # Examples
1408    ///
1409    /// Calling `to_string_lossy` on a `Path` with valid unicode:
1410    ///
1411    /// ```
1412    /// use unix_path::Path;
1413    ///
1414    /// let path = Path::new("foo.txt");
1415    /// assert_eq!(path.to_string_lossy(), "foo.txt");
1416    /// ```
1417    ///
1418    /// Had `path` contained invalid unicode, the `to_string_lossy` call might
1419    /// have returned `"fo�.txt"`.
1420    #[cfg(feature = "alloc")]
1421    pub fn to_string_lossy(&self) -> Cow<'_, str> {
1422        self.inner.to_string_lossy()
1423    }
1424
1425    /// Converts a `Path` to an owned [`PathBuf`].
1426    ///
1427    /// [`PathBuf`]: struct.PathBuf.html
1428    ///
1429    /// # Examples
1430    ///
1431    /// ```
1432    /// use unix_path::Path;
1433    ///
1434    /// let path_buf = Path::new("foo.txt").to_path_buf();
1435    /// assert_eq!(path_buf, unix_path::PathBuf::from("foo.txt"));
1436    /// ```
1437    #[cfg(feature = "alloc")]
1438    pub fn to_path_buf(&self) -> PathBuf {
1439        PathBuf::from(&self.inner)
1440    }
1441
1442    /// Returns `true` if the `Path` is absolute, i.e., if it is independent of
1443    /// the current directory.
1444    ///
1445    /// A path is absolute if it starts with the root, so `is_absolute` and
1446    /// [`has_root`] are equivalent.
1447    ///
1448    /// # Examples
1449    ///
1450    /// ```
1451    /// use unix_path::Path;
1452    ///
1453    /// assert!(!Path::new("foo.txt").is_absolute());
1454    /// ```
1455    ///
1456    /// [`has_root`]: #method.has_root
1457    pub fn is_absolute(&self) -> bool {
1458        self.has_root()
1459    }
1460
1461    /// Returns `true` if the `Path` is relative, i.e., not absolute.
1462    ///
1463    /// See [`is_absolute`]'s documentation for more details.
1464    ///
1465    /// # Examples
1466    ///
1467    /// ```
1468    /// use unix_path::Path;
1469    ///
1470    /// assert!(Path::new("foo.txt").is_relative());
1471    /// ```
1472    ///
1473    /// [`is_absolute`]: #method.is_absolute
1474    pub fn is_relative(&self) -> bool {
1475        !self.is_absolute()
1476    }
1477
1478    /// Returns `true` if the `Path` has a root.
1479    ///
1480    /// A path has a root if it begins with `/`.
1481    ///
1482    /// # Examples
1483    ///
1484    /// ```
1485    /// use unix_path::Path;
1486    ///
1487    /// assert!(Path::new("/etc/passwd").has_root());
1488    /// ```
1489    pub fn has_root(&self) -> bool {
1490        self.components().has_root()
1491    }
1492
1493    /// Returns the `Path` without its final component, if there is one.
1494    ///
1495    /// Returns `None` if the path terminates in a root or prefix.
1496    ///
1497    /// # Examples
1498    ///
1499    /// ```
1500    /// use unix_path::Path;
1501    ///
1502    /// let path = Path::new("/foo/bar");
1503    /// let parent = path.parent().unwrap();
1504    /// assert_eq!(parent, Path::new("/foo"));
1505    ///
1506    /// let grand_parent = parent.parent().unwrap();
1507    /// assert_eq!(grand_parent, Path::new("/"));
1508    /// assert_eq!(grand_parent.parent(), None);
1509    /// ```
1510    pub fn parent(&self) -> Option<&Path> {
1511        let mut comps = self.components();
1512        let comp = comps.next_back();
1513        comp.and_then(|p| match p {
1514            Component::Normal(_) | Component::CurDir | Component::ParentDir => {
1515                Some(comps.as_path())
1516            }
1517            _ => None,
1518        })
1519    }
1520
1521    /// Produces an iterator over `Path` and its ancestors.
1522    ///
1523    /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
1524    /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
1525    /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
1526    /// `None`, the iterator will do likewise. The iterator will always yield at least one value,
1527    /// namely `&self`.
1528    ///
1529    /// # Examples
1530    ///
1531    /// ```
1532    /// use unix_path::Path;
1533    ///
1534    /// let mut ancestors = Path::new("/foo/bar").ancestors();
1535    /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
1536    /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
1537    /// assert_eq!(ancestors.next(), Some(Path::new("/")));
1538    /// assert_eq!(ancestors.next(), None);
1539    /// ```
1540    ///
1541    /// [`parent`]: struct.Path.html#method.parent
1542    pub fn ancestors(&self) -> Ancestors<'_> {
1543        Ancestors { next: Some(&self) }
1544    }
1545
1546    /// Returns the final component of the `Path`, if there is one.
1547    ///
1548    /// If the path is a normal file, this is the file name. If it's the path of a directory, this
1549    /// is the directory name.
1550    ///
1551    /// Returns `None` if the path terminates in `..`.
1552    ///
1553    /// # Examples
1554    ///
1555    /// ```
1556    /// use unix_path::Path;
1557    /// use unix_str::UnixStr;
1558    ///
1559    /// assert_eq!(Some(UnixStr::new("bin")), Path::new("/usr/bin/").file_name());
1560    /// assert_eq!(Some(UnixStr::new("foo.txt")), Path::new("tmp/foo.txt").file_name());
1561    /// assert_eq!(Some(UnixStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
1562    /// assert_eq!(Some(UnixStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
1563    /// assert_eq!(None, Path::new("foo.txt/..").file_name());
1564    /// assert_eq!(None, Path::new("/").file_name());
1565    /// ```
1566    pub fn file_name(&self) -> Option<&UnixStr> {
1567        self.components().next_back().and_then(|p| match p {
1568            Component::Normal(p) => Some(p),
1569            _ => None,
1570        })
1571    }
1572
1573    /// Returns a path that, when joined onto `base`, yields `self`.
1574    ///
1575    /// # Errors
1576    ///
1577    /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
1578    /// returns `false`), returns `Err`.
1579    ///
1580    /// [`starts_with`]: #method.starts_with
1581    ///
1582    /// # Examples
1583    ///
1584    /// ```
1585    /// use unix_path::{Path, PathBuf};
1586    ///
1587    /// let path = Path::new("/test/haha/foo.txt");
1588    ///
1589    /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
1590    /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
1591    /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
1592    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
1593    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
1594    /// assert_eq!(path.strip_prefix("test").is_ok(), false);
1595    /// assert_eq!(path.strip_prefix("/haha").is_ok(), false);
1596    ///
1597    /// let prefix = PathBuf::from("/test/");
1598    /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
1599    /// ```
1600    pub fn strip_prefix<P>(&self, base: P) -> Result<&Path, StripPrefixError>
1601    where
1602        P: AsRef<Path>,
1603    {
1604        self._strip_prefix(base.as_ref())
1605    }
1606
1607    fn _strip_prefix(&self, base: &Path) -> Result<&Path, StripPrefixError> {
1608        iter_after(self.components(), base.components())
1609            .map(|c| c.as_path())
1610            .ok_or(StripPrefixError(()))
1611    }
1612
1613    /// Determines whether `base` is a prefix of `self`.
1614    ///
1615    /// Only considers whole path components to match.
1616    ///
1617    /// # Examples
1618    ///
1619    /// ```
1620    /// use unix_path::Path;
1621    ///
1622    /// let path = Path::new("/etc/passwd");
1623    ///
1624    /// assert!(path.starts_with("/etc"));
1625    /// assert!(path.starts_with("/etc/"));
1626    /// assert!(path.starts_with("/etc/passwd"));
1627    /// assert!(path.starts_with("/etc/passwd/"));
1628    ///
1629    /// assert!(!path.starts_with("/e"));
1630    /// ```
1631    pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
1632        self._starts_with(base.as_ref())
1633    }
1634
1635    fn _starts_with(&self, base: &Path) -> bool {
1636        iter_after(self.components(), base.components()).is_some()
1637    }
1638
1639    /// Determines whether `child` is a suffix of `self`.
1640    ///
1641    /// Only considers whole path components to match.
1642    ///
1643    /// # Examples
1644    ///
1645    /// ```
1646    /// use unix_path::Path;
1647    ///
1648    /// let path = Path::new("/etc/passwd");
1649    ///
1650    /// assert!(path.ends_with("passwd"));
1651    /// ```
1652    pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
1653        self._ends_with(child.as_ref())
1654    }
1655
1656    fn _ends_with(&self, child: &Path) -> bool {
1657        iter_after(self.components().rev(), child.components().rev()).is_some()
1658    }
1659
1660    /// Extracts the stem (non-extension) portion of [`self.file_name`].
1661    ///
1662    /// [`self.file_name`]: struct.Path.html#method.file_name
1663    ///
1664    /// The stem is:
1665    ///
1666    /// * `None`, if there is no file name;
1667    /// * The entire file name if there is no embedded `.`;
1668    /// * The entire file name if the file name begins with `.` and has no other `.`s within;
1669    /// * Otherwise, the portion of the file name before the final `.`
1670    ///
1671    /// # Examples
1672    ///
1673    /// ```
1674    /// use unix_path::Path;
1675    ///
1676    /// let path = Path::new("foo.rs");
1677    ///
1678    /// assert_eq!("foo", path.file_stem().unwrap());
1679    /// ```
1680    pub fn file_stem(&self) -> Option<&UnixStr> {
1681        self.file_name()
1682            .map(split_file_at_dot)
1683            .and_then(|(before, after)| before.or(after))
1684    }
1685
1686    /// Extracts the extension of [`self.file_name`], if possible.
1687    ///
1688    /// The extension is:
1689    ///
1690    /// * `None`, if there is no file name;
1691    /// * `None`, if there is no embedded `.`;
1692    /// * `None`, if the file name begins with `.` and has no other `.`s within;
1693    /// * Otherwise, the portion of the file name after the final `.`
1694    ///
1695    /// [`self.file_name`]: struct.Path.html#method.file_name
1696    ///
1697    /// # Examples
1698    ///
1699    /// ```
1700    /// use unix_path::Path;
1701    /// use unix_str::UnixStr;
1702    ///
1703    /// let path = Path::new("foo.rs");
1704    ///
1705    /// assert_eq!(UnixStr::new("rs"), path.extension().unwrap());
1706    /// ```
1707    pub fn extension(&self) -> Option<&UnixStr> {
1708        self.file_name()
1709            .map(split_file_at_dot)
1710            .and_then(|(before, after)| before.and(after))
1711    }
1712
1713    /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
1714    ///
1715    /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
1716    ///
1717    /// [`PathBuf`]: struct.PathBuf.html
1718    /// [`PathBuf::push`]: struct.PathBuf.html#method.push
1719    ///
1720    /// # Examples
1721    ///
1722    /// ```
1723    /// use unix_path::{Path, PathBuf};
1724    ///
1725    /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
1726    /// ```
1727    #[must_use]
1728    #[cfg(feature = "alloc")]
1729    pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
1730        self._join(path.as_ref())
1731    }
1732
1733    #[cfg(feature = "alloc")]
1734    fn _join(&self, path: &Path) -> PathBuf {
1735        let mut buf = self.to_path_buf();
1736        buf.push(path);
1737        buf
1738    }
1739
1740    /// Creates an owned [`PathBuf`] like `self` but with the given file name.
1741    ///
1742    /// See [`PathBuf::set_file_name`] for more details.
1743    ///
1744    /// [`PathBuf`]: struct.PathBuf.html
1745    /// [`PathBuf::set_file_name`]: struct.PathBuf.html#method.set_file_name
1746    ///
1747    /// # Examples
1748    ///
1749    /// ```
1750    /// use unix_path::{Path, PathBuf};
1751    ///
1752    /// let path = Path::new("/tmp/foo.txt");
1753    /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
1754    ///
1755    /// let path = Path::new("/tmp");
1756    /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
1757    /// ```
1758    #[cfg(feature = "alloc")]
1759    pub fn with_file_name<S: AsRef<UnixStr>>(&self, file_name: S) -> PathBuf {
1760        self._with_file_name(file_name.as_ref())
1761    }
1762
1763    #[cfg(feature = "alloc")]
1764    fn _with_file_name(&self, file_name: &UnixStr) -> PathBuf {
1765        let mut buf = self.to_path_buf();
1766        buf.set_file_name(file_name);
1767        buf
1768    }
1769
1770    /// Creates an owned [`PathBuf`] like `self` but with the given extension.
1771    ///
1772    /// See [`PathBuf::set_extension`] for more details.
1773    ///
1774    /// [`PathBuf`]: struct.PathBuf.html
1775    /// [`PathBuf::set_extension`]: struct.PathBuf.html#method.set_extension
1776    ///
1777    /// # Examples
1778    ///
1779    /// ```
1780    /// use unix_path::{Path, PathBuf};
1781    ///
1782    /// let path = Path::new("foo.rs");
1783    /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
1784    /// ```
1785    #[cfg(feature = "alloc")]
1786    pub fn with_extension<S: AsRef<UnixStr>>(&self, extension: S) -> PathBuf {
1787        self._with_extension(extension.as_ref())
1788    }
1789
1790    #[cfg(feature = "alloc")]
1791    fn _with_extension(&self, extension: &UnixStr) -> PathBuf {
1792        let mut buf = self.to_path_buf();
1793        buf.set_extension(extension);
1794        buf
1795    }
1796
1797    /// Produces an iterator over the [`Component`]s of the path.
1798    ///
1799    /// When parsing the path, there is a small amount of normalization:
1800    ///
1801    /// * Repeated separators are ignored, so `a/b` and `a//b` both have
1802    ///   `a` and `b` as components.
1803    ///
1804    /// * Occurrences of `.` are normalized away, except if they are at the
1805    ///   beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
1806    ///   `a/b` all have `a` and `b` as components, but `./a/b` starts with
1807    ///   an additional [`CurDir`] component.
1808    ///
1809    /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
1810    ///
1811    /// Note that no other normalization takes place; in particular, `a/c`
1812    /// and `a/b/../c` are distinct, to account for the possibility that `b`
1813    /// is a symbolic link (so its parent isn't `a`).
1814    ///
1815    /// # Examples
1816    ///
1817    /// ```
1818    /// use unix_path::{Path, Component};
1819    /// use unix_str::UnixStr;
1820    ///
1821    /// let mut components = Path::new("/tmp/foo.txt").components();
1822    ///
1823    /// assert_eq!(components.next(), Some(Component::RootDir));
1824    /// assert_eq!(components.next(), Some(Component::Normal(UnixStr::new("tmp"))));
1825    /// assert_eq!(components.next(), Some(Component::Normal(UnixStr::new("foo.txt"))));
1826    /// assert_eq!(components.next(), None)
1827    /// ```
1828    ///
1829    /// [`Component`]: enum.Component.html
1830    /// [`CurDir`]: enum.Component.html#variant.CurDir
1831    pub fn components(&self) -> Components<'_> {
1832        Components {
1833            path: self.as_u8_slice(),
1834            has_physical_root: has_physical_root(self.as_u8_slice()),
1835            front: State::Prefix,
1836            back: State::Body,
1837        }
1838    }
1839
1840    /// Produces an iterator over the path's components viewed as `UnixStr`
1841    /// slices.
1842    ///
1843    /// For more information about the particulars of how the path is separated
1844    /// into components, see [`components`].
1845    ///
1846    /// [`components`]: #method.components
1847    ///
1848    /// # Examples
1849    ///
1850    /// ```
1851    /// use unix_path::{self, Path};
1852    /// use unix_str::UnixStr;
1853    ///
1854    /// let mut it = Path::new("/tmp/foo.txt").iter();
1855    /// assert_eq!(it.next(), Some(UnixStr::new("/")));
1856    /// assert_eq!(it.next(), Some(UnixStr::new("tmp")));
1857    /// assert_eq!(it.next(), Some(UnixStr::new("foo.txt")));
1858    /// assert_eq!(it.next(), None)
1859    /// ```
1860    pub fn iter(&self) -> Iter<'_> {
1861        Iter {
1862            inner: self.components(),
1863        }
1864    }
1865
1866    /// Converts a `Box<Path>` into a [`PathBuf`] without copying or
1867    /// allocating.
1868    ///
1869    /// [`PathBuf`]: struct.PathBuf.html
1870    #[cfg(feature = "alloc")]
1871    pub fn into_path_buf(self: Box<Path>) -> PathBuf {
1872        let rw = Box::into_raw(self) as *mut UnixStr;
1873        let inner = unsafe { Box::from_raw(rw) };
1874        PathBuf {
1875            inner: UnixString::from(inner),
1876        }
1877    }
1878
1879    /// Returns a newtype that implements Display for safely printing paths
1880    /// that may contain non-Unicode data.
1881    pub fn display(&self) -> Display<'_> {
1882        Display { path: self }
1883    }
1884}
1885
1886impl AsRef<UnixStr> for Path {
1887    fn as_ref(&self) -> &UnixStr {
1888        &self.inner
1889    }
1890}
1891
1892impl fmt::Debug for Path {
1893    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1894        fmt::Debug::fmt(&self.inner, formatter)
1895    }
1896}
1897
1898impl cmp::PartialEq for Path {
1899    fn eq(&self, other: &Path) -> bool {
1900        self.components().eq(other.components())
1901    }
1902}
1903
1904impl Hash for Path {
1905    fn hash<H: Hasher>(&self, h: &mut H) {
1906        for component in self.components() {
1907            component.hash(h);
1908        }
1909    }
1910}
1911
1912impl cmp::Eq for Path {}
1913
1914impl cmp::PartialOrd for Path {
1915    fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
1916        self.components().partial_cmp(other.components())
1917    }
1918}
1919
1920impl cmp::Ord for Path {
1921    fn cmp(&self, other: &Path) -> cmp::Ordering {
1922        self.components().cmp(other.components())
1923    }
1924}
1925
1926impl AsRef<Path> for Path {
1927    fn as_ref(&self) -> &Path {
1928        self
1929    }
1930}
1931
1932impl AsRef<Path> for UnixStr {
1933    fn as_ref(&self) -> &Path {
1934        Path::new(self)
1935    }
1936}
1937
1938#[cfg(feature = "alloc")]
1939impl AsRef<Path> for Cow<'_, UnixStr> {
1940    fn as_ref(&self) -> &Path {
1941        Path::new(self)
1942    }
1943}
1944
1945#[cfg(feature = "alloc")]
1946impl AsRef<Path> for UnixString {
1947    fn as_ref(&self) -> &Path {
1948        Path::new(self)
1949    }
1950}
1951
1952impl AsRef<Path> for str {
1953    #[inline]
1954    fn as_ref(&self) -> &Path {
1955        Path::new(self)
1956    }
1957}
1958
1959#[cfg(feature = "alloc")]
1960impl AsRef<Path> for String {
1961    fn as_ref(&self) -> &Path {
1962        Path::new(self)
1963    }
1964}
1965
1966#[cfg(feature = "alloc")]
1967impl AsRef<Path> for PathBuf {
1968    #[inline]
1969    fn as_ref(&self) -> &Path {
1970        self
1971    }
1972}
1973
1974#[cfg(feature = "alloc")]
1975impl<'a> IntoIterator for &'a PathBuf {
1976    type Item = &'a UnixStr;
1977    type IntoIter = Iter<'a>;
1978    fn into_iter(self) -> Iter<'a> {
1979        self.iter()
1980    }
1981}
1982
1983impl<'a> IntoIterator for &'a Path {
1984    type Item = &'a UnixStr;
1985    type IntoIter = Iter<'a>;
1986    fn into_iter(self) -> Iter<'a> {
1987        self.iter()
1988    }
1989}
1990
1991#[cfg(feature = "serde")]
1992use serde::{
1993    de::{self, Deserialize, Deserializer, Unexpected, Visitor},
1994    ser::{self, Serialize, Serializer},
1995};
1996
1997#[cfg(feature = "serde")]
1998impl Serialize for Path {
1999    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2000    where
2001        S: Serializer,
2002    {
2003        match self.to_str() {
2004            Some(s) => s.serialize(serializer),
2005            None => Err(ser::Error::custom("path contains invalid UTF-8 characters")),
2006        }
2007    }
2008}
2009
2010#[cfg(feature = "serde")]
2011impl Serialize for PathBuf {
2012    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2013    where
2014        S: Serializer,
2015    {
2016        self.as_path().serialize(serializer)
2017    }
2018}
2019
2020#[cfg(feature = "serde")]
2021struct PathVisitor;
2022
2023#[cfg(feature = "serde")]
2024impl<'a> Visitor<'a> for PathVisitor {
2025    type Value = &'a Path;
2026
2027    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2028        formatter.write_str("a borrowed path")
2029    }
2030
2031    fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
2032    where
2033        E: de::Error,
2034    {
2035        Ok(v.as_ref())
2036    }
2037
2038    fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
2039    where
2040        E: de::Error,
2041    {
2042        core::str::from_utf8(v)
2043            .map(AsRef::as_ref)
2044            .map_err(|_| de::Error::invalid_value(Unexpected::Bytes(v), &self))
2045    }
2046}
2047
2048#[cfg(feature = "serde")]
2049impl<'de: 'a, 'a> Deserialize<'de> for &'a Path {
2050    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2051    where
2052        D: Deserializer<'de>,
2053    {
2054        deserializer.deserialize_str(PathVisitor)
2055    }
2056}
2057
2058#[cfg(feature = "serde")]
2059struct PathBufVisitor;
2060
2061#[cfg(feature = "serde")]
2062impl<'de> Visitor<'de> for PathBufVisitor {
2063    type Value = PathBuf;
2064
2065    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2066        formatter.write_str("path string")
2067    }
2068
2069    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
2070    where
2071        E: de::Error,
2072    {
2073        Ok(From::from(v))
2074    }
2075
2076    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
2077    where
2078        E: de::Error,
2079    {
2080        Ok(From::from(v))
2081    }
2082
2083    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
2084    where
2085        E: de::Error,
2086    {
2087        core::str::from_utf8(v)
2088            .map(From::from)
2089            .map_err(|_| de::Error::invalid_value(Unexpected::Bytes(v), &self))
2090    }
2091
2092    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
2093    where
2094        E: de::Error,
2095    {
2096        String::from_utf8(v)
2097            .map(From::from)
2098            .map_err(|e| de::Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self))
2099    }
2100}
2101
2102#[cfg(feature = "serde")]
2103impl<'de> Deserialize<'de> for PathBuf {
2104    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2105    where
2106        D: Deserializer<'de>,
2107    {
2108        deserializer.deserialize_string(PathBufVisitor)
2109    }
2110}
2111
2112#[cfg(feature = "serde")]
2113impl<'de> Deserialize<'de> for Box<Path> {
2114    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2115    where
2116        D: Deserializer<'de>,
2117    {
2118        Deserialize::deserialize(deserializer).map(PathBuf::into_boxed_path)
2119    }
2120}
2121
2122#[cfg(feature = "alloc")]
2123macro_rules! impl_cmp {
2124    ($lhs:ty, $rhs: ty) => {
2125        impl<'a, 'b> PartialEq<$rhs> for $lhs {
2126            #[inline]
2127            fn eq(&self, other: &$rhs) -> bool {
2128                <Path as PartialEq>::eq(self, other)
2129            }
2130        }
2131
2132        impl<'a, 'b> PartialEq<$lhs> for $rhs {
2133            #[inline]
2134            fn eq(&self, other: &$lhs) -> bool {
2135                <Path as PartialEq>::eq(self, other)
2136            }
2137        }
2138
2139        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
2140            #[inline]
2141            fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
2142                <Path as PartialOrd>::partial_cmp(self, other)
2143            }
2144        }
2145
2146        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
2147            #[inline]
2148            fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
2149                <Path as PartialOrd>::partial_cmp(self, other)
2150            }
2151        }
2152    };
2153}
2154
2155#[cfg(feature = "alloc")]
2156impl_cmp!(PathBuf, Path);
2157#[cfg(feature = "alloc")]
2158impl_cmp!(PathBuf, &'a Path);
2159#[cfg(feature = "alloc")]
2160impl_cmp!(Cow<'a, Path>, Path);
2161#[cfg(feature = "alloc")]
2162impl_cmp!(Cow<'a, Path>, &'b Path);
2163#[cfg(feature = "alloc")]
2164impl_cmp!(Cow<'a, Path>, PathBuf);
2165
2166impl fmt::Display for StripPrefixError {
2167    #[allow(deprecated, deprecated_in_future)]
2168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2169        "prefix not found".fmt(f)
2170    }
2171}
2172
2173#[cfg(feature = "std")]
2174impl Error for StripPrefixError {
2175    #[allow(deprecated)]
2176    fn description(&self) -> &str {
2177        "prefix not found"
2178    }
2179}
2180
2181pub struct Display<'a> {
2182    path: &'a Path,
2183}
2184
2185impl fmt::Debug for Display<'_> {
2186    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2187        fmt::Debug::fmt(&self.path, formatter)
2188    }
2189}
2190
2191impl fmt::Display for Display<'_> {
2192    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
2193        fmt::Display::fmt(
2194            &lossy::Utf8Lossy::from_bytes(&self.path.as_unix_str().as_bytes()),
2195            formatter,
2196        )
2197    }
2198}
2199
2200#[cfg(test)]
2201mod tests {
2202    use super::*;
2203
2204    use alloc::rc::Rc;
2205    use alloc::sync::Arc;
2206
2207    macro_rules! t(
2208        ($path:expr, iter: $iter:expr) => (
2209            {
2210                let path = Path::new($path);
2211
2212                // Forward iteration
2213                let comps = path.iter()
2214                    .map(|p| p.to_string_lossy().into_owned())
2215                    .collect::<Vec<String>>();
2216                let exp: &[&str] = &$iter;
2217                let exps = exp.iter().map(|s| s.to_string()).collect::<Vec<String>>();
2218                assert!(comps == exps, "iter: Expected {:?}, found {:?}",
2219                        exps, comps);
2220
2221                // Reverse iteration
2222                let comps = Path::new($path).iter().rev()
2223                    .map(|p| p.to_string_lossy().into_owned())
2224                    .collect::<Vec<String>>();
2225                let exps = exps.into_iter().rev().collect::<Vec<String>>();
2226                assert!(comps == exps, "iter().rev(): Expected {:?}, found {:?}",
2227                        exps, comps);
2228            }
2229        );
2230
2231        ($path:expr, has_root: $has_root:expr, is_absolute: $is_absolute:expr) => (
2232            {
2233                let path = Path::new($path);
2234
2235                let act_root = path.has_root();
2236                assert!(act_root == $has_root, "has_root: Expected {:?}, found {:?}",
2237                        $has_root, act_root);
2238
2239                let act_abs = path.is_absolute();
2240                assert!(act_abs == $is_absolute, "is_absolute: Expected {:?}, found {:?}",
2241                        $is_absolute, act_abs);
2242            }
2243        );
2244
2245        ($path:expr, parent: $parent:expr, file_name: $file:expr) => (
2246            {
2247                let path = Path::new($path);
2248
2249                let parent = path.parent().map(|p| p.to_str().unwrap());
2250                let exp_parent: Option<&str> = $parent;
2251                assert!(parent == exp_parent, "parent: Expected {:?}, found {:?}",
2252                        exp_parent, parent);
2253
2254                let file = path.file_name().map(|p| p.to_str().unwrap());
2255                let exp_file: Option<&str> = $file;
2256                assert!(file == exp_file, "file_name: Expected {:?}, found {:?}",
2257                        exp_file, file);
2258            }
2259        );
2260
2261        ($path:expr, file_stem: $file_stem:expr, extension: $extension:expr) => (
2262            {
2263                let path = Path::new($path);
2264
2265                let stem = path.file_stem().map(|p| p.to_str().unwrap());
2266                let exp_stem: Option<&str> = $file_stem;
2267                assert!(stem == exp_stem, "file_stem: Expected {:?}, found {:?}",
2268                        exp_stem, stem);
2269
2270                let ext = path.extension().map(|p| p.to_str().unwrap());
2271                let exp_ext: Option<&str> = $extension;
2272                assert!(ext == exp_ext, "extension: Expected {:?}, found {:?}",
2273                        exp_ext, ext);
2274            }
2275        );
2276
2277        ($path:expr, iter: $iter:expr,
2278                     has_root: $has_root:expr, is_absolute: $is_absolute:expr,
2279                     parent: $parent:expr, file_name: $file:expr,
2280                     file_stem: $file_stem:expr, extension: $extension:expr) => (
2281            {
2282                t!($path, iter: $iter);
2283                t!($path, has_root: $has_root, is_absolute: $is_absolute);
2284                t!($path, parent: $parent, file_name: $file);
2285                t!($path, file_stem: $file_stem, extension: $extension);
2286            }
2287        );
2288    );
2289
2290    #[test]
2291    fn into() {
2292        use alloc::borrow::Cow;
2293
2294        let static_path = Path::new("/home/foo");
2295        let static_cow_path: Cow<'static, Path> = static_path.into();
2296        let pathbuf = PathBuf::from("/home/foo");
2297
2298        {
2299            let path: &Path = &pathbuf;
2300            let borrowed_cow_path: Cow<'_, Path> = path.into();
2301
2302            assert_eq!(static_cow_path, borrowed_cow_path);
2303        }
2304
2305        let owned_cow_path: Cow<'static, Path> = pathbuf.into();
2306
2307        assert_eq!(static_cow_path, owned_cow_path);
2308    }
2309
2310    #[test]
2311    pub fn test_decompositions_unix() {
2312        t!("",
2313        iter: [],
2314        has_root: false,
2315        is_absolute: false,
2316        parent: None,
2317        file_name: None,
2318        file_stem: None,
2319        extension: None
2320        );
2321
2322        t!("foo",
2323        iter: ["foo"],
2324        has_root: false,
2325        is_absolute: false,
2326        parent: Some(""),
2327        file_name: Some("foo"),
2328        file_stem: Some("foo"),
2329        extension: None
2330        );
2331
2332        t!("/",
2333        iter: ["/"],
2334        has_root: true,
2335        is_absolute: true,
2336        parent: None,
2337        file_name: None,
2338        file_stem: None,
2339        extension: None
2340        );
2341
2342        t!("/foo",
2343        iter: ["/", "foo"],
2344        has_root: true,
2345        is_absolute: true,
2346        parent: Some("/"),
2347        file_name: Some("foo"),
2348        file_stem: Some("foo"),
2349        extension: None
2350        );
2351
2352        t!("foo/",
2353        iter: ["foo"],
2354        has_root: false,
2355        is_absolute: false,
2356        parent: Some(""),
2357        file_name: Some("foo"),
2358        file_stem: Some("foo"),
2359        extension: None
2360        );
2361
2362        t!("/foo/",
2363        iter: ["/", "foo"],
2364        has_root: true,
2365        is_absolute: true,
2366        parent: Some("/"),
2367        file_name: Some("foo"),
2368        file_stem: Some("foo"),
2369        extension: None
2370        );
2371
2372        t!("foo/bar",
2373        iter: ["foo", "bar"],
2374        has_root: false,
2375        is_absolute: false,
2376        parent: Some("foo"),
2377        file_name: Some("bar"),
2378        file_stem: Some("bar"),
2379        extension: None
2380        );
2381
2382        t!("/foo/bar",
2383        iter: ["/", "foo", "bar"],
2384        has_root: true,
2385        is_absolute: true,
2386        parent: Some("/foo"),
2387        file_name: Some("bar"),
2388        file_stem: Some("bar"),
2389        extension: None
2390        );
2391
2392        t!("///foo///",
2393        iter: ["/", "foo"],
2394        has_root: true,
2395        is_absolute: true,
2396        parent: Some("/"),
2397        file_name: Some("foo"),
2398        file_stem: Some("foo"),
2399        extension: None
2400        );
2401
2402        t!("///foo///bar",
2403        iter: ["/", "foo", "bar"],
2404        has_root: true,
2405        is_absolute: true,
2406        parent: Some("///foo"),
2407        file_name: Some("bar"),
2408        file_stem: Some("bar"),
2409        extension: None
2410        );
2411
2412        t!("./.",
2413        iter: ["."],
2414        has_root: false,
2415        is_absolute: false,
2416        parent: Some(""),
2417        file_name: None,
2418        file_stem: None,
2419        extension: None
2420        );
2421
2422        t!("/..",
2423        iter: ["/", ".."],
2424        has_root: true,
2425        is_absolute: true,
2426        parent: Some("/"),
2427        file_name: None,
2428        file_stem: None,
2429        extension: None
2430        );
2431
2432        t!("../",
2433        iter: [".."],
2434        has_root: false,
2435        is_absolute: false,
2436        parent: Some(""),
2437        file_name: None,
2438        file_stem: None,
2439        extension: None
2440        );
2441
2442        t!("foo/.",
2443        iter: ["foo"],
2444        has_root: false,
2445        is_absolute: false,
2446        parent: Some(""),
2447        file_name: Some("foo"),
2448        file_stem: Some("foo"),
2449        extension: None
2450        );
2451
2452        t!("foo/..",
2453        iter: ["foo", ".."],
2454        has_root: false,
2455        is_absolute: false,
2456        parent: Some("foo"),
2457        file_name: None,
2458        file_stem: None,
2459        extension: None
2460        );
2461
2462        t!("foo/./",
2463        iter: ["foo"],
2464        has_root: false,
2465        is_absolute: false,
2466        parent: Some(""),
2467        file_name: Some("foo"),
2468        file_stem: Some("foo"),
2469        extension: None
2470        );
2471
2472        t!("foo/./bar",
2473        iter: ["foo", "bar"],
2474        has_root: false,
2475        is_absolute: false,
2476        parent: Some("foo"),
2477        file_name: Some("bar"),
2478        file_stem: Some("bar"),
2479        extension: None
2480        );
2481
2482        t!("foo/../",
2483        iter: ["foo", ".."],
2484        has_root: false,
2485        is_absolute: false,
2486        parent: Some("foo"),
2487        file_name: None,
2488        file_stem: None,
2489        extension: None
2490        );
2491
2492        t!("foo/../bar",
2493        iter: ["foo", "..", "bar"],
2494        has_root: false,
2495        is_absolute: false,
2496        parent: Some("foo/.."),
2497        file_name: Some("bar"),
2498        file_stem: Some("bar"),
2499        extension: None
2500        );
2501
2502        t!("./a",
2503        iter: [".", "a"],
2504        has_root: false,
2505        is_absolute: false,
2506        parent: Some("."),
2507        file_name: Some("a"),
2508        file_stem: Some("a"),
2509        extension: None
2510        );
2511
2512        t!(".",
2513        iter: ["."],
2514        has_root: false,
2515        is_absolute: false,
2516        parent: Some(""),
2517        file_name: None,
2518        file_stem: None,
2519        extension: None
2520        );
2521
2522        t!("./",
2523        iter: ["."],
2524        has_root: false,
2525        is_absolute: false,
2526        parent: Some(""),
2527        file_name: None,
2528        file_stem: None,
2529        extension: None
2530        );
2531
2532        t!("a/b",
2533        iter: ["a", "b"],
2534        has_root: false,
2535        is_absolute: false,
2536        parent: Some("a"),
2537        file_name: Some("b"),
2538        file_stem: Some("b"),
2539        extension: None
2540        );
2541
2542        t!("a//b",
2543        iter: ["a", "b"],
2544        has_root: false,
2545        is_absolute: false,
2546        parent: Some("a"),
2547        file_name: Some("b"),
2548        file_stem: Some("b"),
2549        extension: None
2550        );
2551
2552        t!("a/./b",
2553        iter: ["a", "b"],
2554        has_root: false,
2555        is_absolute: false,
2556        parent: Some("a"),
2557        file_name: Some("b"),
2558        file_stem: Some("b"),
2559        extension: None
2560        );
2561
2562        t!("a/b/c",
2563        iter: ["a", "b", "c"],
2564        has_root: false,
2565        is_absolute: false,
2566        parent: Some("a/b"),
2567        file_name: Some("c"),
2568        file_stem: Some("c"),
2569        extension: None
2570        );
2571
2572        t!(".foo",
2573        iter: [".foo"],
2574        has_root: false,
2575        is_absolute: false,
2576        parent: Some(""),
2577        file_name: Some(".foo"),
2578        file_stem: Some(".foo"),
2579        extension: None
2580        );
2581    }
2582
2583    #[test]
2584    pub fn test_stem_ext() {
2585        t!("foo",
2586        file_stem: Some("foo"),
2587        extension: None
2588        );
2589
2590        t!("foo.",
2591        file_stem: Some("foo"),
2592        extension: Some("")
2593        );
2594
2595        t!(".foo",
2596        file_stem: Some(".foo"),
2597        extension: None
2598        );
2599
2600        t!("foo.txt",
2601        file_stem: Some("foo"),
2602        extension: Some("txt")
2603        );
2604
2605        t!("foo.bar.txt",
2606        file_stem: Some("foo.bar"),
2607        extension: Some("txt")
2608        );
2609
2610        t!("foo.bar.",
2611        file_stem: Some("foo.bar"),
2612        extension: Some("")
2613        );
2614
2615        t!(".", file_stem: None, extension: None);
2616
2617        t!("..", file_stem: None, extension: None);
2618
2619        t!("", file_stem: None, extension: None);
2620    }
2621
2622    #[test]
2623    pub fn test_push() {
2624        macro_rules! tp(
2625            ($path:expr, $push:expr, $expected:expr) => ( {
2626                let mut actual = PathBuf::from($path);
2627                actual.push($push);
2628                assert!(actual.to_str() == Some($expected),
2629                        "pushing {:?} onto {:?}: Expected {:?}, got {:?}",
2630                        $push, $path, $expected, actual.to_str().unwrap());
2631            });
2632        );
2633
2634        tp!("", "foo", "foo");
2635        tp!("foo", "bar", "foo/bar");
2636        tp!("foo/", "bar", "foo/bar");
2637        tp!("foo//", "bar", "foo//bar");
2638        tp!("foo/.", "bar", "foo/./bar");
2639        tp!("foo./.", "bar", "foo././bar");
2640        tp!("foo", "", "foo/");
2641        tp!("foo", ".", "foo/.");
2642        tp!("foo", "..", "foo/..");
2643        tp!("foo", "/", "/");
2644        tp!("/foo/bar", "/", "/");
2645        tp!("/foo/bar", "/baz", "/baz");
2646        tp!("/foo/bar", "./baz", "/foo/bar/./baz");
2647    }
2648
2649    #[test]
2650    pub fn test_pop() {
2651        macro_rules! tp(
2652            ($path:expr, $expected:expr, $output:expr) => ( {
2653                let mut actual = PathBuf::from($path);
2654                let output = actual.pop();
2655                assert!(actual.to_str() == Some($expected) && output == $output,
2656                        "popping from {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
2657                        $path, $expected, $output,
2658                        actual.to_str().unwrap(), output);
2659            });
2660        );
2661
2662        tp!("", "", false);
2663        tp!("/", "/", false);
2664        tp!("foo", "", true);
2665        tp!(".", "", true);
2666        tp!("/foo", "/", true);
2667        tp!("/foo/bar", "/foo", true);
2668        tp!("foo/bar", "foo", true);
2669        tp!("foo/.", "", true);
2670        tp!("foo//bar", "foo", true);
2671    }
2672
2673    #[test]
2674    pub fn test_set_file_name() {
2675        macro_rules! tfn(
2676                ($path:expr, $file:expr, $expected:expr) => ( {
2677                let mut p = PathBuf::from($path);
2678                p.set_file_name($file);
2679                assert!(p.to_str() == Some($expected),
2680                        "setting file name of {:?} to {:?}: Expected {:?}, got {:?}",
2681                        $path, $file, $expected,
2682                        p.to_str().unwrap());
2683            });
2684        );
2685
2686        tfn!("foo", "foo", "foo");
2687        tfn!("foo", "bar", "bar");
2688        tfn!("foo", "", "");
2689        tfn!("", "foo", "foo");
2690        tfn!(".", "foo", "./foo");
2691        tfn!("foo/", "bar", "bar");
2692        tfn!("foo/.", "bar", "bar");
2693        tfn!("..", "foo", "../foo");
2694        tfn!("foo/..", "bar", "foo/../bar");
2695        tfn!("/", "foo", "/foo");
2696    }
2697
2698    #[test]
2699    pub fn test_set_extension() {
2700        macro_rules! tfe(
2701                ($path:expr, $ext:expr, $expected:expr, $output:expr) => ( {
2702                let mut p = PathBuf::from($path);
2703                let output = p.set_extension($ext);
2704                assert!(p.to_str() == Some($expected) && output == $output,
2705                        "setting extension of {:?} to {:?}: Expected {:?}/{:?}, got {:?}/{:?}",
2706                        $path, $ext, $expected, $output,
2707                        p.to_str().unwrap(), output);
2708            });
2709        );
2710
2711        tfe!("foo", "txt", "foo.txt", true);
2712        tfe!("foo.bar", "txt", "foo.txt", true);
2713        tfe!("foo.bar.baz", "txt", "foo.bar.txt", true);
2714        tfe!(".test", "txt", ".test.txt", true);
2715        tfe!("foo.txt", "", "foo", true);
2716        tfe!("foo", "", "foo", true);
2717        tfe!("", "foo", "", false);
2718        tfe!(".", "foo", ".", false);
2719        tfe!("foo/", "bar", "foo.bar", true);
2720        tfe!("foo/.", "bar", "foo.bar", true);
2721        tfe!("..", "foo", "..", false);
2722        tfe!("foo/..", "bar", "foo/..", false);
2723        tfe!("/", "foo", "/", false);
2724    }
2725
2726    #[test]
2727    fn test_eq_receivers() {
2728        use alloc::borrow::Cow;
2729
2730        let borrowed: &Path = Path::new("foo/bar");
2731        let mut owned: PathBuf = PathBuf::new();
2732        owned.push("foo");
2733        owned.push("bar");
2734        let borrowed_cow: Cow<'_, Path> = borrowed.into();
2735        let owned_cow: Cow<'_, Path> = owned.clone().into();
2736
2737        macro_rules! t {
2738            ($($current:expr),+) => {
2739                $(
2740                    assert_eq!($current, borrowed);
2741                    assert_eq!($current, owned);
2742                    assert_eq!($current, borrowed_cow);
2743                    assert_eq!($current, owned_cow);
2744                )+
2745            }
2746        }
2747
2748        t!(borrowed, owned, borrowed_cow, owned_cow);
2749    }
2750
2751    #[test]
2752    pub fn test_compare() {
2753        use std::collections::hash_map::DefaultHasher;
2754        use std::hash::{Hash, Hasher};
2755
2756        fn hash<T: Hash>(t: T) -> u64 {
2757            let mut s = DefaultHasher::new();
2758            t.hash(&mut s);
2759            s.finish()
2760        }
2761
2762        macro_rules! tc(
2763            ($path1:expr, $path2:expr, eq: $eq:expr,
2764             starts_with: $starts_with:expr, ends_with: $ends_with:expr,
2765             relative_from: $relative_from:expr) => ({
2766                 let path1 = Path::new($path1);
2767                 let path2 = Path::new($path2);
2768
2769                 let eq = path1 == path2;
2770                 assert!(eq == $eq, "{:?} == {:?}, expected {:?}, got {:?}",
2771                         $path1, $path2, $eq, eq);
2772                 assert!($eq == (hash(path1) == hash(path2)),
2773                         "{:?} == {:?}, expected {:?}, got {} and {}",
2774                         $path1, $path2, $eq, hash(path1), hash(path2));
2775
2776                 let starts_with = path1.starts_with(path2);
2777                 assert!(starts_with == $starts_with,
2778                         "{:?}.starts_with({:?}), expected {:?}, got {:?}", $path1, $path2,
2779                         $starts_with, starts_with);
2780
2781                 let ends_with = path1.ends_with(path2);
2782                 assert!(ends_with == $ends_with,
2783                         "{:?}.ends_with({:?}), expected {:?}, got {:?}", $path1, $path2,
2784                         $ends_with, ends_with);
2785
2786                 let relative_from = path1.strip_prefix(path2)
2787                                          .map(|p| p.to_str().unwrap())
2788                                          .ok();
2789                 let exp: Option<&str> = $relative_from;
2790                 assert!(relative_from == exp,
2791                         "{:?}.strip_prefix({:?}), expected {:?}, got {:?}",
2792                         $path1, $path2, exp, relative_from);
2793            });
2794        );
2795
2796        tc!("", "",
2797        eq: true,
2798        starts_with: true,
2799        ends_with: true,
2800        relative_from: Some("")
2801        );
2802
2803        tc!("foo", "",
2804        eq: false,
2805        starts_with: true,
2806        ends_with: true,
2807        relative_from: Some("foo")
2808        );
2809
2810        tc!("", "foo",
2811        eq: false,
2812        starts_with: false,
2813        ends_with: false,
2814        relative_from: None
2815        );
2816
2817        tc!("foo", "foo",
2818        eq: true,
2819        starts_with: true,
2820        ends_with: true,
2821        relative_from: Some("")
2822        );
2823
2824        tc!("foo/", "foo",
2825        eq: true,
2826        starts_with: true,
2827        ends_with: true,
2828        relative_from: Some("")
2829        );
2830
2831        tc!("foo/bar", "foo",
2832        eq: false,
2833        starts_with: true,
2834        ends_with: false,
2835        relative_from: Some("bar")
2836        );
2837
2838        tc!("foo/bar/baz", "foo/bar",
2839        eq: false,
2840        starts_with: true,
2841        ends_with: false,
2842        relative_from: Some("baz")
2843        );
2844
2845        tc!("foo/bar", "foo/bar/baz",
2846        eq: false,
2847        starts_with: false,
2848        ends_with: false,
2849        relative_from: None
2850        );
2851
2852        tc!("./foo/bar/", ".",
2853        eq: false,
2854        starts_with: true,
2855        ends_with: false,
2856        relative_from: Some("foo/bar")
2857        );
2858    }
2859
2860    #[test]
2861    fn test_components_debug() {
2862        let path = Path::new("/tmp");
2863
2864        let mut components = path.components();
2865
2866        let expected = "Components([RootDir, Normal(\"tmp\")])";
2867        let actual = format!("{:?}", components);
2868        assert_eq!(expected, actual);
2869
2870        let _ = components.next().unwrap();
2871        let expected = "Components([Normal(\"tmp\")])";
2872        let actual = format!("{:?}", components);
2873        assert_eq!(expected, actual);
2874
2875        let _ = components.next().unwrap();
2876        let expected = "Components([])";
2877        let actual = format!("{:?}", components);
2878        assert_eq!(expected, actual);
2879    }
2880
2881    #[test]
2882    fn test_iter_debug() {
2883        let path = Path::new("/tmp");
2884
2885        let mut iter = path.iter();
2886
2887        let expected = "Iter([\"/\", \"tmp\"])";
2888        let actual = format!("{:?}", iter);
2889        assert_eq!(expected, actual);
2890
2891        let _ = iter.next().unwrap();
2892        let expected = "Iter([\"tmp\"])";
2893        let actual = format!("{:?}", iter);
2894        assert_eq!(expected, actual);
2895
2896        let _ = iter.next().unwrap();
2897        let expected = "Iter([])";
2898        let actual = format!("{:?}", iter);
2899        assert_eq!(expected, actual);
2900    }
2901
2902    #[test]
2903    fn into_boxed() {
2904        let orig: &str = "some/sort/of/path";
2905        let path = Path::new(orig);
2906        let boxed: Box<Path> = Box::from(path);
2907        let path_buf = path.to_owned().into_boxed_path().into_path_buf();
2908        assert_eq!(path, &*boxed);
2909        assert_eq!(&*boxed, &*path_buf);
2910        assert_eq!(&*path_buf, path);
2911    }
2912
2913    #[test]
2914    fn into_rc() {
2915        let orig = "hello/world";
2916        let path = Path::new(orig);
2917        let rc: Rc<Path> = Rc::from(path);
2918        let arc: Arc<Path> = Arc::from(path);
2919
2920        assert_eq!(&*rc, path);
2921        assert_eq!(&*arc, path);
2922
2923        let rc2: Rc<Path> = Rc::from(path.to_owned());
2924        let arc2: Arc<Path> = Arc::from(path.to_owned());
2925
2926        assert_eq!(&*rc2, path);
2927        assert_eq!(&*arc2, path);
2928    }
2929}