1use std::{
2 borrow::{Borrow, Cow},
3 convert::identity,
4 error::Error,
5 ffi::{OsStr, OsString},
6 hash::{self, Hash},
7 iter::FromIterator,
8 net::ToSocketAddrs,
9 ops::{Deref, Index},
10 path::{Path, PathBuf},
11 rc::Rc,
12 slice::SliceIndex,
13 str::{self, FromStr},
14 string::ParseError,
15 sync::Arc,
16};
17
18use crate::{
19 intern::Interned,
20 pool::{Intern, STR_POOL},
21 MowStr,
22};
23
24#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
26pub struct IStr(Intern<str>);
27
28impl IStr {
29 #[inline]
37 pub fn new(s: impl AsRef<str>) -> Self {
38 Self(STR_POOL.intern(s.as_ref(), Arc::from))
39 }
40
41 #[inline]
43 pub fn from_string(s: String) -> Self {
44 Self(STR_POOL.intern(s, Arc::from))
45 }
46
47 #[inline]
49 pub fn from_boxed(s: Box<str>) -> Self {
50 Self(STR_POOL.intern(s, Arc::from))
51 }
52
53 #[inline]
55 pub fn from_arc(s: Arc<str>) -> Self {
56 Self(STR_POOL.intern(s, identity))
57 }
58
59 #[inline]
61 pub fn from_rc(s: Rc<str>) -> Self {
62 Self(STR_POOL.intern(s, |s| Arc::from(s.to_string())))
63 }
64
65 #[inline]
67 pub fn from_mow(s: MowStr) -> Self {
68 s.into()
69 }
70
71 #[inline]
73 pub fn from_to_arc<S: AsRef<str>>(s: S, to_arc: impl FnOnce(S) -> Arc<str>) -> Self {
74 Self(STR_POOL.intern(s, to_arc))
75 }
76}
77
78impl IStr {
79 #[inline]
81 pub fn as_str(&self) -> &str {
82 self.deref()
83 }
84
85 #[inline]
87 pub fn into_boxed_str(&self) -> Box<str> {
88 self.deref().into()
89 }
90
91 #[inline]
93 pub fn into_mut(&self) -> MowStr {
94 MowStr::from(self.clone())
95 }
96}
97
98unsafe impl Interned for IStr {}
99
100impl Deref for IStr {
101 type Target = str;
102
103 #[inline]
104 fn deref(&self) -> &Self::Target {
105 self.as_ref()
106 }
107}
108
109impl FromStr for IStr {
110 type Err = ParseError;
111
112 #[inline]
113 fn from_str(s: &str) -> Result<Self, Self::Err> {
114 Ok(Self::new(s))
115 }
116}
117
118impl AsRef<[u8]> for IStr {
119 #[inline]
120 fn as_ref(&self) -> &[u8] {
121 self.deref().as_bytes()
122 }
123}
124
125impl AsRef<str> for IStr {
126 #[inline]
127 fn as_ref(&self) -> &str {
128 self.0.get()
129 }
130}
131
132impl AsRef<OsStr> for IStr {
133 #[inline]
134 fn as_ref(&self) -> &OsStr {
135 self.deref().as_ref()
136 }
137}
138
139impl AsRef<Path> for IStr {
140 #[inline]
141 fn as_ref(&self) -> &Path {
142 self.deref().as_ref()
143 }
144}
145
146impl<I: SliceIndex<str>> Index<I> for IStr {
147 type Output = <I as SliceIndex<str>>::Output;
148
149 #[inline]
150 fn index(&self, index: I) -> &Self::Output {
151 self.deref().index(index)
152 }
153}
154
155impl Hash for IStr {
156 #[inline]
157 fn hash<H: hash::Hasher>(&self, state: &mut H) {
158 self.deref().hash(state)
159 }
160}
161
162impl Borrow<str> for IStr {
163 #[inline]
164 fn borrow(&self) -> &str {
165 self.deref()
166 }
167}
168
169impl From<&'_ String> for IStr {
170 #[inline]
171 fn from(s: &'_ String) -> Self {
172 Self::new(s)
173 }
174}
175
176impl From<&'_ str> for IStr {
177 #[inline]
178 fn from(s: &'_ str) -> Self {
179 Self::new(s)
180 }
181}
182
183impl From<&'_ mut str> for IStr {
184 #[inline]
185 fn from(s: &'_ mut str) -> Self {
186 Self::new(s)
187 }
188}
189
190impl From<char> for IStr {
191 #[inline]
192 fn from(c: char) -> Self {
193 let mut tmp = [0; 4];
194 Self::new(c.encode_utf8(&mut tmp))
195 }
196}
197
198impl From<Box<str>> for IStr {
199 #[inline]
200 fn from(s: Box<str>) -> Self {
201 Self::from_boxed(s)
202 }
203}
204
205impl From<Arc<str>> for IStr {
206 #[inline]
207 fn from(s: Arc<str>) -> Self {
208 Self::from_arc(s)
209 }
210}
211
212impl From<Rc<str>> for IStr {
213 #[inline]
214 fn from(s: Rc<str>) -> Self {
215 Self::from_rc(s)
216 }
217}
218
219impl<'a> From<Cow<'a, str>> for IStr {
220 #[inline]
221 fn from(s: Cow<'a, str>) -> Self {
222 match s {
223 Cow::Borrowed(v) => Self::new(v),
224 Cow::Owned(v) => Self::from_string(v),
225 }
226 }
227}
228
229impl<'a> FromIterator<&'a char> for IStr {
230 #[inline]
231 fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
232 Self::from_string(String::from_iter(iter))
233 }
234}
235
236impl<'a> FromIterator<&'a str> for IStr {
237 #[inline]
238 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
239 Self::from_string(String::from_iter(iter))
240 }
241}
242
243impl FromIterator<Box<str>> for IStr {
244 #[inline]
245 fn from_iter<T: IntoIterator<Item = Box<str>>>(iter: T) -> Self {
246 Self::from_string(String::from_iter(iter))
247 }
248}
249
250impl<'a> FromIterator<Cow<'a, str>> for IStr {
251 #[inline]
252 fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
253 Self::from_string(String::from_iter(iter))
254 }
255}
256
257impl FromIterator<String> for IStr {
258 #[inline]
259 fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
260 Self::from_string(String::from_iter(iter))
261 }
262}
263
264impl FromIterator<char> for IStr {
265 #[inline]
266 fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
267 Self::from_string(String::from_iter(iter))
268 }
269}
270
271impl ToSocketAddrs for IStr {
272 type Iter = <str as ToSocketAddrs>::Iter;
273
274 #[inline]
275 fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
276 ToSocketAddrs::to_socket_addrs(self.deref())
277 }
278}
279
280impl From<IStr> for Box<str> {
281 #[inline]
282 fn from(v: IStr) -> Self {
283 Self::from(v.deref())
284 }
285}
286
287impl From<IStr> for Vec<u8> {
288 #[inline]
289 fn from(v: IStr) -> Self {
290 Self::from(v.deref())
291 }
292}
293
294impl From<IStr> for Arc<str> {
295 #[inline]
296 fn from(v: IStr) -> Self {
297 Self::from(v.deref())
298 }
299}
300
301impl From<IStr> for Rc<str> {
302 #[inline]
303 fn from(v: IStr) -> Self {
304 Self::from(v.deref())
305 }
306}
307
308impl<'a> From<IStr> for Cow<'a, str> {
309 #[inline]
310 fn from(v: IStr) -> Self {
311 Cow::Owned(v.to_string())
312 }
313}
314
315impl<'a> From<&'a IStr> for Cow<'a, str> {
316 #[inline]
317 fn from(v: &'a IStr) -> Self {
318 Cow::Borrowed(v.deref())
319 }
320}
321
322impl ToString for IStr {
323 fn to_string(&self) -> String {
324 self.deref().to_string()
325 }
326}
327
328impl From<IStr> for Box<dyn Error> {
329 #[inline]
330 fn from(v: IStr) -> Self {
331 Self::from(v.deref())
332 }
333}
334
335impl From<IStr> for Box<dyn Error + Send + Sync> {
336 #[inline]
337 fn from(v: IStr) -> Self {
338 Self::from(v.deref())
339 }
340}
341
342impl From<IStr> for OsString {
343 #[inline]
344 fn from(v: IStr) -> Self {
345 Self::from(v.deref())
346 }
347}
348
349impl From<IStr> for PathBuf {
350 #[inline]
351 fn from(v: IStr) -> Self {
352 Self::from(v.deref())
353 }
354}
355
356impl From<IStr> for String {
357 #[inline]
358 fn from(v: IStr) -> Self {
359 v.to_string()
360 }
361}
362
363impl From<String> for IStr {
364 fn from(v: String) -> Self {
365 Self::from_string(v)
366 }
367}
368
369impl PartialEq<str> for IStr {
370 fn eq(&self, other: &str) -> bool {
371 self.deref() == other
372 }
373}
374
375impl PartialEq<&str> for IStr {
376 fn eq(&self, other: &&str) -> bool {
377 self.deref() == *other
378 }
379}
380
381impl PartialEq<String> for IStr {
382 fn eq(&self, other: &String) -> bool {
383 self.deref() == *other
384 }
385}
386
387impl PartialEq<OsStr> for IStr {
388 fn eq(&self, other: &OsStr) -> bool {
389 self.deref() == other
390 }
391}
392
393impl PartialEq<&OsStr> for IStr {
394 fn eq(&self, other: &&OsStr) -> bool {
395 self.deref() == *other
396 }
397}
398
399impl PartialEq<OsString> for IStr {
400 fn eq(&self, other: &OsString) -> bool {
401 self.deref() == *other
402 }
403}
404
405#[cfg(test)]
406mod tests {
407 use super::*;
408
409 #[test]
410 fn test_1() {
411 let s = IStr::new("asd");
412 assert_eq!(s, "asd");
413 }
414
415 #[test]
416 fn test_2() {
417 let a = IStr::new("asd");
418 let b = IStr::new("asd");
419 assert_eq!(a, b);
420 }
421
422 #[test]
423 fn test_3() {
424 let a = IStr::new("asd");
425 let b = IStr::new("123");
426 assert_ne!(a, b);
427 }
428}