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