1use alloc::{borrow::Cow, string::String};
15use core::fmt;
16
17mod sealed {
18    pub trait Sealed {}
20}
21
22pub trait PathLike: sealed::Sealed {
35    fn to_string_lossy(&self) -> Cow<'_, str>;
36}
37
38#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
44pub struct PathLikeRef<'a>(&'a path_like_impls::PathInner);
45
46impl fmt::Debug for PathLikeRef<'_> {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        fmt::Debug::fmt(self.0, f)
49    }
50}
51
52impl<'a> From<&'a str> for PathLikeRef<'a> {
53    fn from(value: &'a str) -> Self {
54        cfg_if::cfg_if! {
55            if #[cfg(std)] {
56                Self(std::path::Path::new(value))
57            } else {
58                Self(value)
59            }
60        }
61    }
62}
63
64#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
70pub struct PathLikeOwned(<path_like_impls::PathInner as alloc::borrow::ToOwned>::Owned);
71
72impl fmt::Debug for PathLikeOwned {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        fmt::Debug::fmt(&self.0, f)
75    }
76}
77
78impl From<String> for PathLikeOwned {
79    fn from(value: String) -> Self {
80        cfg_if::cfg_if! {
81            if #[cfg(std)] {
82                Self(value.into())
83            } else {
84                Self(value)
85            }
86        }
87    }
88}
89
90#[cfg(std)]
91mod path_like_impls {
92    use alloc::borrow::Cow;
98    use std::path::Path;
99
100    use super::{sealed, PathLike};
101
102    pub(super) type PathInner = Path;
103
104    impl<T: AsRef<Path> + ?Sized> PathLike for T {
105        fn to_string_lossy(&self) -> Cow<'_, str> {
106            self.as_ref().to_string_lossy()
107        }
108    }
109
110    impl<T: AsRef<Path> + ?Sized> sealed::Sealed for T {}
111}
112
113#[cfg(no_std)]
114mod path_like_impls {
115    use alloc::{borrow::Cow, string::String};
125    use core::borrow::Borrow;
126
127    use super::{sealed, PathLike, PathLikeOwned, PathLikeRef};
128
129    pub(super) type PathInner = str;
130
131    impl PathLike for String {
132        fn to_string_lossy(&self) -> Cow<'_, str> {
133            Cow::Borrowed(self.as_str())
134        }
135    }
136
137    impl sealed::Sealed for String {}
138
139    impl PathLike for str {
140        fn to_string_lossy(&self) -> Cow<'_, str> {
141            Cow::Borrowed(self)
142        }
143    }
144
145    impl sealed::Sealed for str {}
146
147    impl PathLike for Cow<'_, str> {
148        fn to_string_lossy(&self) -> Cow<'_, str> {
149            Cow::Borrowed(self.borrow())
150        }
151    }
152
153    impl sealed::Sealed for Cow<'_, str> {}
154
155    impl<T: PathLike + ?Sized> PathLike for &T {
156        fn to_string_lossy(&self) -> Cow<'_, str> {
157            (*self).to_string_lossy()
158        }
159    }
160
161    impl<T: PathLike + ?Sized> sealed::Sealed for &T {}
162
163    impl PathLike for PathLikeRef<'_> {
164        fn to_string_lossy(&self) -> Cow<'_, str> {
165            Cow::Borrowed(self.0)
166        }
167    }
168
169    impl sealed::Sealed for PathLikeRef<'_> {}
170
171    impl PathLike for PathLikeOwned {
172        fn to_string_lossy(&self) -> Cow<'_, str> {
173            Cow::Borrowed(self.0.borrow())
174        }
175    }
176
177    impl sealed::Sealed for PathLikeOwned {}
178}
179
180#[cfg(std)]
181mod path_like_owned_std_impls {
182    use std::path::{Path, PathBuf};
185
186    use super::PathLikeOwned;
187
188    impl AsRef<Path> for PathLikeOwned {
189        fn as_ref(&self) -> &Path {
190            self.0.as_ref()
191        }
192    }
193
194    impl From<PathBuf> for PathLikeOwned {
195        fn from(value: PathBuf) -> Self {
196            Self(value)
197        }
198    }
199
200    impl From<PathLikeOwned> for PathBuf {
201        fn from(value: PathLikeOwned) -> Self {
202            value.0
203        }
204    }
205
206    impl AsRef<PathBuf> for PathLikeOwned {
207        fn as_ref(&self) -> &PathBuf {
208            &self.0
209        }
210    }
211}
212
213#[cfg(std)]
214mod path_like_ref_std_impls {
215    use std::path::Path;
218
219    use super::PathLikeRef;
220
221    impl AsRef<Path> for PathLikeRef<'_> {
222        fn as_ref(&self) -> &Path {
223            self.0
224        }
225    }
226
227    impl<'a> From<&'a Path> for PathLikeRef<'a> {
228        fn from(value: &'a Path) -> Self {
229            Self(value)
230        }
231    }
232
233    impl<'a> From<PathLikeRef<'a>> for &'a Path {
234        fn from(value: PathLikeRef<'a>) -> Self {
235            value.0
236        }
237    }
238}