1use alloc::borrow::Cow;
4use alloc::boxed::Box;
5use alloc::string::String;
6use alloc::vec::Vec;
7#[cfg(feature = "std")]
8use std::net::ToSocketAddrs;
9
10use super::HipStr;
11use crate::bytes::HipByt;
12use crate::Backend;
13
14impl<B> AsRef<str> for HipStr<'_, B>
15where
16 B: Backend,
17{
18 #[inline]
19 fn as_ref(&self) -> &str {
20 self.as_str()
21 }
22}
23
24impl<B> AsRef<[u8]> for HipStr<'_, B>
25where
26 B: Backend,
27{
28 #[inline]
29 fn as_ref(&self) -> &[u8] {
30 self.as_bytes()
31 }
32}
33
34#[cfg(feature = "std")]
35impl<B> AsRef<std::ffi::OsStr> for HipStr<'_, B>
36where
37 B: Backend,
38{
39 fn as_ref(&self) -> &std::ffi::OsStr {
40 self.as_str().as_ref()
41 }
42}
43
44#[cfg(feature = "std")]
45impl<B> AsRef<std::path::Path> for HipStr<'_, B>
46where
47 B: Backend,
48{
49 fn as_ref(&self) -> &std::path::Path {
50 self.as_str().as_ref()
51 }
52}
53
54impl<B> From<&str> for HipStr<'_, B>
57where
58 B: Backend,
59{
60 #[inline]
61 fn from(value: &str) -> Self {
62 Self(HipByt::from(value.as_bytes()))
63 }
64}
65
66impl<B> From<Box<str>> for HipStr<'_, B>
67where
68 B: Backend,
69{
70 #[inline]
71 fn from(value: Box<str>) -> Self {
72 Self(HipByt::from(value.into_boxed_bytes().into_vec()))
73 }
74}
75
76impl<B> From<String> for HipStr<'_, B>
77where
78 B: Backend,
79{
80 #[inline]
81 fn from(value: String) -> Self {
82 Self(HipByt::from(value.into_bytes()))
83 }
84}
85
86impl<'borrow, B> From<Cow<'borrow, str>> for HipStr<'borrow, B>
87where
88 B: Backend,
89{
90 #[inline]
91 fn from(value: Cow<'borrow, str>) -> Self {
92 match value {
93 Cow::Borrowed(borrow) => Self::borrowed(borrow),
94 Cow::Owned(owned) => Self::from(owned),
95 }
96 }
97}
98
99impl<B> From<HipStr<'_, B>> for String
100where
101 B: Backend,
102{
103 #[inline]
104 fn from(value: HipStr<B>) -> Self {
105 value
106 .into_string()
107 .unwrap_or_else(|value| value.as_str().into())
108 }
109}
110
111#[cfg(feature = "std")]
112impl<B> From<HipStr<'_, B>> for std::ffi::OsString
113where
114 B: Backend,
115{
116 #[inline]
117 fn from(value: HipStr<B>) -> Self {
118 value
119 .into_string()
120 .unwrap_or_else(|value| value.as_str().into())
121 .into()
122 }
123}
124
125impl<'borrow, B> From<HipStr<'borrow, B>> for HipByt<'borrow, B>
126where
127 B: Backend,
128{
129 #[inline]
130 fn from(value: HipStr<'borrow, B>) -> Self {
131 value.0
132 }
133}
134
135impl<B> From<HipStr<'_, B>> for Vec<u8>
136where
137 B: Backend,
138{
139 #[inline]
140 fn from(value: HipStr<B>) -> Self {
141 value.0.into()
142 }
143}
144
145impl<'borrow, B> From<HipStr<'borrow, B>> for Cow<'borrow, str>
146where
147 B: Backend,
148{
149 #[inline]
150 fn from(value: HipStr<'borrow, B>) -> Self {
151 value
152 .into_borrowed()
153 .map_or_else(|value| Cow::Owned(value.into()), Cow::Borrowed)
154 }
155}
156
157impl<'borrow, B> TryFrom<HipByt<'borrow, B>> for HipStr<'borrow, B>
160where
161 B: Backend,
162{
163 type Error = super::FromUtf8Error<'borrow, B>;
164
165 #[inline]
166 fn try_from(value: HipByt<'borrow, B>) -> Result<Self, Self::Error> {
167 Self::from_utf8(value)
168 }
169}
170
171impl<'borrow, B> TryFrom<&HipByt<'borrow, B>> for HipStr<'borrow, B>
172where
173 B: Backend,
174{
175 type Error = super::FromUtf8Error<'borrow, B>;
176
177 #[inline]
178 fn try_from(value: &HipByt<'borrow, B>) -> Result<Self, Self::Error> {
179 Self::from_utf8(value.clone())
180 }
181}
182
183impl<B> TryFrom<&[u8]> for HipStr<'_, B>
184where
185 B: Backend,
186{
187 type Error = core::str::Utf8Error;
188
189 #[inline]
190 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
191 Ok(Self::from(core::str::from_utf8(value)?))
192 }
193}
194
195impl<B> TryFrom<Vec<u8>> for HipStr<'_, B>
196where
197 B: Backend,
198{
199 type Error = alloc::string::FromUtf8Error;
200
201 #[inline]
202 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
203 let s = String::from_utf8(value)?;
204 Ok(Self::from(s))
205 }
206}
207
208#[cfg(feature = "std")]
209impl<B> ToSocketAddrs for HipStr<'_, B>
210where
211 B: Backend,
212{
213 type Iter = <str as ToSocketAddrs>::Iter;
214
215 fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
216 self.as_str().to_socket_addrs()
217 }
218}
219
220#[cfg(test)]
221mod tests {
222 use alloc::borrow::Cow;
223 use alloc::boxed::Box;
224 use alloc::string::String;
225 use alloc::vec::Vec;
226 use core::ptr;
227 #[cfg(feature = "std")]
228 use std::net::ToSocketAddrs;
229
230 use crate::{HipByt, HipStr};
231
232 #[test]
233 fn test_as_ref() {
234 let a = HipStr::from("abc");
235 assert!(ptr::eq(a.as_str(), a.as_ref()));
236 }
237
238 #[test]
239 fn test_from() {
240 let slice = "abcdefghijklmnopqrstuvwxyz";
241 let string = String::from(slice);
242 let ptr_string = string.as_ptr();
243 let b: Box<str> = slice.into();
244 let ptr_b = b.as_ptr();
245 let c1: Cow<str> = Cow::Borrowed(slice);
246 let c2: Cow<str> = String::from(slice).into();
247 let ptr_c2 = c2.as_ptr();
248
249 let fs = HipStr::from(slice);
250 assert_eq!(fs.as_str(), slice);
251
252 let fv = HipStr::from(string);
253 assert_eq!(fv.as_str(), slice);
254 assert!(ptr::eq(fv.as_ptr(), ptr_string));
255
256 let fv = HipStr::from(b);
257 assert_eq!(fv.as_str(), slice);
258 assert!(ptr::eq(fv.as_ptr(), ptr_b));
259
260 let fc1 = HipStr::from(c1);
261 assert_eq!(fc1.as_str(), slice);
262
263 let fc2 = HipStr::from(c2);
264 assert_eq!(fc2.as_str(), slice);
265 assert!(ptr::eq(fc2.as_ptr(), ptr_c2));
266 }
267
268 #[test]
269 fn test_into_string() {
270 let v = "a".repeat(42); let p = v.as_ptr();
272 let a = HipStr::from(v);
273 let v: String = a.into();
274 assert_eq!(v.as_ptr(), p);
275
276 let a = HipStr::from("abc");
277 let v: String = a.into();
278 assert_eq!(v.as_str(), "abc");
279
280 let a = HipStr::borrowed("abc");
281 let v: String = a.into();
282 assert_eq!(v.as_str(), "abc");
283 }
284
285 #[test]
286 fn test_into_cow() {
287 let h = HipStr::from_static("abc");
288 let c: Cow<'static, str> = h.into();
289 assert_eq!(c, Cow::Borrowed("abc"));
290
291 let h = HipStr::from("abc");
292 let c: Cow<'static, str> = h.into();
293 assert_eq!(c, Cow::<'static, str>::Owned("abc".into()));
294 }
295
296 #[test]
297 #[cfg(feature = "std")]
298 fn into_os_string() {
299 let h = HipStr::from("abc");
300 let os_string: std::ffi::OsString = h.into();
301 assert_eq!(os_string, "abc");
302 }
303
304 #[test]
305 fn test_into_hipbyt() {
306 let v = "a".repeat(42); let p = v.as_ptr();
308 let hs = HipStr::from(v);
309 let hb: HipByt = hs.into();
310 assert_eq!(hb, b"a".repeat(42));
311 assert_eq!(hb.as_ptr(), p);
312
313 let a = HipStr::from("abc");
314 let v: HipByt = a.into();
315 assert_eq!(v, b"abc");
316
317 let a = HipStr::borrowed("abc");
318 let v: HipByt = a.into();
319 assert_eq!(v, b"abc");
320 }
321
322 #[test]
323 fn test_into_vec() {
324 let v = "a".repeat(42); let p = v.as_ptr();
326 let hs = HipStr::from(v);
327 let v: Vec<u8> = hs.into();
328 assert_eq!(v, b"a".repeat(42));
329 assert_eq!(v.as_ptr(), p);
330 }
331
332 #[test]
333 fn test_try_from() {
334 let slice: &[u8] = b"abcdefghijklmnopqrstuvwxyz";
335
336 let hb = HipByt::borrowed(slice);
337 let hs: HipStr = hb.try_into().unwrap();
338 assert_eq!(hs, "abcdefghijklmnopqrstuvwxyz");
339 assert!(hs.is_borrowed());
340
341 let hb = HipByt::from(slice);
342 let hs: HipStr = hb.try_into().unwrap();
343 assert_eq!(hs, "abcdefghijklmnopqrstuvwxyz");
344
345 let hb = HipByt::borrowed(slice);
346 let hs: HipStr = (&hb).try_into().unwrap();
347 assert_eq!(hs, "abcdefghijklmnopqrstuvwxyz");
348
349 let hs: HipStr = slice.try_into().unwrap();
350 assert_eq!(hs, "abcdefghijklmnopqrstuvwxyz");
351
352 let v = b"a".repeat(42);
353 let p = v.as_ptr();
354 let hs: HipStr = v.try_into().unwrap();
355 assert_eq!(hs, "a".repeat(42));
356 assert_eq!(hs.as_ptr(), p);
357 }
358
359 #[test]
360 fn test_try_from_err() {
361 let slice: &[u8] = b"abc\x80";
362 let hb = HipByt::borrowed(slice);
363 assert!(HipStr::try_from(slice).is_err());
364 assert!(HipStr::try_from(slice.to_vec()).is_err());
365 assert!(HipStr::try_from(&hb).is_err());
366 assert!(HipStr::try_from(hb).is_err());
367 }
368
369 #[test]
370 fn as_ref_bytes() {
371 let h = HipStr::from("abc");
372 let b: &[u8] = h.as_ref();
373 assert!(ptr::eq(h.as_bytes(), b));
374 }
375
376 #[cfg(feature = "std")]
377 #[test]
378 fn as_ref_os_str() {
379 let h = HipStr::from("abc");
380 let o: &std::ffi::OsStr = h.as_ref();
381 assert_eq!(o, "abc");
382 assert!(ptr::eq(h.as_str().as_ref(), o));
383 }
384
385 #[cfg(feature = "std")]
386 #[test]
387 fn as_ref_path() {
388 let h = HipStr::from("abc");
389 let p: &std::path::Path = h.as_ref();
390 assert_eq!(p, std::path::Path::new("abc"));
391 assert!(ptr::eq(h.as_str().as_ref(), p));
392 }
393
394 #[cfg(feature = "std")]
395 #[test]
396 fn to_sock_addrs() {
397 let h = HipStr::from("0.0.0.0:80");
398 let v: Vec<_> = h.to_socket_addrs().unwrap().collect();
399 let v2: Vec<_> = "0.0.0.0:80".to_socket_addrs().unwrap().collect();
400 assert_eq!(v, v2);
401 }
402}