1 | /// A UTF-8-encoded fixed string |
2 | /// |
3 | /// <div class="warning"> |
4 | /// |
5 | /// **NOTE:** To support dynamic values (i.e. `String`), enable the `string` |
6 | /// feature |
7 | /// |
8 | /// </div> |
9 | #[derive (Default, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] |
10 | pub struct Str { |
11 | name: Inner, |
12 | } |
13 | |
14 | impl Str { |
15 | #[cfg (feature = "string" )] |
16 | pub(crate) fn from_string(name: String) -> Self { |
17 | Self { |
18 | name: Inner::from_string(name), |
19 | } |
20 | } |
21 | |
22 | #[cfg (feature = "string" )] |
23 | pub(crate) fn from_ref(name: &str) -> Self { |
24 | Self { |
25 | name: Inner::from_ref(name), |
26 | } |
27 | } |
28 | |
29 | pub(crate) fn from_static_ref(name: &'static str) -> Self { |
30 | Self { |
31 | name: Inner::from_static_ref(name), |
32 | } |
33 | } |
34 | |
35 | pub(crate) fn into_inner(self) -> Inner { |
36 | self.name |
37 | } |
38 | |
39 | /// Get the raw string of the `Str` |
40 | pub fn as_str(&self) -> &str { |
41 | self.name.as_str() |
42 | } |
43 | } |
44 | |
45 | impl From<&'_ Str> for Str { |
46 | fn from(id: &'_ Str) -> Self { |
47 | id.clone() |
48 | } |
49 | } |
50 | |
51 | #[cfg (feature = "string" )] |
52 | impl From<String> for Str { |
53 | fn from(name: String) -> Self { |
54 | Self::from_string(name) |
55 | } |
56 | } |
57 | |
58 | #[cfg (feature = "string" )] |
59 | impl From<&'_ String> for Str { |
60 | fn from(name: &'_ String) -> Self { |
61 | Self::from_ref(name.as_str()) |
62 | } |
63 | } |
64 | |
65 | impl From<&'static str> for Str { |
66 | fn from(name: &'static str) -> Self { |
67 | Self::from_static_ref(name) |
68 | } |
69 | } |
70 | |
71 | impl From<&'_ &'static str> for Str { |
72 | fn from(name: &'_ &'static str) -> Self { |
73 | Self::from_static_ref(name) |
74 | } |
75 | } |
76 | |
77 | impl From<Str> for String { |
78 | fn from(name: Str) -> Self { |
79 | name.name.into_string() |
80 | } |
81 | } |
82 | |
83 | impl From<Str> for Vec<u8> { |
84 | fn from(name: Str) -> Self { |
85 | String::from(name).into() |
86 | } |
87 | } |
88 | |
89 | impl From<Str> for std::ffi::OsString { |
90 | fn from(name: Str) -> Self { |
91 | String::from(name).into() |
92 | } |
93 | } |
94 | |
95 | impl From<Str> for std::path::PathBuf { |
96 | fn from(name: Str) -> Self { |
97 | String::from(name).into() |
98 | } |
99 | } |
100 | |
101 | impl std::fmt::Display for Str { |
102 | #[inline ] |
103 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
104 | std::fmt::Display::fmt(self.as_str(), f) |
105 | } |
106 | } |
107 | |
108 | impl std::fmt::Debug for Str { |
109 | #[inline ] |
110 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
111 | std::fmt::Debug::fmt(self.as_str(), f) |
112 | } |
113 | } |
114 | |
115 | impl std::ops::Deref for Str { |
116 | type Target = str; |
117 | |
118 | #[inline ] |
119 | fn deref(&self) -> &str { |
120 | self.as_str() |
121 | } |
122 | } |
123 | |
124 | impl AsRef<str> for Str { |
125 | #[inline ] |
126 | fn as_ref(&self) -> &str { |
127 | self.as_str() |
128 | } |
129 | } |
130 | |
131 | impl AsRef<[u8]> for Str { |
132 | #[inline ] |
133 | fn as_ref(&self) -> &[u8] { |
134 | self.as_bytes() |
135 | } |
136 | } |
137 | |
138 | impl AsRef<std::ffi::OsStr> for Str { |
139 | #[inline ] |
140 | fn as_ref(&self) -> &std::ffi::OsStr { |
141 | (**self).as_ref() |
142 | } |
143 | } |
144 | |
145 | impl AsRef<std::path::Path> for Str { |
146 | #[inline ] |
147 | fn as_ref(&self) -> &std::path::Path { |
148 | std::path::Path::new(self) |
149 | } |
150 | } |
151 | |
152 | impl std::borrow::Borrow<str> for Str { |
153 | #[inline ] |
154 | fn borrow(&self) -> &str { |
155 | self.as_str() |
156 | } |
157 | } |
158 | |
159 | impl PartialEq<str> for Str { |
160 | #[inline ] |
161 | fn eq(&self, other: &str) -> bool { |
162 | PartialEq::eq(self.as_str(), other) |
163 | } |
164 | } |
165 | impl PartialEq<Str> for str { |
166 | #[inline ] |
167 | fn eq(&self, other: &Str) -> bool { |
168 | PartialEq::eq(self, other.as_str()) |
169 | } |
170 | } |
171 | |
172 | impl PartialEq<&'_ str> for Str { |
173 | #[inline ] |
174 | fn eq(&self, other: &&str) -> bool { |
175 | PartialEq::eq(self.as_str(), *other) |
176 | } |
177 | } |
178 | impl PartialEq<Str> for &'_ str { |
179 | #[inline ] |
180 | fn eq(&self, other: &Str) -> bool { |
181 | PartialEq::eq(*self, other.as_str()) |
182 | } |
183 | } |
184 | |
185 | impl PartialEq<std::ffi::OsStr> for Str { |
186 | #[inline ] |
187 | fn eq(&self, other: &std::ffi::OsStr) -> bool { |
188 | PartialEq::eq(self.as_str(), other) |
189 | } |
190 | } |
191 | impl PartialEq<Str> for std::ffi::OsStr { |
192 | #[inline ] |
193 | fn eq(&self, other: &Str) -> bool { |
194 | PartialEq::eq(self, other.as_str()) |
195 | } |
196 | } |
197 | |
198 | impl PartialEq<&'_ std::ffi::OsStr> for Str { |
199 | #[inline ] |
200 | fn eq(&self, other: &&std::ffi::OsStr) -> bool { |
201 | PartialEq::eq(self.as_str(), *other) |
202 | } |
203 | } |
204 | impl PartialEq<Str> for &'_ std::ffi::OsStr { |
205 | #[inline ] |
206 | fn eq(&self, other: &Str) -> bool { |
207 | PartialEq::eq(*self, other.as_str()) |
208 | } |
209 | } |
210 | |
211 | impl PartialEq<String> for Str { |
212 | #[inline ] |
213 | fn eq(&self, other: &String) -> bool { |
214 | PartialEq::eq(self.as_str(), other.as_str()) |
215 | } |
216 | } |
217 | impl PartialEq<Str> for String { |
218 | #[inline ] |
219 | fn eq(&self, other: &Str) -> bool { |
220 | PartialEq::eq(self.as_str(), other.as_str()) |
221 | } |
222 | } |
223 | |
224 | #[cfg (feature = "string" )] |
225 | pub(crate) mod inner { |
226 | #[derive (Clone)] |
227 | pub(crate) enum Inner { |
228 | Static(&'static str), |
229 | Owned(Box<str>), |
230 | } |
231 | |
232 | impl Inner { |
233 | pub(crate) fn from_string(name: String) -> Self { |
234 | Self::Owned(name.into_boxed_str()) |
235 | } |
236 | |
237 | pub(crate) fn from_ref(name: &str) -> Self { |
238 | Self::Owned(Box::from(name)) |
239 | } |
240 | |
241 | pub(crate) fn from_static_ref(name: &'static str) -> Self { |
242 | Self::Static(name) |
243 | } |
244 | |
245 | pub(crate) fn as_str(&self) -> &str { |
246 | match self { |
247 | Self::Static(s) => s, |
248 | Self::Owned(s) => s.as_ref(), |
249 | } |
250 | } |
251 | |
252 | pub(crate) fn into_string(self) -> String { |
253 | match self { |
254 | Self::Static(s) => s.to_owned(), |
255 | Self::Owned(s) => s.into(), |
256 | } |
257 | } |
258 | } |
259 | } |
260 | |
261 | #[cfg (not(feature = "string" ))] |
262 | pub(crate) mod inner { |
263 | #[derive (Clone)] |
264 | pub(crate) struct Inner(pub(crate) &'static str); |
265 | |
266 | impl Inner { |
267 | pub(crate) fn from_static_ref(name: &'static str) -> Self { |
268 | Self(name) |
269 | } |
270 | |
271 | pub(crate) fn as_str(&self) -> &str { |
272 | self.0 |
273 | } |
274 | |
275 | pub(crate) fn into_string(self) -> String { |
276 | self.as_str().to_owned() |
277 | } |
278 | } |
279 | } |
280 | |
281 | pub(crate) use inner::Inner; |
282 | |
283 | impl Default for Inner { |
284 | fn default() -> Self { |
285 | Self::from_static_ref(name:"" ) |
286 | } |
287 | } |
288 | |
289 | impl PartialEq for Inner { |
290 | fn eq(&self, other: &Inner) -> bool { |
291 | self.as_str() == other.as_str() |
292 | } |
293 | } |
294 | |
295 | impl PartialOrd for Inner { |
296 | fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { |
297 | Some(self.cmp(other)) |
298 | } |
299 | } |
300 | |
301 | impl Ord for Inner { |
302 | fn cmp(&self, other: &Inner) -> std::cmp::Ordering { |
303 | self.as_str().cmp(other.as_str()) |
304 | } |
305 | } |
306 | |
307 | impl Eq for Inner {} |
308 | |
309 | impl std::hash::Hash for Inner { |
310 | #[inline ] |
311 | fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
312 | self.as_str().hash(state); |
313 | } |
314 | } |
315 | |