uni_path/
lib.rs

1//! Platform-independent path manipulation.
2//!
3//! This module provides two types, [`PathBuf`] and [`Path`] (akin to [`String`]
4//! and [`str`]), for working with paths abstractly. These types are thin wrappers
5//! around [`String`] and [`str`] respectively, meaning that they work directly
6//! on strings.
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 uni_path::Path;
25//!
26//! let path = Path::new("/tmp/foo/bar.txt");
27//!
28//! let parent = path.parent();
29//! assert_eq!(parent, Some(Path::new("/tmp/foo")));
30//!
31//! let file_stem = path.file_stem();
32//! assert_eq!(file_stem, Some("bar"));
33//!
34//! let extension = path.extension();
35//! assert_eq!(extension, Some("txt"));
36//! ```
37//!
38//! To build or modify paths, use [`PathBuf`]:
39//!
40//! ```
41//! use uni_path::PathBuf;
42//!
43//! // This way works...
44//! let mut path = PathBuf::from("/");
45//!
46//! path.push("lib");
47//! path.push("libc");
48//!
49//! path.set_extension("so");
50//!
51//! // ... but push is best used if you don't know everything up
52//! // front. If you do, this way is better:
53//! let path: PathBuf = ["/", "lib", "libc.so"].iter().collect();
54//! ```
55//!
56//! [`components`]: Path::components
57//! [`push`]: PathBuf::push
58
59
60mod sys;
61#[cfg(test)]
62mod tests;
63
64use std::borrow::{Borrow, Cow};
65use std::cmp;
66use std::error::Error;
67use std::fmt;
68use std::hash::{Hash, Hasher};
69use std::iter::{self, FusedIterator};
70use std::ops::{self, Deref};
71use std::rc::Rc;
72use std::str::FromStr;
73use std::sync::Arc;
74
75use sys::{is_sep_char, MAIN_SEP_STR, MAIN_SEP};
76
77
78////////////////////////////////////////////////////////////////////////////////
79// Exposed parsing helpers
80////////////////////////////////////////////////////////////////////////////////
81
82/// Determines whether the character is one of the permitted path
83/// separators for the current platform.
84///
85/// # Examples
86///
87/// ```
88/// use uni_path as path;
89///
90/// assert!(path::is_separator('/'));
91/// assert!(!path::is_separator('❤'));
92/// ```
93pub fn is_separator(c: char) -> bool {
94    is_sep_char(c)
95}
96
97/// The primary separator of path components for the current platform.
98///
99/// It is always `/`.
100pub const MAIN_SEPARATOR: char = sys::MAIN_SEP;
101
102////////////////////////////////////////////////////////////////////////////////
103// Misc helpers
104////////////////////////////////////////////////////////////////////////////////
105
106// Iterate through `iter` while it matches `prefix`; return `None` if `prefix`
107// is not a prefix of `iter`, otherwise return `Some(iter_after_prefix)` giving
108// `iter` after having exhausted `prefix`.
109fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
110where
111    I: Iterator<Item = Component<'a>> + Clone,
112    J: Iterator<Item = Component<'b>>,
113{
114    loop {
115        let mut iter_next = iter.clone();
116        match (iter_next.next(), prefix.next()) {
117            (Some(ref x), Some(ref y)) if x == y => (),
118            (Some(_), Some(_)) => return None,
119            (Some(_), None) => return Some(iter),
120            (None, None) => return Some(iter),
121            (None, Some(_)) => return None,
122        }
123        iter = iter_next;
124    }
125}
126
127////////////////////////////////////////////////////////////////////////////////
128// Cross-platform, iterator-independent parsing
129////////////////////////////////////////////////////////////////////////////////
130
131/// Says whether the first byte is a separator.
132fn has_physical_root(path: &str) -> bool {
133    !path.is_empty() && is_sep_char(path.chars().nth(0).unwrap())
134}
135
136// basic workhorse for splitting stem and extension
137fn split_file_at_dot(file: &str) -> (Option<&str>, Option<&str>) {
138    if file == ".." {
139        return (Some(file), None);
140    }
141
142    let mut iter = file.rsplitn(2, '.');
143    let after = iter.next();
144    let before = iter.next();
145    if before == Some("") {
146        (Some(file), None)
147    } else {
148        (before, after)
149    }
150}
151
152////////////////////////////////////////////////////////////////////////////////
153// The core iterators
154////////////////////////////////////////////////////////////////////////////////
155
156/// Component parsing works by a double-ended state machine; the cursors at the
157/// front and back of the path each keep track of what parts of the path have
158/// been consumed so far.
159///
160/// Going front to back, a path is made up of a starting
161/// directory component, and a body (of normal components)
162#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
163enum State {
164    StartDir = 1, // / or . or nothing
165    Body = 2,     // foo/bar/baz
166    Done = 3,
167}
168
169/// A single component of a path.
170///
171/// A `Component` roughly corresponds to a substring between path separators
172/// (`/`).
173///
174/// This `enum` is created by iterating over [`Components`], which in turn is
175/// created by the [`components`](Path::components) method on [`Path`].
176///
177/// # Examples
178///
179/// ```rust
180/// use uni_path::{Component, Path};
181///
182/// let path = Path::new("/tmp/foo/bar.txt");
183/// let components = path.components().collect::<Vec<_>>();
184/// assert_eq!(&components, &[
185///     Component::RootDir,
186///     Component::Normal("tmp".as_ref()),
187///     Component::Normal("foo".as_ref()),
188///     Component::Normal("bar.txt".as_ref()),
189/// ]);
190/// ```
191#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
192pub enum Component<'a> {
193    /// The root directory component, appears after any prefix and before anything else.
194    ///
195    /// It represents a separator that designates that a path starts from root.
196    RootDir,
197
198    /// A reference to the current directory, i.e., `.`.
199    CurDir,
200
201    /// A reference to the parent directory, i.e., `..`.
202    ParentDir,
203
204    /// A normal component, e.g., `a` and `b` in `a/b`.
205    ///
206    /// This variant is the most common one, it represents references to files
207    /// or directories.
208    Normal(&'a str),
209}
210
211impl<'a> Component<'a> {
212    /// Extracts the underlying [`str`] slice.
213    ///
214    /// # Examples
215    ///
216    /// ```
217    /// use uni_path::Path;
218    ///
219    /// let path = Path::new("./tmp/foo/bar.txt");
220    /// let components: Vec<_> = path.components().map(|comp| comp.as_str()).collect();
221    /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
222    /// ```
223    pub fn as_str(self) -> &'a str {
224        match self {
225            Component::RootDir => MAIN_SEP_STR,
226            Component::CurDir => ".",
227            Component::ParentDir => "..",
228            Component::Normal(path) => path,
229        }
230    }
231}
232
233impl AsRef<str> for Component<'_> {
234    #[inline]
235    fn as_ref(&self) -> &str {
236        self.as_str()
237    }
238}
239
240impl AsRef<Path> for Component<'_> {
241    #[inline]
242    fn as_ref(&self) -> &Path {
243        self.as_str().as_ref()
244    }
245}
246
247/// An iterator over the [`Component`]s of a [`Path`].
248///
249/// This `struct` is created by the [`components`] method on [`Path`].
250/// See its documentation for more.
251///
252/// # Examples
253///
254/// ```
255/// use uni_path::Path;
256///
257/// let path = Path::new("/tmp/foo/bar.txt");
258///
259/// for component in path.components() {
260///     println!("{:?}", component);
261/// }
262/// ```
263///
264/// [`components`]: Path::components
265#[derive(Clone)]
266pub struct Components<'a> {
267    // The path left to parse components from
268    path: &'a str,
269
270    // true if path *physically* has a root separator;
271    has_physical_root: bool,
272
273    // The iterator is double-ended, and these two states keep track of what has
274    // been produced from either end
275    front: State,
276    back: State,
277}
278
279/// An iterator over the [`Component`]s of a [`Path`], as [`str`] slices.
280///
281/// This `struct` is created by the [`iter`] method on [`Path`].
282/// See its documentation for more.
283///
284/// [`iter`]: Path::iter
285#[derive(Clone)]
286pub struct Iter<'a> {
287    inner: Components<'a>,
288}
289
290impl fmt::Debug for Components<'_> {
291    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292        struct DebugHelper<'a>(&'a Path);
293
294        impl fmt::Debug for DebugHelper<'_> {
295            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296                f.debug_list().entries(self.0.components()).finish()
297            }
298        }
299
300        f.debug_tuple("Components").field(&DebugHelper(self.as_path())).finish()
301    }
302}
303
304impl<'a> Components<'a> {
305    // Given the iteration so far, how much of the pre-State::Body path is left?
306    #[inline]
307    fn len_before_body(&self) -> usize {
308        let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 };
309        let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 };
310        root + cur_dir
311    }
312
313    // is the iteration complete?
314    #[inline]
315    fn finished(&self) -> bool {
316        self.front == State::Done || self.back == State::Done || self.front > self.back
317    }
318
319    #[inline]
320    fn is_sep_char(&self, b: char) -> bool {
321        is_sep_char(b)
322    }
323
324    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
325    ///
326    /// # Examples
327    ///
328    /// ```
329    /// use uni_path::Path;
330    ///
331    /// let mut components = Path::new("/tmp/foo/bar.txt").components();
332    /// components.next();
333    /// components.next();
334    ///
335    /// assert_eq!(Path::new("foo/bar.txt"), components.as_path());
336    /// ```
337    pub fn as_path(&self) -> &'a Path {
338        let mut comps = self.clone();
339        if comps.front == State::Body {
340            comps.trim_left();
341        }
342        if comps.back == State::Body {
343            comps.trim_right();
344        }
345        Path::from_str(comps.path)
346    }
347
348    /// Is the *original* path rooted?
349    fn has_root(&self) -> bool {
350        self.has_physical_root
351    }
352
353    /// Should the normalized path include a leading . ?
354    fn include_cur_dir(&self) -> bool {
355        if self.has_root() {
356            return false;
357        }
358        let mut iter = self.path.chars();
359        match (iter.next(), iter.next()) {
360            (Some('.'), None) => true,
361            (Some('.'), Some(b)) => self.is_sep_char(b),
362            _ => false,
363        }
364    }
365
366    // parse a given byte sequence into the corresponding path component
367    fn parse_single_component<'b>(&self, comp: &'b str) -> Option<Component<'b>> {
368        match comp {
369            "." => None, // . components are normalized away, except at
370            // the beginning of a path, which is treated
371            // separately via `include_cur_dir`
372            ".." => Some(Component::ParentDir),
373            "" => None,
374            _ => Some(Component::Normal(comp)),
375        }
376    }
377
378    // parse a component from the left, saying how many bytes to consume to
379    // remove the component
380    fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {
381        debug_assert!(self.front == State::Body);
382        let (extra, comp) = match self.path.chars().position(|b| self.is_sep_char(b)) {
383            None => (0, self.path),
384            Some(i) => (1, &self.path[..i]),
385        };
386        (comp.len() + extra, self.parse_single_component(comp))
387    }
388
389    // parse a component from the right, saying how many bytes to consume to
390    // remove the component
391    fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {
392        debug_assert!(self.back == State::Body);
393        let start = self.len_before_body();
394        // @@ rewrite
395        let path = &self.path[start..];
396        let (extra, comp) = match path.chars().rev().position(|b| self.is_sep_char(b)).map(|p| path.len() - p - 1) {
397            None => (0, &self.path[start..]),
398            Some(i) => (1, &self.path[start + i + 1..]),
399        };
400        (comp.len() + extra, self.parse_single_component(comp))
401    }
402
403    // trim away repeated separators (i.e., empty components) on the left
404    fn trim_left(&mut self) {
405        while !self.path.is_empty() {
406            let (size, comp) = self.parse_next_component();
407            if comp.is_some() {
408                return;
409            } else {
410                self.path = &self.path[size..];
411            }
412        }
413    }
414
415    // trim away repeated separators (i.e., empty components) on the right
416    fn trim_right(&mut self) {
417        while self.path.len() > self.len_before_body() {
418            let (size, comp) = self.parse_next_component_back();
419            if comp.is_some() {
420                return;
421            } else {
422                self.path = &self.path[..self.path.len() - size];
423            }
424        }
425    }
426}
427
428impl AsRef<Path> for Components<'_> {
429    #[inline]
430    fn as_ref(&self) -> &Path {
431        self.as_path()
432    }
433}
434
435impl AsRef<str> for Components<'_> {
436    #[inline]
437    fn as_ref(&self) -> &str {
438        self.as_path().as_str()
439    }
440}
441
442impl fmt::Debug for Iter<'_> {
443    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444        struct DebugHelper<'a>(&'a Path);
445
446        impl fmt::Debug for DebugHelper<'_> {
447            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448                f.debug_list().entries(self.0.iter()).finish()
449            }
450        }
451
452        f.debug_tuple("Iter").field(&DebugHelper(self.as_path())).finish()
453    }
454}
455
456impl<'a> Iter<'a> {
457    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
458    ///
459    /// # Examples
460    ///
461    /// ```
462    /// use uni_path::Path;
463    ///
464    /// let mut iter = Path::new("/tmp/foo/bar.txt").iter();
465    /// iter.next();
466    /// iter.next();
467    ///
468    /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());
469    /// ```
470        #[inline]
471    pub fn as_path(&self) -> &'a Path {
472        self.inner.as_path()
473    }
474}
475
476impl AsRef<Path> for Iter<'_> {
477    #[inline]
478    fn as_ref(&self) -> &Path {
479        self.as_path()
480    }
481}
482
483impl AsRef<str> for Iter<'_> {
484    #[inline]
485    fn as_ref(&self) -> &str {
486        self.as_path().as_str()
487    }
488}
489
490impl<'a> Iterator for Iter<'a> {
491    type Item = &'a str;
492
493    #[inline]
494    fn next(&mut self) -> Option<&'a str> {
495        self.inner.next().map(Component::as_str)
496    }
497}
498
499impl<'a> DoubleEndedIterator for Iter<'a> {
500    #[inline]
501    fn next_back(&mut self) -> Option<&'a str> {
502        self.inner.next_back().map(Component::as_str)
503    }
504}
505
506impl FusedIterator for Iter<'_> {}
507
508impl<'a> Iterator for Components<'a> {
509    type Item = Component<'a>;
510
511    fn next(&mut self) -> Option<Component<'a>> {
512        while !self.finished() {
513            match self.front {
514                State::StartDir => {
515                    self.front = State::Body;
516                    if self.has_physical_root {
517                        debug_assert!(!self.path.is_empty());
518                        self.path = &self.path[1..];
519                        return Some(Component::RootDir);
520                    } else if self.include_cur_dir() {
521                        debug_assert!(!self.path.is_empty());
522                        self.path = &self.path[1..];
523                        return Some(Component::CurDir);
524                    }
525                }
526                State::Body if !self.path.is_empty() => {
527                    let (size, comp) = self.parse_next_component();
528                    self.path = &self.path[size..];
529                    if comp.is_some() {
530                        return comp;
531                    }
532                }
533                State::Body => {
534                    self.front = State::Done;
535                }
536                State::Done => unreachable!(),
537            }
538        }
539        None
540    }
541}
542
543impl<'a> DoubleEndedIterator for Components<'a> {
544    fn next_back(&mut self) -> Option<Component<'a>> {
545        while !self.finished() {
546            match self.back {
547                State::Body if self.path.len() > self.len_before_body() => {
548                    let (size, comp) = self.parse_next_component_back();
549                    self.path = &self.path[..self.path.len() - size];
550                    if comp.is_some() {
551                        return comp;
552                    }
553                }
554                State::Body => {
555                    self.back = State::StartDir;
556                }
557                State::StartDir => {
558                    self.back = State::Done;
559                    if self.has_physical_root {
560                        self.path = &self.path[..self.path.len() - 1];
561                        return Some(Component::RootDir);
562                    } else if self.include_cur_dir() {
563                        self.path = &self.path[..self.path.len() - 1];
564                        return Some(Component::CurDir);
565                    }
566                }
567                State::Done => unreachable!(),
568            }
569        }
570        None
571    }
572}
573
574impl FusedIterator for Components<'_> {}
575
576impl<'a> cmp::PartialEq for Components<'a> {
577    #[inline]
578    fn eq(&self, other: &Components<'a>) -> bool {
579        Iterator::eq(self.clone(), other.clone())
580    }
581}
582
583impl cmp::Eq for Components<'_> {}
584
585impl<'a> cmp::PartialOrd for Components<'a> {
586    #[inline]
587    fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
588        Iterator::partial_cmp(self.clone(), other.clone())
589    }
590}
591
592impl cmp::Ord for Components<'_> {
593    #[inline]
594    fn cmp(&self, other: &Self) -> cmp::Ordering {
595        Iterator::cmp(self.clone(), other.clone())
596    }
597}
598
599/// An iterator over [`Path`] and its ancestors.
600///
601/// This `struct` is created by the [`ancestors`] method on [`Path`].
602/// See its documentation for more.
603///
604/// # Examples
605///
606/// ```
607/// use uni_path::Path;
608///
609/// let path = Path::new("/foo/bar");
610///
611/// for ancestor in path.ancestors() {
612///     println!("{}", ancestor);
613/// }
614/// ```
615///
616/// [`ancestors`]: Path::ancestors
617#[derive(Copy, Clone, Debug)]
618pub struct Ancestors<'a> {
619    next: Option<&'a Path>,
620}
621
622impl<'a> Iterator for Ancestors<'a> {
623    type Item = &'a Path;
624
625    #[inline]
626    fn next(&mut self) -> Option<Self::Item> {
627        let next = self.next;
628        self.next = next.and_then(Path::parent);
629        next
630    }
631}
632
633impl FusedIterator for Ancestors<'_> {}
634
635////////////////////////////////////////////////////////////////////////////////
636// Basic types and traits
637////////////////////////////////////////////////////////////////////////////////
638
639/// An owned, mutable path (akin to [`String`]).
640///
641/// This type provides methods like [`push`] and [`set_extension`] that mutate
642/// the path in place. It also implements [`Deref`] to [`Path`], meaning that
643/// all methods on [`Path`] slices are available on `PathBuf` values as well.
644///
645/// [`push`]: PathBuf::push
646/// [`set_extension`]: PathBuf::set_extension
647///
648/// More details about the overall approach can be found in
649/// the [module documentation](self).
650///
651/// # Examples
652///
653/// You can use [`push`] to build up a `PathBuf` from
654/// components:
655///
656/// ```
657/// use uni_path::PathBuf;
658///
659/// let mut path = PathBuf::new();
660///
661/// path.push(r"/");
662/// path.push("lib");
663/// path.push("libc");
664///
665/// path.set_extension("so");
666/// ```
667///
668/// However, [`push`] is best used for dynamic situations. This is a better way
669/// to do this when you know all of the components ahead of time:
670///
671/// ```
672/// use uni_path::PathBuf;
673///
674/// let path: PathBuf = [r"/", "lib", "libc.so"].iter().collect();
675/// ```
676///
677/// We can still do better than this! Since these are all strings, we can use
678/// `From::from`:
679///
680/// ```
681/// use uni_path::PathBuf;
682///
683/// let path = PathBuf::from("/lib/libc.so");
684/// ```
685///
686/// Which method works best depends on what kind of situation you're in.
687#[derive(Clone)]
688#[repr(transparent)]
689pub struct PathBuf {
690    inner: String,
691}
692
693impl PathBuf {
694    #[inline]
695    fn as_mut_string(&mut self) -> &mut String {
696        &mut self.inner
697    }
698
699    /// Allocates an empty `PathBuf`.
700    ///
701    /// # Examples
702    ///
703    /// ```
704    /// use uni_path::PathBuf;
705    ///
706    /// let path = PathBuf::new();
707    /// ```
708    #[inline]
709    pub fn new() -> PathBuf {
710        PathBuf { inner: String::new() }
711    }
712
713    /// Creates a new `PathBuf` with a given capacity used to create the
714    /// internal [`String`]. See [`with_capacity`] defined on [`String`].
715    ///
716    /// # Examples
717    ///
718    /// ```
719    /// use uni_path::PathBuf;
720    ///
721    /// let mut path = PathBuf::with_capacity(10);
722    /// let capacity = path.capacity();
723    ///
724    /// // This push is done without reallocating
725    /// path.push(r"/");
726    ///
727    /// assert_eq!(capacity, path.capacity());
728    /// ```
729    ///
730    /// [`with_capacity`]: String::with_capacity
731    #[inline]
732    pub fn with_capacity(capacity: usize) -> PathBuf {
733        PathBuf { inner: String::with_capacity(capacity) }
734    }
735
736    /// Coerces to a [`Path`] slice.
737    ///
738    /// # Examples
739    ///
740    /// ```
741    /// use uni_path::{Path, PathBuf};
742    ///
743    /// let p = PathBuf::from("/test");
744    /// assert_eq!(Path::new("/test"), p.as_path());
745    /// ```
746    #[inline]
747    pub fn as_path(&self) -> &Path {
748        self
749    }
750
751    /// Extends `self` with `path`.
752    ///
753    /// If `path` is absolute, it replaces the current path.
754    ///
755    /// # Examples
756    ///
757    /// Pushing a relative path extends the existing path:
758    ///
759    /// ```
760    /// use uni_path::PathBuf;
761    ///
762    /// let mut path = PathBuf::from("/tmp");
763    /// path.push("file.bk");
764    /// assert_eq!(path, PathBuf::from("/tmp/file.bk"));
765    /// ```
766    ///
767    /// Pushing an absolute path replaces the existing path:
768    ///
769    /// ```
770    /// use uni_path::PathBuf;
771    ///
772    /// let mut path = PathBuf::from("/tmp");
773    /// path.push("/etc");
774    /// assert_eq!(path, PathBuf::from("/etc"));
775    /// ```
776    pub fn push<P: AsRef<Path>>(&mut self, path: P) {
777        self._push(path.as_ref())
778    }
779
780    fn _push(&mut self, path: &Path) {
781        // in general, a separator is needed if the rightmost byte is not a separator
782        let need_sep = self.as_mut_string().chars().last().map(|c| !is_sep_char(c)).unwrap_or(false);
783
784        // absolute `path` replaces `self`
785        if path.is_absolute() {
786            self.as_mut_string().truncate(0);
787
788        // `path` has a root
789        } else if path.has_root() {
790            self.as_mut_string().truncate(0);
791
792        // `path` is a pure relative path
793        } else if need_sep {
794            self.inner.push(MAIN_SEP);
795        }
796
797        self.inner.push_str(path.as_str());
798    }
799
800    /// Truncates `self` to [`self.parent`].
801    ///
802    /// Returns `false` and does nothing if [`self.parent`] is [`None`].
803    /// Otherwise, returns `true`.
804    ///
805    /// [`self.parent`]: Path::parent
806    ///
807    /// # Examples
808    ///
809    /// ```
810    /// use uni_path::{Path, PathBuf};
811    ///
812    /// let mut p = PathBuf::from("/spirited/away.rs");
813    ///
814    /// p.pop();
815    /// assert_eq!(Path::new("/spirited"), p);
816    /// p.pop();
817    /// assert_eq!(Path::new("/"), p);
818    /// ```
819    pub fn pop(&mut self) -> bool {
820        match self.parent().map(|p| p.as_str().len()) {
821            Some(len) => {
822                self.as_mut_string().truncate(len);
823                true
824            }
825            None => false,
826        }
827    }
828
829    /// Updates [`self.file_name`] to `file_name`.
830    ///
831    /// If [`self.file_name`] was [`None`], this is equivalent to pushing
832    /// `file_name`.
833    ///
834    /// Otherwise it is equivalent to calling [`pop`] and then pushing
835    /// `file_name`. The new path will be a sibling of the original path.
836    /// (That is, it will have the same parent.)
837    ///
838    /// [`self.file_name`]: Path::file_name
839    /// [`pop`]: PathBuf::pop
840    ///
841    /// # Examples
842    ///
843    /// ```
844    /// use uni_path::PathBuf;
845    ///
846    /// let mut buf = PathBuf::from("/");
847    /// assert!(buf.file_name() == None);
848    /// buf.set_file_name("bar");
849    /// assert!(buf == PathBuf::from("/bar"));
850    /// assert!(buf.file_name().is_some());
851    /// buf.set_file_name("baz.txt");
852    /// assert!(buf == PathBuf::from("/baz.txt"));
853    /// ```
854    pub fn set_file_name<S: AsRef<str>>(&mut self, file_name: S) {
855        self._set_file_name(file_name.as_ref())
856    }
857
858    fn _set_file_name(&mut self, file_name: &str) {
859        if self.file_name().is_some() {
860            let popped = self.pop();
861            debug_assert!(popped);
862        }
863        self.push(file_name);
864    }
865
866    /// Updates [`self.extension`] to `extension`.
867    ///
868    /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
869    /// returns `true` and updates the extension otherwise.
870    ///
871    /// If [`self.extension`] is [`None`], the extension is added; otherwise
872    /// it is replaced.
873    ///
874    /// [`self.file_name`]: Path::file_name
875    /// [`self.extension`]: Path::extension
876    ///
877    /// # Examples
878    ///
879    /// ```
880    /// use uni_path::{Path, PathBuf};
881    ///
882    /// let mut p = PathBuf::from("/feel/the");
883    ///
884    /// p.set_extension("force");
885    /// assert_eq!(Path::new("/feel/the.force"), p.as_path());
886    ///
887    /// p.set_extension("dark_side");
888    /// assert_eq!(Path::new("/feel/the.dark_side"), p.as_path());
889    /// ```
890    pub fn set_extension<S: AsRef<str>>(&mut self, extension: S) -> bool {
891        self._set_extension(extension.as_ref())
892    }
893
894    fn _set_extension(&mut self, extension: &str) -> bool {
895        let file_stem = match self.file_stem() {
896            None => return false,
897            Some(f) => f,
898        };
899        
900        // truncate until right after the file stem
901        let start = self.inner.as_ptr() as usize;
902        let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
903        let v = &mut self.inner;
904        v.truncate(end_file_stem.wrapping_sub(start));
905
906        // add the new extension, if any
907        if !extension.is_empty() {
908            v.reserve_exact(extension.len() + 1);
909            v.push('.');
910            v.push_str(extension);
911        }
912
913        true
914    }
915
916    /// Consumes the `PathBuf`, yielding its internal [`String`] storage.
917    ///
918    /// # Examples
919    ///
920    /// ```
921    /// use uni_path::PathBuf;
922    ///
923    /// let p = PathBuf::from("/the/head");
924    /// let str = p.into_string();
925    /// ```
926    #[inline]
927    pub fn into_string(self) -> String {
928        self.inner
929    }
930
931    /// Converts this `PathBuf` into a [boxed](Box) [`Path`].
932    #[inline]
933    pub fn into_boxed_path(self) -> Box<Path> {
934        let rw = Box::into_raw(self.inner.into_boxed_str()) as *mut Path;
935        unsafe { Box::from_raw(rw) }
936    }
937
938    /// Invokes [`capacity`] on the underlying instance of [`String`].
939    ///
940    /// [`capacity`]: String::capacity
941    #[inline]
942    pub fn capacity(&self) -> usize {
943        self.inner.capacity()
944    }
945
946    /// Invokes [`clear`] on the underlying instance of [`String`].
947    ///
948    /// [`clear`]: String::clear=
949    #[inline]
950    pub fn clear(&mut self) {
951        self.inner.clear()
952    }
953
954    /// Invokes [`reserve`] on the underlying instance of [`String`].
955    ///
956    /// [`reserve`]: String::reserve
957    #[inline]
958    pub fn reserve(&mut self, additional: usize) {
959        self.inner.reserve(additional)
960    }
961
962    /// Invokes [`reserve_exact`] on the underlying instance of [`String`].
963    ///
964    /// [`reserve_exact`]: String::reserve_exact
965    #[inline]
966    pub fn reserve_exact(&mut self, additional: usize) {
967        self.inner.reserve_exact(additional)
968    }
969
970    /// Invokes [`shrink_to_fit`] on the underlying instance of [`String`].
971    ///
972    /// [`shrink_to_fit`]: String::shrink_to_fit
973    #[inline]
974    pub fn shrink_to_fit(&mut self) {
975        self.inner.shrink_to_fit()
976    }
977
978    /*
979    /// Invokes [`shrink_to`] on the underlying instance of [`String`].
980    ///
981    /// [`shrink_to`]: String::shrink_to
982    #[inline]
983    pub fn shrink_to(&mut self, min_capacity: usize) {
984        self.inner.shrink_to(min_capacity)
985    }
986    */
987}
988
989impl From<&Path> for Box<Path> {
990    fn from(path: &Path) -> Box<Path> {
991        let boxed: Box<str> = path.inner.into();
992        let rw = Box::into_raw(boxed) as *mut Path;
993        unsafe { Box::from_raw(rw) }
994    }
995}
996
997impl From<Cow<'_, Path>> for Box<Path> {
998    #[inline]
999    fn from(cow: Cow<'_, Path>) -> Box<Path> {
1000        match cow {
1001            Cow::Borrowed(path) => Box::from(path),
1002            Cow::Owned(path) => Box::from(path),
1003        }
1004    }
1005}
1006
1007impl From<Box<Path>> for PathBuf {
1008    /// Converts a `Box<Path>` into a `PathBuf`
1009    ///
1010    /// This conversion does not allocate or copy memory.
1011    #[inline]
1012    fn from(boxed: Box<Path>) -> PathBuf {
1013        boxed.into_path_buf()
1014    }
1015}
1016
1017impl From<PathBuf> for Box<Path> {
1018    /// Converts a `PathBuf` into a `Box<Path>`
1019    ///
1020    /// This conversion currently should not allocate memory,
1021    /// but this behavior is not guaranteed on all platforms or in all future versions.
1022    #[inline]
1023    fn from(p: PathBuf) -> Box<Path> {
1024        p.into_boxed_path()
1025    }
1026}
1027
1028impl Clone for Box<Path> {
1029    #[inline]
1030    fn clone(&self) -> Self {
1031        self.to_path_buf().into_boxed_path()
1032    }
1033}
1034
1035impl<T: ?Sized + AsRef<str>> From<&T> for PathBuf {
1036    #[inline]
1037    fn from(s: &T) -> PathBuf {
1038        PathBuf::from(s.as_ref().to_string())
1039    }
1040}
1041
1042impl From<String> for PathBuf {
1043    /// Converts a `String` into a `PathBuf`
1044    ///
1045    /// This conversion does not allocate or copy memory.
1046    #[inline]
1047    fn from(s: String) -> PathBuf {
1048        PathBuf { inner: s }
1049    }
1050}
1051
1052impl From<PathBuf> for String {
1053    /// Converts a `PathBuf` into a `String`
1054    ///
1055    /// This conversion does not allocate or copy memory.
1056    #[inline]
1057    fn from(path_buf: PathBuf) -> String {
1058        path_buf.inner
1059    }
1060}
1061
1062impl FromStr for PathBuf {
1063    type Err = core::convert::Infallible;
1064
1065    #[inline]
1066    fn from_str(s: &str) -> Result<Self, Self::Err> {
1067        Ok(PathBuf::from(s))
1068    }
1069}
1070
1071impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
1072    fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
1073        let mut buf = PathBuf::new();
1074        buf.extend(iter);
1075        buf
1076    }
1077}
1078
1079impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
1080    fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
1081        iter.into_iter().for_each(move |p| self.push(p.as_ref()));
1082    }
1083    /*
1084    #[inline]
1085    fn extend_one(&mut self, p: P) {
1086        self.push(p.as_ref());
1087    }
1088    */
1089}
1090
1091impl fmt::Debug for PathBuf {
1092    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1093        fmt::Debug::fmt(&**self, formatter)
1094    }
1095}
1096
1097impl fmt::Display for PathBuf {
1098    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1099        fmt::Display::fmt(&**self, formatter)
1100    }
1101}
1102
1103impl ops::Deref for PathBuf {
1104    type Target = Path;
1105    #[inline]
1106    fn deref(&self) -> &Path {
1107        Path::new(&self.inner)
1108    }
1109}
1110
1111impl Borrow<Path> for PathBuf {
1112    #[inline]
1113    fn borrow(&self) -> &Path {
1114        self.deref()
1115    }
1116}
1117
1118impl Default for PathBuf {
1119    #[inline]
1120    fn default() -> Self {
1121        PathBuf::new()
1122    }
1123}
1124
1125impl<'a> From<&'a Path> for Cow<'a, Path> {
1126    #[inline]
1127    fn from(s: &'a Path) -> Cow<'a, Path> {
1128        Cow::Borrowed(s)
1129    }
1130}
1131
1132impl<'a> From<PathBuf> for Cow<'a, Path> {
1133    #[inline]
1134    fn from(s: PathBuf) -> Cow<'a, Path> {
1135        Cow::Owned(s)
1136    }
1137}
1138
1139impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
1140    #[inline]
1141    fn from(p: &'a PathBuf) -> Cow<'a, Path> {
1142        Cow::Borrowed(p.as_path())
1143    }
1144}
1145
1146impl<'a> From<Cow<'a, Path>> for PathBuf {
1147    #[inline]
1148    fn from(p: Cow<'a, Path>) -> Self {
1149        p.into_owned()
1150    }
1151}
1152
1153impl From<PathBuf> for Arc<Path> {
1154    /// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer.
1155    #[inline]
1156    fn from(s: PathBuf) -> Arc<Path> {
1157        let arc: Arc<str> = Arc::from(s.into_string());
1158        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1159    }
1160}
1161
1162impl From<&Path> for Arc<Path> {
1163    /// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer.
1164    #[inline]
1165    fn from(s: &Path) -> Arc<Path> {
1166        let arc: Arc<str> = Arc::from(s.as_str());
1167        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
1168    }
1169}
1170
1171impl From<PathBuf> for Rc<Path> {
1172    /// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer.
1173    #[inline]
1174    fn from(s: PathBuf) -> Rc<Path> {
1175        let rc: Rc<str> = Rc::from(s.into_string());
1176        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1177    }
1178}
1179
1180impl From<&Path> for Rc<Path> {
1181    /// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer.
1182    #[inline]
1183    fn from(s: &Path) -> Rc<Path> {
1184        let rc: Rc<str> = Rc::from(s.as_str());
1185        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
1186    }
1187}
1188
1189impl ToOwned for Path {
1190    type Owned = PathBuf;
1191    #[inline]
1192    fn to_owned(&self) -> PathBuf {
1193        self.to_path_buf()
1194    }
1195    /*
1196    #[inline]
1197    fn clone_into(&self, target: &mut PathBuf) {
1198        self.inner.clone_into(&mut target.inner);
1199    }
1200    */
1201}
1202
1203impl cmp::PartialEq for PathBuf {
1204    #[inline]
1205    fn eq(&self, other: &PathBuf) -> bool {
1206        self.components() == other.components()
1207    }
1208}
1209
1210impl Hash for PathBuf {
1211    fn hash<H: Hasher>(&self, h: &mut H) {
1212        self.as_path().hash(h)
1213    }
1214}
1215
1216impl cmp::Eq for PathBuf {}
1217
1218impl cmp::PartialOrd for PathBuf {
1219    #[inline]
1220    fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
1221        self.components().partial_cmp(other.components())
1222    }
1223}
1224
1225impl cmp::Ord for PathBuf {
1226    #[inline]
1227    fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
1228        self.components().cmp(other.components())
1229    }
1230}
1231
1232impl AsRef<str> for PathBuf {
1233    #[inline]
1234    fn as_ref(&self) -> &str {
1235        &self.inner[..]
1236    }
1237}
1238
1239/// A slice of a path (akin to [`str`]).
1240///
1241/// This type supports a number of operations for inspecting a path, including
1242/// breaking the path into its components (separated by `/`),
1243/// extracting the file name, determining whether the path
1244/// is absolute, and so on.
1245///
1246/// This is an *unsized* type, meaning that it must always be used behind a
1247/// pointer like `&` or [`Box`]. For an owned version of this type,
1248/// see [`PathBuf`].
1249///
1250/// More details about the overall approach can be found in
1251/// the [module documentation](self).
1252///
1253/// # Examples
1254///
1255/// ```
1256/// use uni_path::Path;
1257///
1258/// let path = Path::new("./foo/bar.txt");
1259///
1260/// let parent = path.parent();
1261/// assert_eq!(parent, Some(Path::new("./foo")));
1262///
1263/// let file_stem = path.file_stem();
1264/// assert_eq!(file_stem, Some("bar"));
1265///
1266/// let extension = path.extension();
1267/// assert_eq!(extension, Some("txt"));
1268/// ```
1269#[repr(transparent)]
1270pub struct Path {
1271    inner: str,
1272}
1273
1274/// An error returned from [`Path::strip_prefix`] if the prefix was not found.
1275///
1276/// This `struct` is created by the [`strip_prefix`] method on [`Path`].
1277/// See its documentation for more.
1278///
1279/// [`strip_prefix`]: Path::strip_prefix
1280#[derive(Debug, Clone, PartialEq, Eq)]
1281pub struct StripPrefixError(());
1282
1283impl Path {
1284    fn from_str(s: &str) -> &Path {
1285        Path::new(s)
1286    }
1287
1288    /// Directly wraps a string slice as a `Path` slice.
1289    ///
1290    /// This is a cost-free conversion.
1291    ///
1292    /// # Examples
1293    ///
1294    /// ```
1295    /// use uni_path::Path;
1296    ///
1297    /// Path::new("foo.txt");
1298    /// ```
1299    ///
1300    /// You can create `Path`s from `String`s, or even other `Path`s:
1301    ///
1302    /// ```
1303    /// use uni_path::Path;
1304    ///
1305    /// let string = String::from("foo.txt");
1306    /// let from_string = Path::new(&string);
1307    /// let from_path = Path::new(&from_string);
1308    /// assert_eq!(from_string, from_path);
1309    /// ```
1310    pub fn new<S: AsRef<str> + ?Sized>(s: &S) -> &Path {
1311        unsafe { &*(s.as_ref() as *const str as *const Path) }
1312    }
1313
1314    /// Yields the underlying [`str`] slice.
1315    ///
1316    /// # Examples
1317    ///
1318    /// ```
1319    /// use uni_path::Path;
1320    ///
1321    /// let str = Path::new("foo.txt").as_str();
1322    /// assert_eq!(str, "foo.txt");
1323    /// ```
1324    #[inline]
1325    pub fn as_str(&self) -> &str {
1326        &self.inner
1327    }
1328
1329    /// Yields a [`&str`] slice if the `Path` is valid unicode.
1330    ///
1331    /// This conversion may entail doing a check for UTF-8 validity.
1332    /// Note that validation is performed because non-UTF-8 strings are
1333    /// perfectly valid for some OS.
1334    ///
1335    /// [`&str`]: str
1336    ///
1337    /// # Examples
1338    ///
1339    /// ```
1340    /// use uni_path::Path;
1341    ///
1342    /// let path = Path::new("foo.txt");
1343    /// assert_eq!(path.to_str(), "foo.txt");
1344    /// ```
1345    #[inline]
1346    pub fn to_str(&self) -> &str {
1347        &self.inner
1348    }
1349
1350    /// Converts a `Path` to a [`Cow<str>`].
1351    ///
1352    /// # Examples
1353    ///
1354    /// ```
1355    /// use uni_path::Path;
1356    ///
1357    /// let path = Path::new("foo.txt");
1358    /// assert_eq!(path.to_str_cow(), "foo.txt");
1359    /// ```
1360    #[inline]
1361    pub fn to_str_cow(&self) -> Cow<'_, str> {
1362        Cow::from(&self.inner)
1363    }
1364
1365    /// Converts a `Path` to an owned [`PathBuf`].
1366    ///
1367    /// # Examples
1368    ///
1369    /// ```
1370    /// use uni_path::Path;
1371    ///
1372    /// let path_buf = Path::new("foo.txt").to_path_buf();
1373    /// assert_eq!(path_buf, uni_path::PathBuf::from("foo.txt"));
1374    /// ```
1375    pub fn to_path_buf(&self) -> PathBuf {
1376        PathBuf::from(self.inner.to_string())
1377    }
1378
1379    /// Returns `true` if the `Path` is absolute, i.e., if it is independent of
1380    /// the current directory.
1381    ///
1382    /// A path is absolute if it starts with the root, so
1383    /// `is_absolute` and [`has_root`] are equivalent.
1384    /// # Examples
1385    ///
1386    /// ```
1387    /// use uni_path::Path;
1388    ///
1389    /// assert!(!Path::new("foo.txt").is_absolute());
1390    /// ```
1391    ///
1392    /// [`has_root`]: Path::has_root
1393    #[inline]
1394    pub fn is_absolute(&self) -> bool {
1395        self.has_root()
1396    }
1397
1398    /// Returns `true` if the `Path` is relative, i.e., not absolute.
1399    ///
1400    /// See [`is_absolute`]'s documentation for more details.
1401    ///
1402    /// # Examples
1403    ///
1404    /// ```
1405    /// use uni_path::Path;
1406    ///
1407    /// assert!(Path::new("foo.txt").is_relative());
1408    /// ```
1409    ///
1410    /// [`is_absolute`]: Path::is_absolute
1411    #[inline]
1412    pub fn is_relative(&self) -> bool {
1413        !self.is_absolute()
1414    }
1415
1416    /// Returns `true` if the `Path` has a root.
1417    ///
1418    /// A path has a root if it begins with `/`.
1419    /// 
1420    /// # Examples
1421    ///
1422    /// ```
1423    /// use uni_path::Path;
1424    ///
1425    /// assert!(Path::new("/etc/passwd").has_root());
1426    /// ```
1427    #[inline]
1428    pub fn has_root(&self) -> bool {
1429        self.components().has_root()
1430    }
1431
1432    /// Returns the `Path` without its final component, if there is one.
1433    ///
1434    /// Returns [`None`] if the path terminates in a root or prefix.
1435    ///
1436    /// # Examples
1437    ///
1438    /// ```
1439    /// use uni_path::Path;
1440    ///
1441    /// let path = Path::new("/foo/bar");
1442    /// let parent = path.parent().unwrap();
1443    /// assert_eq!(parent, Path::new("/foo"));
1444    ///
1445    /// let grand_parent = parent.parent().unwrap();
1446    /// assert_eq!(grand_parent, Path::new("/"));
1447    /// assert_eq!(grand_parent.parent(), None);
1448    /// ```
1449    pub fn parent(&self) -> Option<&Path> {
1450        let mut comps = self.components();
1451        let comp = comps.next_back();
1452        comp.and_then(|p| match p {
1453            Component::Normal(_) | Component::CurDir | Component::ParentDir => {
1454                Some(comps.as_path())
1455            }
1456            _ => None,
1457        })
1458    }
1459
1460    /// Produces an iterator over `Path` and its ancestors.
1461    ///
1462    /// The iterator will yield the `Path` that is returned if the [`parent`] method is used zero
1463    /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
1464    /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
1465    /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
1466    /// namely `&self`.
1467    ///
1468    /// # Examples
1469    ///
1470    /// ```
1471    /// use uni_path::Path;
1472    ///
1473    /// let mut ancestors = Path::new("/foo/bar").ancestors();
1474    /// assert_eq!(ancestors.next(), Some(Path::new("/foo/bar")));
1475    /// assert_eq!(ancestors.next(), Some(Path::new("/foo")));
1476    /// assert_eq!(ancestors.next(), Some(Path::new("/")));
1477    /// assert_eq!(ancestors.next(), None);
1478    ///
1479    /// let mut ancestors = Path::new("../foo/bar").ancestors();
1480    /// assert_eq!(ancestors.next(), Some(Path::new("../foo/bar")));
1481    /// assert_eq!(ancestors.next(), Some(Path::new("../foo")));
1482    /// assert_eq!(ancestors.next(), Some(Path::new("..")));
1483    /// assert_eq!(ancestors.next(), Some(Path::new("")));
1484    /// assert_eq!(ancestors.next(), None);
1485    /// ```
1486    ///
1487    /// [`parent`]: Path::parent
1488    #[inline]
1489    pub fn ancestors(&self) -> Ancestors<'_> {
1490        Ancestors { next: Some(&self) }
1491    }
1492
1493    /// Returns the final component of the `Path`, if there is one.
1494    ///
1495    /// If the path is a normal file, this is the file name. If it's the path of a directory, this
1496    /// is the directory name.
1497    ///
1498    /// Returns [`None`] if the path terminates in `..`.
1499    ///
1500    /// # Examples
1501    ///
1502    /// ```
1503    /// use uni_path::Path;
1504    ///
1505    /// assert_eq!(Some("bin"), Path::new("/usr/bin/").file_name());
1506    /// assert_eq!(Some("foo.txt"), Path::new("tmp/foo.txt").file_name());
1507    /// assert_eq!(Some("foo.txt"), Path::new("foo.txt/.").file_name());
1508    /// assert_eq!(Some("foo.txt"), Path::new("foo.txt/.//").file_name());
1509    /// assert_eq!(None, Path::new("foo.txt/..").file_name());
1510    /// assert_eq!(None, Path::new("/").file_name());
1511    /// ```
1512    pub fn file_name(&self) -> Option<&str> {
1513        self.components().next_back().and_then(|p| match p {
1514            Component::Normal(p) => Some(p),
1515            _ => None,
1516        })
1517    }
1518
1519    /// Returns a path that, when joined onto `base`, yields `self`.
1520    ///
1521    /// # Errors
1522    ///
1523    /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
1524    /// returns `false`), returns [`Err`].
1525    ///
1526    /// [`starts_with`]: Path::starts_with
1527    ///
1528    /// # Examples
1529    ///
1530    /// ```
1531    /// use uni_path::{Path, PathBuf};
1532    ///
1533    /// let path = Path::new("/test/haha/foo.txt");
1534    ///
1535    /// assert_eq!(path.strip_prefix("/"), Ok(Path::new("test/haha/foo.txt")));
1536    /// assert_eq!(path.strip_prefix("/test"), Ok(Path::new("haha/foo.txt")));
1537    /// assert_eq!(path.strip_prefix("/test/"), Ok(Path::new("haha/foo.txt")));
1538    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Path::new("")));
1539    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Path::new("")));
1540    ///
1541    /// assert!(path.strip_prefix("test").is_err());
1542    /// assert!(path.strip_prefix("/haha").is_err());
1543    ///
1544    /// let prefix = PathBuf::from("/test/");
1545    /// assert_eq!(path.strip_prefix(prefix), Ok(Path::new("haha/foo.txt")));
1546    /// ```
1547    pub fn strip_prefix<P>(&self, base: P) -> Result<&Path, StripPrefixError>
1548    where
1549        P: AsRef<Path>,
1550    {
1551        self._strip_prefix(base.as_ref())
1552    }
1553
1554    fn _strip_prefix(&self, base: &Path) -> Result<&Path, StripPrefixError> {
1555        iter_after(self.components(), base.components())
1556            .map(|c| c.as_path())
1557            .ok_or(StripPrefixError(()))
1558    }
1559
1560    /// Determines whether `base` is a prefix of `self`.
1561    ///
1562    /// Only considers whole path components to match.
1563    ///
1564    /// # Examples
1565    ///
1566    /// ```
1567    /// use uni_path::Path;
1568    ///
1569    /// let path = Path::new("/etc/passwd");
1570    ///
1571    /// assert!(path.starts_with("/etc"));
1572    /// assert!(path.starts_with("/etc/"));
1573    /// assert!(path.starts_with("/etc/passwd"));
1574    /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay
1575    /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay
1576    ///
1577    /// assert!(!path.starts_with("/e"));
1578    /// assert!(!path.starts_with("/etc/passwd.txt"));
1579    ///
1580    /// assert!(!Path::new("/etc/foo.rs").starts_with("/etc/foo"));
1581    /// ```
1582    pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
1583        self._starts_with(base.as_ref())
1584    }
1585
1586    fn _starts_with(&self, base: &Path) -> bool {
1587        iter_after(self.components(), base.components()).is_some()
1588    }
1589
1590    /// Determines whether `child` is a suffix of `self`.
1591    ///
1592    /// Only considers whole path components to match.
1593    ///
1594    /// # Examples
1595    ///
1596    /// ```
1597    /// use uni_path::Path;
1598    ///
1599    /// let path = Path::new("/etc/resolv.conf");
1600    ///
1601    /// assert!(path.ends_with("resolv.conf"));
1602    /// assert!(path.ends_with("etc/resolv.conf"));
1603    /// assert!(path.ends_with("/etc/resolv.conf"));
1604    ///
1605    /// assert!(!path.ends_with("/resolv.conf"));
1606    /// assert!(!path.ends_with("conf")); // use .extension() instead
1607    /// ```
1608    pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
1609        self._ends_with(child.as_ref())
1610    }
1611
1612    fn _ends_with(&self, child: &Path) -> bool {
1613        iter_after(self.components().rev(), child.components().rev()).is_some()
1614    }
1615
1616    /// Extracts the stem (non-extension) portion of [`self.file_name`].
1617    ///
1618    /// [`self.file_name`]: Path::file_name
1619    ///
1620    /// The stem is:
1621    ///
1622    /// * [`None`], if there is no file name;
1623    /// * The entire file name if there is no embedded `.`;
1624    /// * The entire file name if the file name begins with `.` and has no other `.`s within;
1625    /// * Otherwise, the portion of the file name before the final `.`
1626    ///
1627    /// # Examples
1628    ///
1629    /// ```
1630    /// use uni_path::Path;
1631    ///
1632    /// assert_eq!("foo", Path::new("foo.rs").file_stem().unwrap());
1633    /// assert_eq!("foo.tar", Path::new("foo.tar.gz").file_stem().unwrap());
1634    /// ```
1635    pub fn file_stem(&self) -> Option<&str> {
1636        self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
1637    }
1638
1639    /// Extracts the extension of [`self.file_name`], if possible.
1640    ///
1641    /// The extension is:
1642    ///
1643    /// * [`None`], if there is no file name;
1644    /// * [`None`], if there is no embedded `.`;
1645    /// * [`None`], if the file name begins with `.` and has no other `.`s within;
1646    /// * Otherwise, the portion of the file name after the final `.`
1647    ///
1648    /// [`self.file_name`]: Path::file_name
1649    ///
1650    /// # Examples
1651    ///
1652    /// ```
1653    /// use uni_path::Path;
1654    ///
1655    /// assert_eq!("rs", Path::new("foo.rs").extension().unwrap());
1656    /// assert_eq!("gz", Path::new("foo.tar.gz").extension().unwrap());
1657    /// ```
1658    pub fn extension(&self) -> Option<&str> {
1659        self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
1660    }
1661
1662    /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
1663    ///
1664    /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
1665    ///
1666    /// # Examples
1667    ///
1668    /// ```
1669    /// use uni_path::{Path, PathBuf};
1670    ///
1671    /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd"));
1672    /// ```
1673    #[must_use]
1674    pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
1675        self._join(path.as_ref())
1676    }
1677
1678    fn _join(&self, path: &Path) -> PathBuf {
1679        let mut buf = self.to_path_buf();
1680        buf.push(path);
1681        buf
1682    }
1683
1684    /// Creates an owned [`PathBuf`] like `self` but with the given file name.
1685    ///
1686    /// See [`PathBuf::set_file_name`] for more details.
1687    ///
1688    /// # Examples
1689    ///
1690    /// ```
1691    /// use uni_path::{Path, PathBuf};
1692    ///
1693    /// let path = Path::new("/tmp/foo.txt");
1694    /// assert_eq!(path.with_file_name("bar.txt"), PathBuf::from("/tmp/bar.txt"));
1695    ///
1696    /// let path = Path::new("/tmp");
1697    /// assert_eq!(path.with_file_name("var"), PathBuf::from("/var"));
1698    /// ```
1699    pub fn with_file_name<S: AsRef<str>>(&self, file_name: S) -> PathBuf {
1700        self._with_file_name(file_name.as_ref())
1701    }
1702
1703    fn _with_file_name(&self, file_name: &str) -> PathBuf {
1704        let mut buf = self.to_path_buf();
1705        buf.set_file_name(file_name);
1706        buf
1707    }
1708
1709    /// Creates an owned [`PathBuf`] like `self` but with the given extension.
1710    ///
1711    /// See [`PathBuf::set_extension`] for more details.
1712    ///
1713    /// # Examples
1714    ///
1715    /// ```
1716    /// use uni_path::{Path, PathBuf};
1717    ///
1718    /// let path = Path::new("foo.rs");
1719    /// assert_eq!(path.with_extension("txt"), PathBuf::from("foo.txt"));
1720    ///
1721    /// let path = Path::new("foo.tar.gz");
1722    /// assert_eq!(path.with_extension(""), PathBuf::from("foo.tar"));
1723    /// assert_eq!(path.with_extension("xz"), PathBuf::from("foo.tar.xz"));
1724    /// assert_eq!(path.with_extension("").with_extension("txt"), PathBuf::from("foo.txt"));
1725    /// ```
1726    pub fn with_extension<S: AsRef<str>>(&self, extension: S) -> PathBuf {
1727        self._with_extension(extension.as_ref())
1728    }
1729
1730    fn _with_extension(&self, extension: &str) -> PathBuf {
1731        let mut buf = self.to_path_buf();
1732        buf.set_extension(extension);
1733        buf
1734    }
1735
1736    /// Produces an iterator over the [`Component`]s of the path.
1737    ///
1738    /// When parsing the path, there is a small amount of normalization:
1739    ///
1740    /// * Repeated separators are ignored, so `a/b` and `a//b` both have
1741    ///   `a` and `b` as components.
1742    ///
1743    /// * Occurrences of `.` are normalized away, except if they are at the
1744    ///   beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
1745    ///   `a/b` all have `a` and `b` as components, but `./a/b` starts with
1746    ///   an additional [`CurDir`] component.
1747    ///
1748    /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
1749    ///
1750    /// Note that no other normalization takes place; in particular, `a/c`
1751    /// and `a/b/../c` are distinct, to account for the possibility that `b`
1752    /// is a symbolic link (so its parent isn't `a`).
1753    ///
1754    /// # Examples
1755    ///
1756    /// ```
1757    /// use uni_path::{Path, Component};
1758    ///
1759    /// let mut components = Path::new("/tmp/foo.txt").components();
1760    ///
1761    /// assert_eq!(components.next(), Some(Component::RootDir));
1762    /// assert_eq!(components.next(), Some(Component::Normal("tmp")));
1763    /// assert_eq!(components.next(), Some(Component::Normal("foo.txt")));
1764    /// assert_eq!(components.next(), None)
1765    /// ```
1766    ///
1767    /// [`CurDir`]: Component::CurDir
1768    pub fn components(&self) -> Components<'_> {
1769        Components {
1770            path: self.as_str(),
1771            has_physical_root: has_physical_root(self.as_str()),
1772            front: State::StartDir,
1773            back: State::Body,
1774        }
1775    }
1776
1777    /// Produces an iterator over the path's components viewed as [`str`]
1778    /// slices.
1779    ///
1780    /// For more information about the particulars of how the path is separated
1781    /// into components, see [`components`].
1782    ///
1783    /// [`components`]: Path::components
1784    ///
1785    /// # Examples
1786    ///
1787    /// ```
1788    /// use uni_path::{self as path, Path};
1789    ///
1790    /// let mut it = Path::new("/tmp/foo.txt").iter();
1791    /// assert_eq!(it.next().unwrap(), &path::MAIN_SEPARATOR.to_string());
1792    /// assert_eq!(it.next(), Some("tmp"));
1793    /// assert_eq!(it.next(), Some("foo.txt"));
1794    /// assert_eq!(it.next(), None)
1795    /// ```
1796    #[inline]
1797    pub fn iter(&self) -> Iter<'_> {
1798        Iter { inner: self.components() }
1799    }
1800
1801    /// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
1802    /// allocating.
1803    pub fn into_path_buf(self: Box<Path>) -> PathBuf {
1804        let rw = Box::into_raw(self) as *mut str;
1805        let inner = unsafe { Box::from_raw(rw) };
1806        PathBuf { inner: String::from(inner) }
1807    }
1808}
1809
1810impl AsRef<str> for Path {
1811    #[inline]
1812    fn as_ref(&self) -> &str {
1813        &self.inner
1814    }
1815}
1816
1817impl fmt::Debug for Path {
1818    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1819        fmt::Debug::fmt(&self.inner, formatter)
1820    }
1821}
1822
1823impl fmt::Display for Path {
1824    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1825        fmt::Display::fmt(&self.inner, formatter)
1826    }
1827}
1828
1829impl cmp::PartialEq for Path {
1830    #[inline]
1831    fn eq(&self, other: &Path) -> bool {
1832        self.components().eq(other.components())
1833    }
1834}
1835
1836impl Hash for Path {
1837    fn hash<H: Hasher>(&self, h: &mut H) {
1838        for component in self.components() {
1839            component.hash(h);
1840        }
1841    }
1842}
1843
1844impl cmp::Eq for Path {}
1845
1846impl cmp::PartialOrd for Path {
1847    #[inline]
1848    fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
1849        self.components().partial_cmp(other.components())
1850    }
1851}
1852
1853impl cmp::Ord for Path {
1854    #[inline]
1855    fn cmp(&self, other: &Path) -> cmp::Ordering {
1856        self.components().cmp(other.components())
1857    }
1858}
1859
1860impl AsRef<Path> for Path {
1861    #[inline]
1862    fn as_ref(&self) -> &Path {
1863        self
1864    }
1865}
1866
1867impl AsRef<Path> for str {
1868    #[inline]
1869    fn as_ref(&self) -> &Path {
1870        Path::new(self)
1871    }
1872}
1873
1874impl AsRef<Path> for Cow<'_, str> {
1875    #[inline]
1876    fn as_ref(&self) -> &Path {
1877        Path::new(self)
1878    }
1879}
1880
1881impl AsRef<Path> for String {
1882    #[inline]
1883    fn as_ref(&self) -> &Path {
1884        Path::new(self)
1885    }
1886}
1887
1888impl AsRef<Path> for PathBuf {
1889    #[inline]
1890    fn as_ref(&self) -> &Path {
1891        self
1892    }
1893}
1894
1895impl<'a> IntoIterator for &'a PathBuf {
1896    type Item = &'a str;
1897    type IntoIter = Iter<'a>;
1898    #[inline]
1899    fn into_iter(self) -> Iter<'a> {
1900        self.iter()
1901    }
1902}
1903
1904impl<'a> IntoIterator for &'a Path {
1905    type Item = &'a str;
1906    type IntoIter = Iter<'a>;
1907    #[inline]
1908    fn into_iter(self) -> Iter<'a> {
1909        self.iter()
1910    }
1911}
1912
1913macro_rules! impl_cmp {
1914    ($lhs:ty, $rhs: ty) => {
1915        impl<'a, 'b> PartialEq<$rhs> for $lhs {
1916            #[inline]
1917            fn eq(&self, other: &$rhs) -> bool {
1918                <Path as PartialEq>::eq(self, other)
1919            }
1920        }
1921
1922        impl<'a, 'b> PartialEq<$lhs> for $rhs {
1923            #[inline]
1924            fn eq(&self, other: &$lhs) -> bool {
1925                <Path as PartialEq>::eq(self, other)
1926            }
1927        }
1928
1929        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
1930            #[inline]
1931            fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
1932                <Path as PartialOrd>::partial_cmp(self, other)
1933            }
1934        }
1935
1936        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
1937            #[inline]
1938            fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
1939                <Path as PartialOrd>::partial_cmp(self, other)
1940            }
1941        }
1942    };
1943}
1944
1945impl_cmp!(PathBuf, Path);
1946impl_cmp!(PathBuf, &'a Path);
1947impl_cmp!(Cow<'a, Path>, Path);
1948impl_cmp!(Cow<'a, Path>, &'b Path);
1949impl_cmp!(Cow<'a, Path>, PathBuf);
1950
1951impl fmt::Display for StripPrefixError {
1952    #[allow(deprecated, deprecated_in_future)]
1953    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1954        self.description().fmt(f)
1955    }
1956}
1957
1958impl Error for StripPrefixError {
1959    #[allow(deprecated)]
1960    fn description(&self) -> &str {
1961        "prefix not found"
1962    }
1963}