use alloc::{borrow::Cow, string::String};
use core::fmt;
mod sealed {
pub trait Sealed {}
}
pub trait PathLike: sealed::Sealed {
fn to_string_lossy(&self) -> Cow<'_, str>;
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PathLikeRef<'a>(&'a path_like_impls::PathInner);
impl fmt::Debug for PathLikeRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self.0, f)
}
}
impl<'a> From<&'a str> for PathLikeRef<'a> {
fn from(value: &'a str) -> Self {
cfg_if::cfg_if! {
if #[cfg(std)] {
Self(std::path::Path::new(value))
} else {
Self(value)
}
}
}
}
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PathLikeOwned(<path_like_impls::PathInner as alloc::borrow::ToOwned>::Owned);
impl fmt::Debug for PathLikeOwned {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, f)
}
}
impl From<String> for PathLikeOwned {
fn from(value: String) -> Self {
cfg_if::cfg_if! {
if #[cfg(std)] {
Self(value.into())
} else {
Self(value)
}
}
}
}
#[cfg(std)]
mod path_like_impls {
use alloc::borrow::Cow;
use std::path::Path;
use super::{sealed, PathLike};
pub(super) type PathInner = Path;
impl<T: AsRef<Path> + ?Sized> PathLike for T {
fn to_string_lossy(&self) -> Cow<'_, str> {
self.as_ref().to_string_lossy()
}
}
impl<T: AsRef<Path> + ?Sized> sealed::Sealed for T {}
}
#[cfg(no_std)]
mod path_like_impls {
use alloc::{borrow::Cow, string::String};
use core::borrow::Borrow;
use super::{sealed, PathLike, PathLikeOwned, PathLikeRef};
pub(super) type PathInner = str;
impl PathLike for String {
fn to_string_lossy(&self) -> Cow<'_, str> {
Cow::Borrowed(self.as_str())
}
}
impl sealed::Sealed for String {}
impl PathLike for str {
fn to_string_lossy(&self) -> Cow<'_, str> {
Cow::Borrowed(self)
}
}
impl sealed::Sealed for str {}
impl PathLike for Cow<'_, str> {
fn to_string_lossy(&self) -> Cow<'_, str> {
Cow::Borrowed(self.borrow())
}
}
impl sealed::Sealed for Cow<'_, str> {}
impl<T: PathLike + ?Sized> PathLike for &T {
fn to_string_lossy(&self) -> Cow<'_, str> {
(*self).to_string_lossy()
}
}
impl<T: PathLike + ?Sized> sealed::Sealed for &T {}
impl PathLike for PathLikeRef<'_> {
fn to_string_lossy(&self) -> Cow<'_, str> {
Cow::Borrowed(self.0)
}
}
impl sealed::Sealed for PathLikeRef<'_> {}
impl PathLike for PathLikeOwned {
fn to_string_lossy(&self) -> Cow<'_, str> {
Cow::Borrowed(self.0.borrow())
}
}
impl sealed::Sealed for PathLikeOwned {}
}
#[cfg(std)]
mod path_like_owned_std_impls {
use std::path::{Path, PathBuf};
use super::PathLikeOwned;
impl AsRef<Path> for PathLikeOwned {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}
impl From<PathBuf> for PathLikeOwned {
fn from(value: PathBuf) -> Self {
Self(value)
}
}
impl From<PathLikeOwned> for PathBuf {
fn from(value: PathLikeOwned) -> Self {
value.0
}
}
impl AsRef<PathBuf> for PathLikeOwned {
fn as_ref(&self) -> &PathBuf {
&self.0
}
}
}
#[cfg(std)]
mod path_like_ref_std_impls {
use std::path::Path;
use super::PathLikeRef;
impl AsRef<Path> for PathLikeRef<'_> {
fn as_ref(&self) -> &Path {
self.0
}
}
impl<'a> From<&'a Path> for PathLikeRef<'a> {
fn from(value: &'a Path) -> Self {
Self(value)
}
}
impl<'a> From<PathLikeRef<'a>> for &'a Path {
fn from(value: PathLikeRef<'a>) -> Self {
value.0
}
}
}