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#[derive(Default, Clone)]
9pub struct HeapStr(crate::HeapSlice<u8>);
10
11impl HeapStr {
12 pub fn from_utf8(content: crate::HeapSlice<u8>) -> Result<Self, core::str::Utf8Error> {
15 Ok(str::from_utf8(&content)?.into())
16 }
17 pub unsafe fn from_utf8_unchecked(content: crate::HeapSlice<u8>) -> Self {
19 str::from_utf8_unchecked(&content).into()
20 }
21 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}