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}