pstd/string.rs
1use crate::{
2 VecA,
3 alloc::{Allocator, Global},
4};
5use std::{borrow::Borrow, fmt::Debug, ops, ptr};
6
7/// A UTF-8–encoded, growable string allocated from Global.
8pub type String = StringA<Global>;
9
10/// A UTF-8–encoded, growable string.
11#[derive(Clone)]
12pub struct StringA<A: Allocator>(VecA<u8, A>);
13
14impl<A: Allocator> StringA<A> {
15 /// Create an empty string.
16 pub fn new() -> Self
17 where
18 A: Default,
19 {
20 Self(VecA::new())
21 }
22
23 /// Create an empty string in specified allocator.
24 pub const fn new_in(a: A) -> Self {
25 Self(VecA::new_in(a))
26 }
27
28 /// Appends a given string slice onto the end of this `String`.
29 /// # Example
30 ///
31 /// ```
32 /// use pstd::{String,alloc::Global};
33 /// let mut s = String::from_str_in("foo",Global);
34 ///
35 /// s.push_str("bar");
36 ///
37 /// assert_eq!("foobar", &*s);
38 /// ```
39 pub fn push_str(&mut self, string: &str) {
40 self.0.extend_from_slice(string.as_bytes())
41 }
42
43 /// Appends the given [`char`] to the end of this `String`.
44 ///
45 /// # Panics
46 ///
47 /// Panics if the new capacity exceeds `isize::MAX` _bytes_.
48 ///
49 /// # Examples
50 ///
51 /// ```
52 /// use pstd::String;
53 /// let mut s = String::from("abc");
54 ///
55 /// s.push('1');
56 /// s.push('2');
57 /// s.push('3');
58 ///
59 /// assert_eq!("abc123", s);
60 /// ```
61 pub fn push(&mut self, ch: char) {
62 let mut buf: [u8; 4] = [0; 4];
63 self.push_str(ch.encode_utf8(&mut buf));
64 }
65
66 /// Removes the last character from the string buffer and returns it.
67 ///
68 /// Returns [`None`] if this `String` is empty.
69 ///
70 /// # Examples
71 ///
72 /// ```
73 /// use pstd::String;
74 /// let mut s = String::from("abč");
75 ///
76 /// assert_eq!(s.pop(), Some('č'));
77 /// assert_eq!(s.pop(), Some('b'));
78 /// assert_eq!(s.pop(), Some('a'));
79 ///
80 /// assert_eq!(s.pop(), None);
81 /// ```
82 pub fn pop(&mut self) -> Option<char> {
83 let ch = self.chars().next_back()?;
84 let newlen = self.len() - ch.len_utf8();
85 self.0.truncate(newlen);
86 Some(ch)
87 }
88
89 /// Inserts a string slice into this `String` at byte position `idx`.
90 ///
91 /// Reallocates if `self.capacity()` is insufficient, which may involve copying all
92 /// `self.capacity()` bytes. Makes space for the insertion by copying all bytes of
93 /// `&self[idx..]` to new positions.
94 ///
95 /// Note that calling this in a loop can result in quadratic behavior.
96 ///
97 /// # Panics
98 ///
99 /// Panics if `idx` is larger than the `String`'s length, or if it does not
100 /// lie on a [`char`] boundary.
101 ///
102 /// # Examples
103 ///
104 /// ```
105 /// use pstd::String;
106 /// let mut s = String::from("bar");
107 ///
108 /// s.insert_str(0, "foo");
109 ///
110 /// assert_eq!("foobar", s);
111 /// ```
112 pub fn insert_str(&mut self, idx: usize, string: &str) {
113 assert!(self.is_char_boundary(idx));
114
115 let len = self.len();
116 let amt = string.len();
117 self.reserve(amt);
118
119 // SAFETY: Move the bytes starting from `idx` to their new location `amt` bytes
120 // ahead. This is safe because sufficient capacity was just reserved, and `idx`
121 // is a char boundary.
122 unsafe {
123 ptr::copy(
124 self.0.as_ptr().add(idx),
125 self.0.as_mut_ptr().add(idx + amt),
126 len - idx,
127 );
128 }
129
130 // SAFETY: Copy the new string slice into the vacated region if `idx != len`,
131 // or into the uninitialized spare capacity otherwise. The borrow checker
132 // ensures that the source and destination do not overlap.
133 unsafe {
134 ptr::copy_nonoverlapping(string.as_ptr(), self.0.as_mut_ptr().add(idx), amt);
135 }
136
137 // SAFETY: Update the length to include the newly added bytes.
138 unsafe {
139 self.0.set_len(len + amt);
140 }
141 }
142
143 /// Inserts a character into this `String` at byte position `idx`.
144 ///
145 /// Reallocates if `self.capacity()` is insufficient, which may involve copying all
146 /// `self.capacity()` bytes. Makes space for the insertion by copying all bytes of
147 /// `&self[idx..]` to new positions.
148 ///
149 /// Note that calling this in a loop can result in quadratic behavior.
150 ///
151 /// # Panics
152 ///
153 /// Panics if `idx` is larger than the `String`'s length, or if it does not
154 /// lie on a [`char`] boundary.
155 ///
156 /// # Examples
157 ///
158 /// ```
159 /// use pstd::String;
160 /// let mut s = String::with_capacity(3);
161 ///
162 /// s.insert(0, 'f');
163 /// s.insert(1, 'o');
164 /// s.insert(2, 'o');
165 ///
166 /// assert_eq!("foo", s);
167 /// ```
168 pub fn insert(&mut self, idx: usize, ch: char) {
169 assert!(self.is_char_boundary(idx));
170 let mut buf: [u8; 4] = [0; 4];
171 self.insert_str(idx, ch.encode_utf8(&mut buf));
172 }
173
174 /// Returns the length of this `String`, in bytes, not [`char`]s or
175 /// graphemes. In other words, it might not be what a human considers the
176 /// length of the string.
177 ///
178 /// # Examples
179 ///
180 /// ```
181 /// use pstd::String;
182 /// let a = String::from("foo");
183 /// assert_eq!(a.len(), 3);
184 ///
185 /// let fancy_f = String::from("ƒoo");
186 /// assert_eq!(fancy_f.len(), 4);
187 /// assert_eq!(fancy_f.chars().count(), 3);
188 /// ```
189 #[must_use]
190 pub const fn len(&self) -> usize {
191 self.0.len()
192 }
193
194 /// Returns `true` if this `String` has a length of zero, and `false` otherwise.
195 ///
196 /// # Examples
197 ///
198 /// ```
199 /// use pstd::String;
200 /// let mut v = String::new();
201 /// assert!(v.is_empty());
202 ///
203 /// v.push('a');
204 /// assert!(!v.is_empty());
205 /// ```
206 #[must_use]
207 pub const fn is_empty(&self) -> bool {
208 self.len() == 0
209 }
210
211 /// Replaces all matches of a pattern with another string.
212 pub fn replace(&self, pat: &str, with: &str) -> Self
213 where
214 A: Clone,
215 {
216 let mut result = Self::new_in(self.0.allocator().clone());
217 let mut last_end = 0;
218 for (start, part) in self.match_indices(pat) {
219 result.push_str(unsafe { self.get_unchecked(last_end..start) });
220 result.push_str(with);
221 last_end = start + part.len();
222 }
223 result.push_str(unsafe { self.get_unchecked(last_end..self.len()) });
224 result
225 }
226
227 /// Splits the string into two at the given byte index.
228 ///
229 /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and
230 /// the returned `String` contains bytes `[at, len)`. `at` must be on the
231 /// boundary of a UTF-8 code point.
232 ///
233 /// Note that the capacity of `self` does not change.
234 ///
235 /// # Panics
236 ///
237 /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last
238 /// code point of the string.
239 ///
240 /// # Examples
241 ///
242 /// ```
243 /// use pstd::String;
244 /// let mut hello = String::from("Hello, World!");
245 /// let world = hello.split_off(7);
246 /// assert_eq!(hello, "Hello, ");
247 /// assert_eq!(world, "World!");
248 /// ```
249 #[must_use = "use `.truncate()` if you don't need the other half"]
250 pub fn split_off(&mut self, at: usize) -> Self
251 where
252 A: Clone,
253 {
254 assert!(self.is_char_boundary(at));
255 Self(self.0.split_off(at))
256 }
257
258 /// Truncates this `String`, removing all contents.
259 ///
260 /// While this means the `String` will have a length of zero, it does not
261 /// touch its capacity.
262 ///
263 /// # Examples
264 ///
265 /// ```
266 /// use pstd::String;
267 /// let mut s = String::from("foo");
268 ///
269 /// s.clear();
270 ///
271 /// assert!(s.is_empty());
272 /// assert_eq!(0, s.len());
273 /// assert_eq!(3, s.capacity());
274 /// ```
275 pub fn clear(&mut self) {
276 self.0.clear();
277 }
278
279 /// Creates a String from a str in the specified allocator.
280 pub fn from_str_in(s: &str, alloc: A) -> Self {
281 let mut v = VecA::with_capacity_in(s.len(), alloc);
282 v.extend_from_slice(s.as_bytes());
283 Self(v)
284 }
285
286 /// Create an empty string with specified capacity.
287 pub fn with_capacity(cap: usize) -> Self
288 where
289 A: Default,
290 {
291 Self(VecA::with_capacity(cap))
292 }
293
294 /// Returns this `String`'s capacity, in bytes.
295 ///
296 /// # Examples
297 ///
298 /// ```
299 /// use pstd::String;
300 /// let s = String::with_capacity(10);
301 ///
302 /// assert!(s.capacity() >= 10);
303 /// ```
304 #[must_use]
305 pub const fn capacity(&self) -> usize {
306 self.0.capacity()
307 }
308
309 /// Reserves capacity for at least `additional` bytes more than the
310 /// current length. The allocator may reserve more space to speculatively
311 /// avoid frequent allocations. After calling `reserve`,
312 /// capacity will be greater than or equal to `self.len() + additional`.
313 /// Does nothing if capacity is already sufficient.
314 ///
315 /// # Panics
316 ///
317 /// Panics if the new capacity exceeds `isize::MAX` _bytes_.
318 ///
319 /// # Examples
320 ///
321 /// Basic usage:
322 ///
323 /// ```
324 /// use pstd::String;
325 /// let mut s = String::new();
326 ///
327 /// s.reserve(10);
328 ///
329 /// assert!(s.capacity() >= 10);
330 /// ```
331 ///
332 /// This might not actually increase the capacity:
333 ///
334 /// ```
335 /// use pstd::String;
336 /// let mut s = String::with_capacity(10);
337 /// s.push('a');
338 /// s.push('b');
339 ///
340 /// // s now has a length of 2 and a capacity of at least 10
341 /// let capacity = s.capacity();
342 /// assert_eq!(2, s.len());
343 /// assert!(capacity >= 10);
344 ///
345 /// // Since we already have at least an extra 8 capacity, calling this...
346 /// s.reserve(8);
347 ///
348 /// // ... doesn't actually increase.
349 /// assert_eq!(capacity, s.capacity());
350 /// ```
351 pub fn reserve(&mut self, additional: usize) {
352 self.0.reserve(additional)
353 }
354
355 /// Extracts a string slice containing the entire String.
356 pub fn as_str(&self) -> &str {
357 unsafe { str::from_utf8_unchecked(self.0.as_slice()) }
358 }
359
360 /// Converts a String into a mutable string slice.
361 pub fn as_mut_str(&mut self) -> &mut str {
362 unsafe { str::from_utf8_unchecked_mut(self.0.as_mut_slice()) }
363 }
364
365 /// Returns a byte slice of this `String`'s contents.
366 ///
367 /// # Examples
368 ///
369 /// ```
370 /// use pstd::String;
371 /// let s = String::from("hello");
372 ///
373 /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes());
374 /// ```
375 #[must_use]
376 pub const fn as_bytes(&self) -> &[u8] {
377 self.0.as_slice()
378 }
379
380 /// Converts a `String` into a byte vector.
381 ///
382 /// This consumes the `String`, so we do not need to copy its contents.
383 ///
384 /// # Examples
385 ///
386 /// ```
387 /// use pstd::String;
388 /// let s = String::from("hello");
389 /// let bytes = s.into_bytes();
390 ///
391 /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
392 /// ```
393 #[must_use = "`self` will be dropped if the result is not used"]
394 pub fn into_bytes(self) -> VecA<u8, A> {
395 self.0
396 }
397}
398
399impl<A: Allocator> ops::Deref for StringA<A> {
400 type Target = str;
401
402 fn deref(&self) -> &str {
403 self.as_str()
404 }
405}
406
407impl<A: Allocator> ops::DerefMut for StringA<A> {
408 fn deref_mut(&mut self) -> &mut str {
409 self.as_mut_str()
410 }
411}
412
413impl<A: Allocator> Borrow<str> for StringA<A> {
414 fn borrow(&self) -> &str {
415 self.as_str()
416 }
417}
418
419impl<A: Allocator> std::fmt::Display for StringA<A> {
420 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
421 std::fmt::Display::fmt(&**self, f)
422 }
423}
424
425impl<A: Allocator> Debug for StringA<A> {
426 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
427 std::fmt::Debug::fmt(&**self, f)
428 }
429}
430
431impl<A: Allocator> std::hash::Hash for StringA<A> {
432 fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
433 (**self).hash(hasher)
434 }
435}
436
437impl<A: Allocator> Eq for StringA<A> {}
438
439impl<A1: Allocator, A2: Allocator> PartialEq<StringA<A2>> for StringA<A1> {
440 fn eq(&self, other: &StringA<A2>) -> bool {
441 **self == **other
442 }
443}
444
445impl<A1, A2> PartialOrd<StringA<A2>> for StringA<A1>
446where
447 A1: Allocator,
448 A2: Allocator,
449{
450 fn partial_cmp(&self, other: &StringA<A2>) -> Option<std::cmp::Ordering> {
451 PartialOrd::partial_cmp(&**self, &**other)
452 }
453}
454
455impl<A: Allocator> Ord for StringA<A> {
456 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
457 std::cmp::Ord::cmp(&**self, &**other)
458 }
459}
460
461impl<A: Allocator> Default for StringA<A>
462where
463 A: Default,
464{
465 fn default() -> Self {
466 Self::new()
467 }
468}
469
470impl<A: Allocator> PartialEq<StringA<A>> for str {
471 fn eq(&self, s: &StringA<A>) -> bool {
472 self == &**s
473 }
474}
475
476impl<A: Allocator> PartialEq<StringA<A>> for &str {
477 fn eq(&self, s: &StringA<A>) -> bool {
478 &**s == *self
479 }
480}
481
482impl<A: Allocator> PartialEq<str> for StringA<A> {
483 fn eq(&self, s: &str) -> bool {
484 s == &**self
485 }
486}
487
488impl<A: Allocator> PartialEq<&str> for StringA<A> {
489 fn eq(&self, s: &&str) -> bool {
490 &**self == *s
491 }
492}
493
494impl<A: Allocator> std::fmt::Write for StringA<A> {
495 fn write_str(&mut self, s: &str) -> Result<(), std::fmt::Error> {
496 self.push_str(s);
497 Ok(())
498 }
499}
500
501impl<A: Allocator + Default> From<&str> for StringA<A> {
502 fn from(s: &str) -> Self {
503 let mut v = VecA::with_capacity(s.len());
504 v.extend_from_slice(s.as_bytes());
505 Self(v)
506 }
507}
508
509#[cfg(feature = "serde")]
510use {
511 serde::{
512 Deserialize, Deserializer, Serialize, Serializer,
513 de::{Error, Visitor},
514 },
515 std::fmt,
516};
517
518#[cfg(feature = "serde")]
519impl<A: Allocator> Serialize for StringA<A> {
520 #[inline]
521 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
522 where
523 S: Serializer,
524 {
525 serializer.serialize_str(self)
526 }
527}
528
529#[cfg(feature = "serde")]
530impl<'de, A: Allocator + Default> Deserialize<'de> for StringA<A> {
531 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
532 where
533 D: Deserializer<'de>,
534 {
535 let v: MyVisitor<A> = MyVisitor {
536 pd: std::marker::PhantomData,
537 };
538 let s = deserializer.deserialize_string(v).unwrap();
539 Ok(Self::from(&*s))
540 }
541}
542
543#[cfg(feature = "serde")]
544struct MyVisitor<A: Allocator> {
545 pd: std::marker::PhantomData<A>,
546}
547
548#[cfg(feature = "serde")]
549impl<'a, A: Allocator + Default> Visitor<'a> for MyVisitor<A> {
550 type Value = StringA<A>;
551
552 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
553 formatter.write_str("a string")
554 }
555
556 fn visit_string<E>(self, s: std::string::String) -> Result<Self::Value, E>
557 where
558 E: Error,
559 {
560 Ok(Self::Value::from(&*s))
561 }
562
563 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
564 where
565 E: Error,
566 {
567 Ok(Self::Value::from(s))
568 }
569}
570
571#[test]
572fn test_string() {
573 use crate::localalloc::Local;
574
575 let mut s: StringA<Local> = StringA::new();
576 s.push_str("George");
577 assert!(s == "George");
578 assert!("George" == s);
579}
580
581#[test]
582fn test_string_replace() {
583 use crate::localalloc::Temp;
584
585 let mut s = StringA::<Temp>::from("George");
586 s = s.replace("eorge", "raham");
587 assert!(s == "Graham");
588 println!("s={}", s);
589}
590
591#[test]
592fn test_string_write() {
593 use crate::localalloc::Temp;
594
595 let mut output = StringA::<Temp>::new();
596
597 use std::fmt::Write;
598
599 let x: i64 = -319;
600
601 write!(&mut output, "Hello {}! {}", "world", x).unwrap();
602
603 assert_eq!(output, "Hello world! -319");
604
605 println!("output={}", output);
606}