Skip to main content

pstr/
istr.rs

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/// Immutable Interning String
25#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
26pub struct IStr(Intern<str>);
27
28impl IStr {
29    /// Create a `IStr` from str slice  
30    ///
31    /// # Example
32    /// ```
33    /// # use pstr::IStr;
34    /// let s = IStr::new("hello world");
35    /// ```
36    #[inline]
37    pub fn new(s: impl AsRef<str>) -> Self {
38        Self(STR_POOL.intern(s.as_ref(), Arc::from))
39    }
40
41    /// Create a `IStr` from `String`  
42    #[inline]
43    pub fn from_string(s: String) -> Self {
44        Self(STR_POOL.intern(s, Arc::from))
45    }
46
47    /// Create a `IStr` from `Box<str>`  
48    #[inline]
49    pub fn from_boxed(s: Box<str>) -> Self {
50        Self(STR_POOL.intern(s, Arc::from))
51    }
52
53    /// Create a `IStr` from `Arc<str>`  
54    #[inline]
55    pub fn from_arc(s: Arc<str>) -> Self {
56        Self(STR_POOL.intern(s, identity))
57    }
58
59    /// Create a `IStr` from `Rc<str>`  
60    #[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    /// Create a `IStr` from `MowStr`  
66    #[inline]
67    pub fn from_mow(s: MowStr) -> Self {
68        s.into()
69    }
70
71    /// Create a `IStr` from custom fn  
72    #[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    /// Extracts a string slice containing the entire `IStr`
80    #[inline]
81    pub fn as_str(&self) -> &str {
82        self.deref()
83    }
84
85    /// Clone a boxed string slice containing the entire `IStr`
86    #[inline]
87    pub fn into_boxed_str(&self) -> Box<str> {
88        self.deref().into()
89    }
90
91    /// Convert to `MowStr`  
92    #[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}