#[cfg(feature = "alloc")] use core::{borrow::Borrow, ops::Deref}; #[cfg(feature = "alloc")] use alloc::borrow::ToOwned; #[cfg(feature = "alloc")] use alloc::string::String; #[repr(transparent)] #[derive(Debug)] pub struct Path { inner: str, } impl From<&str> for &Path { fn from(value: &str) -> Self { unsafe { &*(value as *const str as *const Path) } } } impl AsRef for str { fn as_ref(&self) -> &Path { unsafe { &*(self as *const str as *const Path) } } } #[cfg(feature = "alloc")] impl AsRef for String { fn as_ref(&self) -> &Path { self.as_str().as_ref() } } impl AsRef for Path { fn as_ref(&self) -> &Path { self } } impl AsRef for Path { fn as_ref(&self) -> &str { self.as_str() } } impl Path { pub fn new(path: &str) -> &Self { path.as_ref() } pub fn split_path(&self) -> (&str, Option<&Path>) { if let Some((start, end)) = self.inner.split_once("/") { if end.is_empty() { (start, None) } else { (start, Some(end.into())) } } else { (&self.inner, None) } } pub fn as_str(&self) -> &str { &self.inner } pub fn is_absolute(&self) -> bool { self.inner.starts_with("/") } pub fn is_relative(&self) -> bool { !self.is_absolute() } pub fn is_empty(&self) -> bool { self.inner.is_empty() } pub fn is_root(&self) -> bool { self.as_str() == "/" } pub fn starts_with>(&self, other: P) -> bool { let this = self.split_path(); let other = other.as_ref().split_path(); if this.0 == other.0 { if let Some(this) = this.1 && let Some(other) = other.1 { this.starts_with(other) } else { other.1.is_none() } } else { false } } pub fn without>(&self, other: P) -> &Path { let this = self.split_path(); let other = other.as_ref().split_path(); if this.0 == other.0 { match (this.1, other.1) { (None, None) => Path::new(""), (None, Some(_)) => todo!(), (Some(p), None) => p, (Some(this), Some(other)) => this.without(other), } } else { todo!() } } } #[cfg(feature = "alloc")] #[derive(Debug, Hash, PartialEq, Eq)] pub struct PathBuf { inner: String, } #[cfg(feature = "alloc")] impl Deref for PathBuf { type Target = Path; fn deref(&self) -> &Self::Target { self.inner.as_str().into() } } #[cfg(feature = "alloc")] impl AsRef for PathBuf { fn as_ref(&self) -> &Path { self.inner.as_ref() } } #[cfg(feature = "alloc")] impl Borrow for PathBuf { fn borrow(&self) -> &str { &self.inner } } #[cfg(feature = "alloc")] impl From<&str> for PathBuf { fn from(val: &str) -> Self { PathBuf { inner: val.to_owned(), } } } #[cfg(feature = "alloc")] impl From for PathBuf { fn from(val: String) -> Self { PathBuf { inner: val } } }