Skip to main content

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}