stabby_abi/alloc/
string.rs1use super::{
2 boxed::BoxedSlice,
3 sync::{ArcSlice, WeakSlice},
4 vec::Vec,
5 AllocationError, IAlloc,
6};
7use core::hash::Hash;
8
9#[crate::stabby]
11#[derive(Clone)]
12pub struct String<Alloc: IAlloc = super::DefaultAllocator> {
13 pub(crate) inner: Vec<u8, Alloc>,
14}
15
16#[cfg(not(stabby_default_alloc = "disabled"))]
17impl String {
18 pub const fn new() -> Self {
20 Self { inner: Vec::new() }
21 }
22}
23impl<Alloc: IAlloc> String<Alloc> {
24 pub const fn new_in(alloc: Alloc) -> Self {
26 Self {
27 inner: Vec::new_in(alloc),
28 }
29 }
30 pub fn as_str(&self) -> &str {
32 unsafe { core::str::from_utf8_unchecked(self.inner.as_slice()) }
33 }
34 pub fn as_str_mut(&mut self) -> &mut str {
36 unsafe { core::str::from_utf8_unchecked_mut(self.inner.as_slice_mut()) }
37 }
38 fn try_concat_str(&mut self, s: &str) -> Result<(), AllocationError> {
39 self.inner.try_copy_extend(s.as_bytes())
40 }
41 pub fn try_concat<S: AsRef<str> + ?Sized>(&mut self, s: &S) -> Result<(), AllocationError> {
45 self.try_concat_str(s.as_ref())
46 }
47}
48impl<Alloc: IAlloc + Default> Default for String<Alloc> {
49 fn default() -> Self {
50 Self {
51 inner: Vec::default(),
52 }
53 }
54}
55impl<S: AsRef<str> + ?Sized, Alloc: IAlloc> core::ops::Add<&S> for String<Alloc> {
56 type Output = Self;
57 fn add(mut self, rhs: &S) -> Self::Output {
58 self += rhs.as_ref();
59 self
60 }
61}
62impl<S: AsRef<str> + ?Sized, Alloc: IAlloc> core::ops::AddAssign<&S> for String<Alloc> {
63 fn add_assign(&mut self, rhs: &S) {
64 self.inner.copy_extend(rhs.as_ref().as_bytes())
65 }
66}
67
68impl<Alloc: IAlloc> From<String<Alloc>> for Vec<u8, Alloc> {
69 fn from(value: String<Alloc>) -> Self {
70 value.inner
71 }
72}
73
74impl<Alloc: IAlloc> TryFrom<Vec<u8, Alloc>> for String<Alloc> {
75 type Error = core::str::Utf8Error;
76 fn try_from(value: Vec<u8, Alloc>) -> Result<Self, Self::Error> {
77 core::str::from_utf8(value.as_slice())?;
78 Ok(Self { inner: value })
79 }
80}
81
82impl<Alloc: IAlloc> core::ops::Deref for String<Alloc> {
83 type Target = str;
84 fn deref(&self) -> &Self::Target {
85 self.as_str()
86 }
87}
88
89impl<Alloc: IAlloc> core::convert::AsRef<str> for String<Alloc> {
90 fn as_ref(&self) -> &str {
91 self.as_str()
92 }
93}
94impl<Alloc: IAlloc> core::ops::DerefMut for String<Alloc> {
95 fn deref_mut(&mut self) -> &mut Self::Target {
96 self.as_str_mut()
97 }
98}
99
100impl<Alloc: IAlloc> core::fmt::Debug for String<Alloc> {
101 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
102 core::fmt::Debug::fmt(self.as_str(), f)
103 }
104}
105impl<Alloc: IAlloc> core::fmt::Display for String<Alloc> {
106 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107 core::fmt::Display::fmt(self.as_str(), f)
108 }
109}
110impl<Alloc: IAlloc> Hash for String<Alloc> {
111 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
112 self.as_str().hash(state)
113 }
114}
115impl<Alloc: IAlloc, Rhs: AsRef<str>> PartialEq<Rhs> for String<Alloc> {
116 fn eq(&self, other: &Rhs) -> bool {
117 self.as_str() == other.as_ref()
118 }
119}
120impl<Alloc: IAlloc> Eq for String<Alloc> {}
121impl<Alloc: IAlloc, Rhs: AsRef<str>> PartialOrd<Rhs> for String<Alloc> {
122 fn partial_cmp(&self, other: &Rhs) -> Option<core::cmp::Ordering> {
123 self.as_str().partial_cmp(other.as_ref())
124 }
125}
126impl<Alloc: IAlloc> Ord for String<Alloc> {
127 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
128 self.as_str().cmp(other.as_str())
129 }
130}
131
132impl<Alloc: IAlloc + Default> From<&str> for String<Alloc> {
133 fn from(value: &str) -> Self {
134 Self::default() + value
135 }
136}
137
138impl<Alloc: IAlloc + Default> From<crate::str::Str<'_>> for String<Alloc> {
139 fn from(value: crate::str::Str<'_>) -> Self {
140 Self::default() + value.as_ref()
141 }
142}
143
144#[crate::stabby]
146pub struct ArcStr<Alloc: IAlloc = super::DefaultAllocator> {
147 inner: ArcSlice<u8, Alloc>,
148}
149impl<Alloc: IAlloc> ArcStr<Alloc> {
150 pub fn as_str(&self) -> &str {
152 unsafe { core::str::from_utf8_unchecked(self.inner.as_slice()) }
153 }
154 pub unsafe fn as_str_mut_unchecked(&mut self) -> &mut str {
158 unsafe { core::str::from_utf8_unchecked_mut(self.inner.as_slice_mut_unchecked()) }
159 }
160 pub fn as_str_mut(&mut self) -> Option<&mut str> {
162 Self::is_unique(self).then(|| unsafe { self.as_str_mut_unchecked() })
163 }
164 pub fn is_unique(this: &Self) -> bool {
166 ArcSlice::is_unique(&this.inner)
167 }
168}
169impl<Alloc: IAlloc> AsRef<str> for ArcStr<Alloc> {
170 fn as_ref(&self) -> &str {
171 self.as_str()
172 }
173}
174
175impl<Alloc: IAlloc> core::fmt::Debug for ArcStr<Alloc> {
176 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177 core::fmt::Debug::fmt(self.as_str(), f)
178 }
179}
180impl<Alloc: IAlloc> core::fmt::Display for ArcStr<Alloc> {
181 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
182 core::fmt::Display::fmt(self.as_str(), f)
183 }
184}
185impl<Alloc: IAlloc> core::ops::Deref for ArcStr<Alloc> {
186 type Target = str;
187 fn deref(&self) -> &Self::Target {
188 self.as_str()
189 }
190}
191impl<Alloc: IAlloc> From<String<Alloc>> for ArcStr<Alloc> {
192 fn from(value: String<Alloc>) -> Self {
193 Self {
194 inner: value.inner.into(),
195 }
196 }
197}
198impl<Alloc: IAlloc> TryFrom<ArcStr<Alloc>> for String<Alloc> {
199 type Error = ArcStr<Alloc>;
200 fn try_from(value: ArcStr<Alloc>) -> Result<Self, ArcStr<Alloc>> {
201 match value.inner.try_into() {
202 Ok(vec) => Ok(String { inner: vec }),
203 Err(slice) => Err(ArcStr { inner: slice }),
204 }
205 }
206}
207impl<Alloc: IAlloc> Clone for ArcStr<Alloc> {
208 fn clone(&self) -> Self {
209 Self {
210 inner: self.inner.clone(),
211 }
212 }
213}
214impl<Alloc: IAlloc> Eq for ArcStr<Alloc> {}
215impl<Alloc: IAlloc> PartialEq for ArcStr<Alloc> {
216 fn eq(&self, other: &Self) -> bool {
217 self.as_str() == other.as_str()
218 }
219}
220impl<Alloc: IAlloc> Ord for ArcStr<Alloc> {
221 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
222 self.as_str().cmp(other.as_str())
223 }
224}
225impl<Alloc: IAlloc> PartialOrd for ArcStr<Alloc> {
226 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
227 Some(self.cmp(other))
228 }
229}
230impl<Alloc: IAlloc> Hash for ArcStr<Alloc> {
231 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
232 self.as_str().hash(state)
233 }
234}
235
236#[crate::stabby]
238pub struct WeakStr<Alloc: IAlloc = super::DefaultAllocator> {
239 inner: WeakSlice<u8, Alloc>,
240}
241impl<Alloc: IAlloc> WeakStr<Alloc> {
242 pub fn upgrade(&self) -> Option<ArcStr<Alloc>> {
244 self.inner.upgrade().map(|inner| ArcStr { inner })
245 }
246 pub fn force_upgrade(&self) -> ArcStr<Alloc> {
250 ArcStr {
251 inner: self.inner.force_upgrade(),
252 }
253 }
254}
255impl<Alloc: IAlloc> From<&ArcStr<Alloc>> for WeakStr<Alloc> {
256 fn from(value: &ArcStr<Alloc>) -> Self {
257 Self {
258 inner: (&value.inner).into(),
259 }
260 }
261}
262impl<Alloc: IAlloc> Clone for WeakStr<Alloc> {
263 fn clone(&self) -> Self {
264 Self {
265 inner: self.inner.clone(),
266 }
267 }
268}
269
270#[crate::stabby]
272pub struct BoxedStr<Alloc: IAlloc = super::DefaultAllocator> {
273 inner: BoxedSlice<u8, Alloc>,
274}
275impl<Alloc: IAlloc> BoxedStr<Alloc> {
276 pub fn as_str(&self) -> &str {
278 unsafe { core::str::from_utf8_unchecked(self.inner.as_slice()) }
279 }
280 pub fn as_str_mut(&mut self) -> &mut str {
282 unsafe { core::str::from_utf8_unchecked_mut(self.inner.as_slice_mut()) }
283 }
284}
285impl<Alloc: IAlloc> AsRef<str> for BoxedStr<Alloc> {
286 fn as_ref(&self) -> &str {
287 self.as_str()
288 }
289}
290impl<Alloc: IAlloc> core::ops::Deref for BoxedStr<Alloc> {
291 type Target = str;
292 fn deref(&self) -> &Self::Target {
293 self.as_str()
294 }
295}
296impl<Alloc: IAlloc> From<String<Alloc>> for BoxedStr<Alloc> {
297 fn from(value: String<Alloc>) -> Self {
298 Self {
299 inner: value.inner.into(),
300 }
301 }
302}
303impl<Alloc: IAlloc> From<BoxedStr<Alloc>> for String<Alloc> {
304 fn from(value: BoxedStr<Alloc>) -> Self {
305 String {
306 inner: value.inner.into(),
307 }
308 }
309}
310impl<Alloc: IAlloc> Eq for BoxedStr<Alloc> {}
311impl<Alloc: IAlloc> PartialEq for BoxedStr<Alloc> {
312 fn eq(&self, other: &Self) -> bool {
313 self.as_str() == other.as_str()
314 }
315}
316impl<Alloc: IAlloc> Ord for BoxedStr<Alloc> {
317 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
318 self.as_str().cmp(other.as_str())
319 }
320}
321impl<Alloc: IAlloc> PartialOrd for BoxedStr<Alloc> {
322 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
323 Some(self.cmp(other))
324 }
325}
326impl<Alloc: IAlloc> core::hash::Hash for BoxedStr<Alloc> {
327 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
328 self.as_str().hash(state)
329 }
330}
331
332impl<Alloc: IAlloc> core::fmt::Debug for BoxedStr<Alloc> {
333 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
334 core::fmt::Debug::fmt(self.as_str(), f)
335 }
336}
337impl<Alloc: IAlloc> core::fmt::Display for BoxedStr<Alloc> {
338 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
339 core::fmt::Display::fmt(self.as_str(), f)
340 }
341}
342
343impl core::fmt::Write for String {
344 fn write_str(&mut self, s: &str) -> core::fmt::Result {
345 self.try_concat(s).map_err(|_| core::fmt::Error)
346 }
347}
348
349#[cfg(feature = "std")]
350mod std_impl {
351 use crate::alloc::IAlloc;
352 impl<Alloc: IAlloc + Default> From<std::string::String> for crate::alloc::string::String<Alloc> {
353 fn from(value: std::string::String) -> Self {
354 Self::from(value.as_ref())
355 }
356 }
357 impl<Alloc: IAlloc + Default> From<crate::alloc::string::String<Alloc>> for std::string::String {
358 fn from(value: crate::alloc::string::String<Alloc>) -> Self {
359 Self::from(value.as_ref())
360 }
361 }
362}
363
364#[cfg(feature = "serde")]
365mod serde_impl {
366 use super::*;
367 use crate::alloc::IAlloc;
368 use serde::{Deserialize, Serialize};
369 impl<Alloc: IAlloc> Serialize for String<Alloc> {
370 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
371 where
372 S: serde::Serializer,
373 {
374 let slice: &str = self;
375 slice.serialize(serializer)
376 }
377 }
378 impl<'a, Alloc: IAlloc + Default> Deserialize<'a> for String<Alloc> {
379 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
380 where
381 D: serde::Deserializer<'a>,
382 {
383 crate::str::Str::deserialize(deserializer).map(Into::into)
384 }
385 }
386}