heap_slice/
string.rs

1use core::borrow::{Borrow, BorrowMut};
2use core::ops::{Deref, DerefMut};
3use core::hash::{Hash, Hasher};
4use core::cmp::Ordering;
5use core::{str, fmt};
6
7/// Basically [`Box<str>`](alloc::boxed::Box), but smaller.
8#[derive(Default, Clone)]
9pub struct HeapStr(crate::HeapSlice<u8>);
10
11impl HeapStr {
12    /// Attempts to construct a new [`HeapStr`] from its underlying [`HeapSlice<u8>`](crate::HeapSlice) container.
13    /// No allocations are performed.
14    pub fn from_utf8(content: crate::HeapSlice<u8>) -> Result<Self, core::str::Utf8Error> {
15        Ok(str::from_utf8(&content)?.into())
16    }
17    /// As [`HeapStr::from_utf8`], but does not perform its UTF-8 conformance check.
18    pub unsafe fn from_utf8_unchecked(content: crate::HeapSlice<u8>) -> Self {
19        str::from_utf8_unchecked(&content).into()
20    }
21    /// Extracts the underlying [`HeapSlice<u8>`](crate::HeapSlice) container.
22    pub fn into_bytes(self) -> crate::HeapSlice<u8> {
23        self.0
24    }
25}
26
27impl From<&str> for HeapStr {
28    fn from(value: &str) -> Self {
29        Self(value.as_bytes().into())
30    }
31}
32
33impl Deref for HeapStr {
34    type Target = str;
35    fn deref(&self) -> &Self::Target {
36        unsafe {
37            str::from_utf8_unchecked(&self.0)
38        }
39    }
40}
41
42impl DerefMut for HeapStr {
43    fn deref_mut(&mut self) -> &mut Self::Target {
44        unsafe {
45            str::from_utf8_unchecked_mut(&mut self.0)
46        }
47    }
48}
49
50impl AsRef<str> for HeapStr {
51    fn as_ref(&self) -> &str {
52        self
53    }
54}
55
56impl AsMut<str> for HeapStr {
57    fn as_mut(&mut self) -> &mut str {
58        self
59    }
60}
61
62impl Borrow<str> for HeapStr {
63    fn borrow(&self) -> &str {
64        self
65    }
66}
67
68impl BorrowMut<str> for HeapStr {
69    fn borrow_mut(&mut self) -> &mut str {
70        self
71    }
72}
73
74impl Hash for HeapStr {
75    fn hash<H: Hasher>(&self, state: &mut H) {
76        (**self).hash(state)
77    }
78}
79
80impl fmt::Debug for HeapStr {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        write!(f, "{:?}", &**self)
83    }
84}
85
86impl fmt::Display for HeapStr {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        write!(f, "{}", &**self)
89    }
90}
91
92impl<T: AsRef<str>> PartialEq<T> for HeapStr {
93    fn eq(&self, other: &T) -> bool {
94        (**self).eq(other.as_ref())
95    }
96}
97
98impl Eq for HeapStr {}
99
100impl<T: AsRef<str>> PartialOrd<T> for HeapStr {
101    fn partial_cmp(&self, other: &T) -> Option<Ordering> {
102        (**self).partial_cmp(other.as_ref())
103    }
104}
105
106impl Ord for HeapStr {
107    fn cmp(&self, other: &Self) -> Ordering {
108        (**self).cmp(&**other)
109    }
110}
111
112#[test]
113fn test_basic() {
114    extern crate std;
115
116    assert_eq!(size_of::<HeapStr>(), size_of::<usize>());
117    assert_eq!(size_of::<Option<HeapStr>>(), size_of::<usize>());
118
119    fn assert_traits<T: Send + Sync + fmt::Debug + fmt::Display + Clone + PartialEq + Eq + PartialOrd + Ord + Deref<Target = str> + DerefMut + AsRef<str> + AsMut<str> + Borrow<str> + BorrowMut<str> + Hash + Default>() {}
120    assert_traits::<HeapStr>();
121
122    for content in ["", "h", "he", "hel", "help", "help me obi-wan kenobi, you're my only hope"] {
123        let mut v = HeapStr::from(content);
124        assert_eq!(v, content);
125        assert_eq!(v.deref(), content);
126        assert_eq!(v.deref_mut(), content);
127        assert_eq!(v.as_ref(), content);
128        assert_eq!(v.as_mut(), content);
129        assert_eq!(<HeapStr as Borrow<str>>::borrow(&v), content);
130        assert_eq!(<HeapStr as BorrowMut<str>>::borrow_mut(&mut v), content);
131
132        let mut vv = v.into_bytes();
133        assert_eq!(vv, content.as_bytes());
134        assert_eq!(vv.deref(), content.as_bytes());
135        assert_eq!(vv.deref_mut(), content.as_bytes());
136        assert_eq!(vv.as_ref(), content.as_bytes());
137        assert_eq!(vv.as_mut(), content.as_bytes());
138        assert_eq!(<crate::HeapSlice<u8> as Borrow<[u8]>>::borrow(&vv), content.as_bytes());
139        assert_eq!(<crate::HeapSlice<u8> as BorrowMut<[u8]>>::borrow_mut(&mut vv), content.as_bytes());
140
141        let mut vvv = HeapStr::from_utf8(vv).unwrap();
142        assert_eq!(vvv, content);
143        assert_eq!(vvv.deref(), content);
144        assert_eq!(vvv.deref_mut(), content);
145        assert_eq!(vvv.as_ref(), content);
146        assert_eq!(vvv.as_mut(), content);
147        assert_eq!(<HeapStr as Borrow<str>>::borrow(&vvv), content);
148        assert_eq!(<HeapStr as BorrowMut<str>>::borrow_mut(&mut vvv), content);
149
150        std::thread::spawn(move || {
151            assert_eq!(vvv, content);
152            assert_eq!(vvv.deref(), content);
153            assert_eq!(vvv.deref_mut(), content);
154            assert_eq!(vvv.as_ref(), content);
155            assert_eq!(vvv.as_mut(), content);
156            assert_eq!(<HeapStr as Borrow<str>>::borrow(&vvv), content);
157            assert_eq!(<HeapStr as BorrowMut<str>>::borrow_mut(&mut vvv), content);
158        }).join().unwrap();
159    }
160    assert_eq!(HeapStr::default(), "");
161}