mod sys;
#[cfg(test)]
mod tests;
use std::borrow::{Borrow, Cow};
use std::cmp;
use std::error::Error;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::{self, FusedIterator};
use std::ops::{self, Deref};
use std::rc::Rc;
use std::str::FromStr;
use std::sync::Arc;
use sys::{is_sep_char, MAIN_SEP_STR, MAIN_SEP};
pub fn is_separator(c: char) -> bool {
is_sep_char(c)
}
pub const MAIN_SEPARATOR: char = sys::MAIN_SEP;
fn iter_after<'a, 'b, I, J>(mut iter: I, mut prefix: J) -> Option<I>
where
I: Iterator<Item = Component<'a>> + Clone,
J: Iterator<Item = Component<'b>>,
{
loop {
let mut iter_next = iter.clone();
match (iter_next.next(), prefix.next()) {
(Some(ref x), Some(ref y)) if x == y => (),
(Some(_), Some(_)) => return None,
(Some(_), None) => return Some(iter),
(None, None) => return Some(iter),
(None, Some(_)) => return None,
}
iter = iter_next;
}
}
fn has_physical_root(path: &str) -> bool {
!path.is_empty() && is_sep_char(path.chars().nth(0).unwrap())
}
fn split_file_at_dot(file: &str) -> (Option<&str>, Option<&str>) {
if file == ".." {
return (Some(file), None);
}
let mut iter = file.rsplitn(2, '.');
let after = iter.next();
let before = iter.next();
if before == Some("") {
(Some(file), None)
} else {
(before, after)
}
}
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
enum State {
StartDir = 1, Body = 2, Done = 3,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Component<'a> {
RootDir,
CurDir,
ParentDir,
Normal(&'a str),
}
impl<'a> Component<'a> {
pub fn as_str(self) -> &'a str {
match self {
Component::RootDir => MAIN_SEP_STR,
Component::CurDir => ".",
Component::ParentDir => "..",
Component::Normal(path) => path,
}
}
}
impl AsRef<str> for Component<'_> {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl AsRef<Path> for Component<'_> {
#[inline]
fn as_ref(&self) -> &Path {
self.as_str().as_ref()
}
}
#[derive(Clone)]
pub struct Components<'a> {
path: &'a str,
has_physical_root: bool,
front: State,
back: State,
}
#[derive(Clone)]
pub struct Iter<'a> {
inner: Components<'a>,
}
impl fmt::Debug for Components<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct DebugHelper<'a>(&'a Path);
impl fmt::Debug for DebugHelper<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.0.components()).finish()
}
}
f.debug_tuple("Components").field(&DebugHelper(self.as_path())).finish()
}
}
impl<'a> Components<'a> {
#[inline]
fn len_before_body(&self) -> usize {
let root = if self.front <= State::StartDir && self.has_physical_root { 1 } else { 0 };
let cur_dir = if self.front <= State::StartDir && self.include_cur_dir() { 1 } else { 0 };
root + cur_dir
}
#[inline]
fn finished(&self) -> bool {
self.front == State::Done || self.back == State::Done || self.front > self.back
}
#[inline]
fn is_sep_char(&self, b: char) -> bool {
is_sep_char(b)
}
pub fn as_path(&self) -> &'a Path {
let mut comps = self.clone();
if comps.front == State::Body {
comps.trim_left();
}
if comps.back == State::Body {
comps.trim_right();
}
Path::from_str(comps.path)
}
fn has_root(&self) -> bool {
self.has_physical_root
}
fn include_cur_dir(&self) -> bool {
if self.has_root() {
return false;
}
let mut iter = self.path.chars();
match (iter.next(), iter.next()) {
(Some('.'), None) => true,
(Some('.'), Some(b)) => self.is_sep_char(b),
_ => false,
}
}
fn parse_single_component<'b>(&self, comp: &'b str) -> Option<Component<'b>> {
match comp {
"." => None, ".." => Some(Component::ParentDir),
"" => None,
_ => Some(Component::Normal(comp)),
}
}
fn parse_next_component(&self) -> (usize, Option<Component<'a>>) {
debug_assert!(self.front == State::Body);
let (extra, comp) = match self.path.chars().position(|b| self.is_sep_char(b)) {
None => (0, self.path),
Some(i) => (1, &self.path[..i]),
};
(comp.len() + extra, self.parse_single_component(comp))
}
fn parse_next_component_back(&self) -> (usize, Option<Component<'a>>) {
debug_assert!(self.back == State::Body);
let start = self.len_before_body();
let path = &self.path[start..];
let (extra, comp) = match path.chars().rev().position(|b| self.is_sep_char(b)).map(|p| path.len() - p - 1) {
None => (0, &self.path[start..]),
Some(i) => (1, &self.path[start + i + 1..]),
};
(comp.len() + extra, self.parse_single_component(comp))
}
fn trim_left(&mut self) {
while !self.path.is_empty() {
let (size, comp) = self.parse_next_component();
if comp.is_some() {
return;
} else {
self.path = &self.path[size..];
}
}
}
fn trim_right(&mut self) {
while self.path.len() > self.len_before_body() {
let (size, comp) = self.parse_next_component_back();
if comp.is_some() {
return;
} else {
self.path = &self.path[..self.path.len() - size];
}
}
}
}
impl AsRef<Path> for Components<'_> {
#[inline]
fn as_ref(&self) -> &Path {
self.as_path()
}
}
impl AsRef<str> for Components<'_> {
#[inline]
fn as_ref(&self) -> &str {
self.as_path().as_str()
}
}
impl fmt::Debug for Iter<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct DebugHelper<'a>(&'a Path);
impl fmt::Debug for DebugHelper<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.0.iter()).finish()
}
}
f.debug_tuple("Iter").field(&DebugHelper(self.as_path())).finish()
}
}
impl<'a> Iter<'a> {
#[inline]
pub fn as_path(&self) -> &'a Path {
self.inner.as_path()
}
}
impl AsRef<Path> for Iter<'_> {
#[inline]
fn as_ref(&self) -> &Path {
self.as_path()
}
}
impl AsRef<str> for Iter<'_> {
#[inline]
fn as_ref(&self) -> &str {
self.as_path().as_str()
}
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a str;
#[inline]
fn next(&mut self) -> Option<&'a str> {
self.inner.next().map(Component::as_str)
}
}
impl<'a> DoubleEndedIterator for Iter<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a str> {
self.inner.next_back().map(Component::as_str)
}
}
impl FusedIterator for Iter<'_> {}
impl<'a> Iterator for Components<'a> {
type Item = Component<'a>;
fn next(&mut self) -> Option<Component<'a>> {
while !self.finished() {
match self.front {
State::StartDir => {
self.front = State::Body;
if self.has_physical_root {
debug_assert!(!self.path.is_empty());
self.path = &self.path[1..];
return Some(Component::RootDir);
} else if self.include_cur_dir() {
debug_assert!(!self.path.is_empty());
self.path = &self.path[1..];
return Some(Component::CurDir);
}
}
State::Body if !self.path.is_empty() => {
let (size, comp) = self.parse_next_component();
self.path = &self.path[size..];
if comp.is_some() {
return comp;
}
}
State::Body => {
self.front = State::Done;
}
State::Done => unreachable!(),
}
}
None
}
}
impl<'a> DoubleEndedIterator for Components<'a> {
fn next_back(&mut self) -> Option<Component<'a>> {
while !self.finished() {
match self.back {
State::Body if self.path.len() > self.len_before_body() => {
let (size, comp) = self.parse_next_component_back();
self.path = &self.path[..self.path.len() - size];
if comp.is_some() {
return comp;
}
}
State::Body => {
self.back = State::StartDir;
}
State::StartDir => {
self.back = State::Done;
if self.has_physical_root {
self.path = &self.path[..self.path.len() - 1];
return Some(Component::RootDir);
} else if self.include_cur_dir() {
self.path = &self.path[..self.path.len() - 1];
return Some(Component::CurDir);
}
}
State::Done => unreachable!(),
}
}
None
}
}
impl FusedIterator for Components<'_> {}
impl<'a> cmp::PartialEq for Components<'a> {
#[inline]
fn eq(&self, other: &Components<'a>) -> bool {
Iterator::eq(self.clone(), other.clone())
}
}
impl cmp::Eq for Components<'_> {}
impl<'a> cmp::PartialOrd for Components<'a> {
#[inline]
fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
Iterator::partial_cmp(self.clone(), other.clone())
}
}
impl cmp::Ord for Components<'_> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
Iterator::cmp(self.clone(), other.clone())
}
}
#[derive(Copy, Clone, Debug)]
pub struct Ancestors<'a> {
next: Option<&'a Path>,
}
impl<'a> Iterator for Ancestors<'a> {
type Item = &'a Path;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let next = self.next;
self.next = next.and_then(Path::parent);
next
}
}
impl FusedIterator for Ancestors<'_> {}
#[derive(Clone)]
#[repr(transparent)]
pub struct PathBuf {
inner: String,
}
impl PathBuf {
#[inline]
fn as_mut_string(&mut self) -> &mut String {
&mut self.inner
}
#[inline]
pub fn new() -> PathBuf {
PathBuf { inner: String::new() }
}
#[inline]
pub fn with_capacity(capacity: usize) -> PathBuf {
PathBuf { inner: String::with_capacity(capacity) }
}
#[inline]
pub fn as_path(&self) -> &Path {
self
}
pub fn push<P: AsRef<Path>>(&mut self, path: P) {
self._push(path.as_ref())
}
fn _push(&mut self, path: &Path) {
let need_sep = self.as_mut_string().chars().last().map(|c| !is_sep_char(c)).unwrap_or(false);
if path.is_absolute() {
self.as_mut_string().truncate(0);
} else if path.has_root() {
self.as_mut_string().truncate(0);
} else if need_sep {
self.inner.push(MAIN_SEP);
}
self.inner.push_str(path.as_str());
}
pub fn pop(&mut self) -> bool {
match self.parent().map(|p| p.as_str().len()) {
Some(len) => {
self.as_mut_string().truncate(len);
true
}
None => false,
}
}
pub fn set_file_name<S: AsRef<str>>(&mut self, file_name: S) {
self._set_file_name(file_name.as_ref())
}
fn _set_file_name(&mut self, file_name: &str) {
if self.file_name().is_some() {
let popped = self.pop();
debug_assert!(popped);
}
self.push(file_name);
}
pub fn set_extension<S: AsRef<str>>(&mut self, extension: S) -> bool {
self._set_extension(extension.as_ref())
}
fn _set_extension(&mut self, extension: &str) -> bool {
let file_stem = match self.file_stem() {
None => return false,
Some(f) => f,
};
let start = self.inner.as_ptr() as usize;
let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
let v = &mut self.inner;
v.truncate(end_file_stem.wrapping_sub(start));
if !extension.is_empty() {
v.reserve_exact(extension.len() + 1);
v.push('.');
v.push_str(extension);
}
true
}
#[inline]
pub fn into_string(self) -> String {
self.inner
}
#[inline]
pub fn into_boxed_path(self) -> Box<Path> {
let rw = Box::into_raw(self.inner.into_boxed_str()) as *mut Path;
unsafe { Box::from_raw(rw) }
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional)
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional)
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit()
}
}
impl From<&Path> for Box<Path> {
fn from(path: &Path) -> Box<Path> {
let boxed: Box<str> = path.inner.into();
let rw = Box::into_raw(boxed) as *mut Path;
unsafe { Box::from_raw(rw) }
}
}
impl From<Cow<'_, Path>> for Box<Path> {
#[inline]
fn from(cow: Cow<'_, Path>) -> Box<Path> {
match cow {
Cow::Borrowed(path) => Box::from(path),
Cow::Owned(path) => Box::from(path),
}
}
}
impl From<Box<Path>> for PathBuf {
#[inline]
fn from(boxed: Box<Path>) -> PathBuf {
boxed.into_path_buf()
}
}
impl From<PathBuf> for Box<Path> {
#[inline]
fn from(p: PathBuf) -> Box<Path> {
p.into_boxed_path()
}
}
impl Clone for Box<Path> {
#[inline]
fn clone(&self) -> Self {
self.to_path_buf().into_boxed_path()
}
}
impl<T: ?Sized + AsRef<str>> From<&T> for PathBuf {
#[inline]
fn from(s: &T) -> PathBuf {
PathBuf::from(s.as_ref().to_string())
}
}
impl From<String> for PathBuf {
#[inline]
fn from(s: String) -> PathBuf {
PathBuf { inner: s }
}
}
impl From<PathBuf> for String {
#[inline]
fn from(path_buf: PathBuf) -> String {
path_buf.inner
}
}
impl FromStr for PathBuf {
type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(PathBuf::from(s))
}
}
impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
let mut buf = PathBuf::new();
buf.extend(iter);
buf
}
}
impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
iter.into_iter().for_each(move |p| self.push(p.as_ref()));
}
}
impl fmt::Debug for PathBuf {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, formatter)
}
}
impl fmt::Display for PathBuf {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, formatter)
}
}
impl ops::Deref for PathBuf {
type Target = Path;
#[inline]
fn deref(&self) -> &Path {
Path::new(&self.inner)
}
}
impl Borrow<Path> for PathBuf {
#[inline]
fn borrow(&self) -> &Path {
self.deref()
}
}
impl Default for PathBuf {
#[inline]
fn default() -> Self {
PathBuf::new()
}
}
impl<'a> From<&'a Path> for Cow<'a, Path> {
#[inline]
fn from(s: &'a Path) -> Cow<'a, Path> {
Cow::Borrowed(s)
}
}
impl<'a> From<PathBuf> for Cow<'a, Path> {
#[inline]
fn from(s: PathBuf) -> Cow<'a, Path> {
Cow::Owned(s)
}
}
impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
#[inline]
fn from(p: &'a PathBuf) -> Cow<'a, Path> {
Cow::Borrowed(p.as_path())
}
}
impl<'a> From<Cow<'a, Path>> for PathBuf {
#[inline]
fn from(p: Cow<'a, Path>) -> Self {
p.into_owned()
}
}
impl From<PathBuf> for Arc<Path> {
#[inline]
fn from(s: PathBuf) -> Arc<Path> {
let arc: Arc<str> = Arc::from(s.into_string());
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
}
}
impl From<&Path> for Arc<Path> {
#[inline]
fn from(s: &Path) -> Arc<Path> {
let arc: Arc<str> = Arc::from(s.as_str());
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Path) }
}
}
impl From<PathBuf> for Rc<Path> {
#[inline]
fn from(s: PathBuf) -> Rc<Path> {
let rc: Rc<str> = Rc::from(s.into_string());
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
}
}
impl From<&Path> for Rc<Path> {
#[inline]
fn from(s: &Path) -> Rc<Path> {
let rc: Rc<str> = Rc::from(s.as_str());
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Path) }
}
}
impl ToOwned for Path {
type Owned = PathBuf;
#[inline]
fn to_owned(&self) -> PathBuf {
self.to_path_buf()
}
}
impl cmp::PartialEq for PathBuf {
#[inline]
fn eq(&self, other: &PathBuf) -> bool {
self.components() == other.components()
}
}
impl Hash for PathBuf {
fn hash<H: Hasher>(&self, h: &mut H) {
self.as_path().hash(h)
}
}
impl cmp::Eq for PathBuf {}
impl cmp::PartialOrd for PathBuf {
#[inline]
fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
self.components().partial_cmp(other.components())
}
}
impl cmp::Ord for PathBuf {
#[inline]
fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
self.components().cmp(other.components())
}
}
impl AsRef<str> for PathBuf {
#[inline]
fn as_ref(&self) -> &str {
&self.inner[..]
}
}
#[repr(transparent)]
pub struct Path {
inner: str,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StripPrefixError(());
impl Path {
fn from_str(s: &str) -> &Path {
Path::new(s)
}
pub fn new<S: AsRef<str> + ?Sized>(s: &S) -> &Path {
unsafe { &*(s.as_ref() as *const str as *const Path) }
}
#[inline]
pub fn as_str(&self) -> &str {
&self.inner
}
#[inline]
pub fn to_str(&self) -> &str {
&self.inner
}
#[inline]
pub fn to_str_cow(&self) -> Cow<'_, str> {
Cow::from(&self.inner)
}
pub fn to_path_buf(&self) -> PathBuf {
PathBuf::from(self.inner.to_string())
}
#[inline]
pub fn is_absolute(&self) -> bool {
self.has_root()
}
#[inline]
pub fn is_relative(&self) -> bool {
!self.is_absolute()
}
#[inline]
pub fn has_root(&self) -> bool {
self.components().has_root()
}
pub fn parent(&self) -> Option<&Path> {
let mut comps = self.components();
let comp = comps.next_back();
comp.and_then(|p| match p {
Component::Normal(_) | Component::CurDir | Component::ParentDir => {
Some(comps.as_path())
}
_ => None,
})
}
#[inline]
pub fn ancestors(&self) -> Ancestors<'_> {
Ancestors { next: Some(&self) }
}
pub fn file_name(&self) -> Option<&str> {
self.components().next_back().and_then(|p| match p {
Component::Normal(p) => Some(p),
_ => None,
})
}
pub fn strip_prefix<P>(&self, base: P) -> Result<&Path, StripPrefixError>
where
P: AsRef<Path>,
{
self._strip_prefix(base.as_ref())
}
fn _strip_prefix(&self, base: &Path) -> Result<&Path, StripPrefixError> {
iter_after(self.components(), base.components())
.map(|c| c.as_path())
.ok_or(StripPrefixError(()))
}
pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
self._starts_with(base.as_ref())
}
fn _starts_with(&self, base: &Path) -> bool {
iter_after(self.components(), base.components()).is_some()
}
pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
self._ends_with(child.as_ref())
}
fn _ends_with(&self, child: &Path) -> bool {
iter_after(self.components().rev(), child.components().rev()).is_some()
}
pub fn file_stem(&self) -> Option<&str> {
self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
}
pub fn extension(&self) -> Option<&str> {
self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
}
#[must_use]
pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
self._join(path.as_ref())
}
fn _join(&self, path: &Path) -> PathBuf {
let mut buf = self.to_path_buf();
buf.push(path);
buf
}
pub fn with_file_name<S: AsRef<str>>(&self, file_name: S) -> PathBuf {
self._with_file_name(file_name.as_ref())
}
fn _with_file_name(&self, file_name: &str) -> PathBuf {
let mut buf = self.to_path_buf();
buf.set_file_name(file_name);
buf
}
pub fn with_extension<S: AsRef<str>>(&self, extension: S) -> PathBuf {
self._with_extension(extension.as_ref())
}
fn _with_extension(&self, extension: &str) -> PathBuf {
let mut buf = self.to_path_buf();
buf.set_extension(extension);
buf
}
pub fn components(&self) -> Components<'_> {
Components {
path: self.as_str(),
has_physical_root: has_physical_root(self.as_str()),
front: State::StartDir,
back: State::Body,
}
}
#[inline]
pub fn iter(&self) -> Iter<'_> {
Iter { inner: self.components() }
}
pub fn into_path_buf(self: Box<Path>) -> PathBuf {
let rw = Box::into_raw(self) as *mut str;
let inner = unsafe { Box::from_raw(rw) };
PathBuf { inner: String::from(inner) }
}
}
impl AsRef<str> for Path {
#[inline]
fn as_ref(&self) -> &str {
&self.inner
}
}
impl fmt::Debug for Path {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.inner, formatter)
}
}
impl fmt::Display for Path {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.inner, formatter)
}
}
impl cmp::PartialEq for Path {
#[inline]
fn eq(&self, other: &Path) -> bool {
self.components().eq(other.components())
}
}
impl Hash for Path {
fn hash<H: Hasher>(&self, h: &mut H) {
for component in self.components() {
component.hash(h);
}
}
}
impl cmp::Eq for Path {}
impl cmp::PartialOrd for Path {
#[inline]
fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
self.components().partial_cmp(other.components())
}
}
impl cmp::Ord for Path {
#[inline]
fn cmp(&self, other: &Path) -> cmp::Ordering {
self.components().cmp(other.components())
}
}
impl AsRef<Path> for Path {
#[inline]
fn as_ref(&self) -> &Path {
self
}
}
impl AsRef<Path> for str {
#[inline]
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
impl AsRef<Path> for Cow<'_, str> {
#[inline]
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
impl AsRef<Path> for String {
#[inline]
fn as_ref(&self) -> &Path {
Path::new(self)
}
}
impl AsRef<Path> for PathBuf {
#[inline]
fn as_ref(&self) -> &Path {
self
}
}
impl<'a> IntoIterator for &'a PathBuf {
type Item = &'a str;
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Iter<'a> {
self.iter()
}
}
impl<'a> IntoIterator for &'a Path {
type Item = &'a str;
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Iter<'a> {
self.iter()
}
}
macro_rules! impl_cmp {
($lhs:ty, $rhs: ty) => {
impl<'a, 'b> PartialEq<$rhs> for $lhs {
#[inline]
fn eq(&self, other: &$rhs) -> bool {
<Path as PartialEq>::eq(self, other)
}
}
impl<'a, 'b> PartialEq<$lhs> for $rhs {
#[inline]
fn eq(&self, other: &$lhs) -> bool {
<Path as PartialEq>::eq(self, other)
}
}
impl<'a, 'b> PartialOrd<$rhs> for $lhs {
#[inline]
fn partial_cmp(&self, other: &$rhs) -> Option<cmp::Ordering> {
<Path as PartialOrd>::partial_cmp(self, other)
}
}
impl<'a, 'b> PartialOrd<$lhs> for $rhs {
#[inline]
fn partial_cmp(&self, other: &$lhs) -> Option<cmp::Ordering> {
<Path as PartialOrd>::partial_cmp(self, other)
}
}
};
}
impl_cmp!(PathBuf, Path);
impl_cmp!(PathBuf, &'a Path);
impl_cmp!(Cow<'a, Path>, Path);
impl_cmp!(Cow<'a, Path>, &'b Path);
impl_cmp!(Cow<'a, Path>, PathBuf);
impl fmt::Display for StripPrefixError {
#[allow(deprecated, deprecated_in_future)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.description().fmt(f)
}
}
impl Error for StripPrefixError {
#[allow(deprecated)]
fn description(&self) -> &str {
"prefix not found"
}
}