generic_str/
owned_utf32.rs

1#[cfg(feature = "alloc")]
2use std::alloc::{Allocator, Global};
3use std::mem::MaybeUninit;
4
5use generic_vec::{
6    raw::{Storage, StorageWithCapacity},
7    ArrayVec, GenericVec,
8};
9
10use crate::{OwnedString, StringBase};
11
12/// UTF-32 Owned String that supports reallocation
13///
14/// ```
15/// # use generic_str::String32;
16/// let mut s = String32::new();
17/// s.push_str32(&String32::from("foobar"));
18/// assert_eq!(s, String32::from("foobar"));
19/// ```
20#[cfg(feature = "alloc")]
21pub type String32<A = Global> = OwnedString<char, Box<[MaybeUninit<char>], A>>;
22
23/// UTF-32 Owned String that has a fixed capacity
24///
25/// ```
26/// # use generic_str::{String32, ArrayString32};
27/// let mut s = ArrayString32::<8>::new();
28/// assert_eq!(std::mem::size_of_val(&s), 8 * 4 + 8); // 8 chars of storage, 8 bytes for length
29///
30/// s.push_str32(&String32::from("foo"));
31/// let t = s.clone(); // cloning requires no heap allocations
32/// s.push_str32(&String32::from("bar"));
33///
34/// assert_eq!(t, String32::from("foo"));
35/// assert_eq!(s, String32::from("foobar"));
36/// ```
37pub type ArrayString32<const N: usize> = OwnedString<char, [MaybeUninit<char>; N]>;
38
39#[cfg(feature = "alloc")]
40impl String32 {
41    /// Creates a new empty `String32`.
42    ///
43    /// Given that the `String32` is empty, this will not allocate any initial
44    /// buffer. While that means that this initial operation is very
45    /// inexpensive, it may cause excessive allocation later when you add
46    /// data. If you have an idea of how much data the `String32` will hold,
47    /// consider the [`with_capacity`] method to prevent excessive
48    /// re-allocation.
49    ///
50    /// [`with_capacity`]: String32::with_capacity
51    ///
52    /// # Examples
53    ///
54    /// Basic usage:
55    ///
56    /// ```
57    /// # use generic_str::String32;
58    /// let s = String32::new();
59    /// ```
60    #[inline]
61    pub fn new() -> Self {
62        Self::with_storage(Box::default())
63    }
64
65    /// Creates a new empty `String` with a particular capacity.
66    ///
67    /// `String`s have an internal buffer to hold their data. The capacity is
68    /// the length of that buffer, and can be queried with the [`capacity`]
69    /// method. This method creates an empty `String`, but one with an initial
70    /// buffer that can hold `capacity` bytes. This is useful when you may be
71    /// appending a bunch of data to the `String`, reducing the number of
72    /// reallocations it needs to do.
73    ///
74    /// [`capacity`]: StringBase::capacity
75    ///
76    /// If the given capacity is `0`, no allocation will occur, and this method
77    /// is identical to the [`new`] method.
78    ///
79    /// [`new`]: StringBase::new
80    ///
81    /// # Examples
82    ///
83    /// Basic usage:
84    ///
85    /// ```
86    /// # use generic_str::String32;
87    /// let mut s = String32::with_capacity(10);
88    ///
89    /// // The String contains no chars, even though it has capacity for more
90    /// assert_eq!(s.len(), 0);
91    ///
92    /// // These are all done without reallocating...
93    /// let cap = s.capacity();
94    /// for _ in 0..10 {
95    ///     s.push('a');
96    /// }
97    ///
98    /// assert_eq!(s.capacity(), cap);
99    ///
100    /// // ...but this may make the string reallocate
101    /// s.push('a');
102    /// ```
103    #[inline]
104    pub fn with_capacity(capacity: usize) -> Self {
105        Self::new_with_capacity(capacity)
106    }
107}
108
109#[cfg(feature = "alloc")]
110impl<A: Allocator> String32<A> {
111    pub fn with_alloc(alloc: A) -> Self {
112        Self::with_storage(Box::new_uninit_slice_in(0, alloc))
113    }
114}
115
116impl<const N: usize> ArrayString32<N> {
117    /// Creates a new empty `ArrayString`.
118    ///
119    /// # Examples
120    ///
121    /// Basic usage:
122    ///
123    /// ```
124    /// # use generic_str::ArrayString32;
125    /// let s = ArrayString32::<8>::new();
126    /// ```
127    #[inline]
128    pub fn new() -> Self {
129        Self {
130            storage: ArrayVec::new(),
131        }
132    }
133}
134
135impl<S: ?Sized + Storage<Item = char>> OwnedString<char, S> {
136    /// Appends a given string slice onto the end of this `String`.
137    ///
138    /// # Examples
139    ///
140    /// Basic usage:
141    ///
142    /// ```
143    /// # use generic_str::String32;
144    /// let mut s = String32::from("foo");
145    /// let t = String32::from("bar");
146    ///
147    /// s.push_str32(&t);
148    ///
149    /// assert_eq!(s, String32::from("foobar"));
150    /// ```
151    #[inline]
152    pub fn push_str32(&mut self, string: &crate::str32) {
153        self.storage.extend_from_slice(&string.storage)
154    }
155
156    /// Appends the given [`char`] to the end of this `String`.
157    ///
158    /// # Examples
159    ///
160    /// Basic usage:
161    ///
162    /// ```
163    /// # use generic_str::String32;
164    /// let mut s = String32::new();
165    ///
166    /// s.push('1');
167    /// s.push('2');
168    /// s.push('3');
169    ///
170    /// assert_eq!(s, String32::from("123"));
171    /// ```
172    #[inline]
173    pub fn push(&mut self, ch: char) {
174        self.storage.push(ch);
175    }
176
177    /// Removes the last character from the string buffer and returns it.
178    ///
179    /// Returns [`None`] if this `String` is empty.
180    ///
181    /// # Examples
182    ///
183    /// Basic usage:
184    ///
185    /// ```
186    /// # use generic_str::String32;
187    /// let mut s = String32::from("foo");
188    ///
189    /// assert_eq!(s.pop(), Some('o'));
190    /// assert_eq!(s.pop(), Some('o'));
191    /// assert_eq!(s.pop(), Some('f'));
192    ///
193    /// assert_eq!(s.pop(), None);
194    /// ```
195    #[inline]
196    pub fn pop(&mut self) -> Option<char> {
197        self.storage.try_pop()
198    }
199
200    /// Shortens this `String` to the specified length.
201    ///
202    /// If `new_len` is greater than the string's current length, this has no
203    /// effect.
204    ///
205    /// Note that this method has no effect on the allocated capacity
206    /// of the string
207    ///
208    /// # Panics
209    ///
210    /// Panics if `new_len` does not lie on a [`char`] boundary.
211    ///
212    /// # Examples
213    ///
214    /// Basic usage:
215    ///
216    /// ```
217    /// # use generic_str::String32;
218    /// let mut s = String32::from("hello");
219    ///
220    /// s.truncate(2);
221    ///
222    /// assert_eq!(s, String32::from("he"));
223    /// ```
224    #[inline]
225    pub fn truncate(&mut self, new_len: usize) {
226        self.storage.truncate(new_len)
227    }
228
229    /// Removes a [`char`] from this `String` at a byte position and returns it.
230    ///
231    /// This is an *O*(*n*) operation, as it requires copying every element in the
232    /// buffer.
233    ///
234    /// # Panics
235    ///
236    /// Panics if `idx` is larger than or equal to the `String`'s length,
237    /// or if it does not lie on a [`char`] boundary.
238    ///
239    /// # Examples
240    ///
241    /// Basic usage:
242    ///
243    /// ```
244    /// # use generic_str::String32;
245    /// let mut s = String32::from("foo");
246    ///
247    /// assert_eq!(s.remove(0), 'f');
248    /// assert_eq!(s.remove(1), 'o');
249    /// assert_eq!(s.remove(0), 'o');
250    /// ```
251    #[inline]
252    pub fn remove(&mut self, idx: usize) -> char {
253        self.storage.remove(idx)
254    }
255
256    /// Inserts a character into this `String` at a byte position.
257    ///
258    /// This is an *O*(*n*) operation as it requires copying every element in the
259    /// buffer.
260    ///
261    /// # Panics
262    ///
263    /// Panics if `idx` is larger than the `String`'s length, or if it does not
264    /// lie on a [`char`] boundary.
265    ///
266    /// # Examples
267    ///
268    /// Basic usage:
269    ///
270    /// ```
271    /// # use generic_str::String32;
272    /// let mut s = String32::with_capacity(3);
273    ///
274    /// s.insert(0, 'f');
275    /// s.insert(1, 'o');
276    /// s.insert(2, 'o');
277    ///
278    /// assert_eq!(s, String32::from("foo"));
279    /// ```
280    #[inline]
281    pub fn insert(&mut self, idx: usize, ch: char) {
282        self.storage.insert(idx, ch);
283    }
284
285    /// Returns a mutable reference to the contents of this `String`.
286    ///
287    /// # Examples
288    ///
289    /// Basic usage:
290    ///
291    /// ```
292    /// # use generic_str::String32;
293    /// let mut s = String32::from("hello");
294    ///
295    /// unsafe {
296    ///     let vec = s.as_mut_vec();
297    ///     assert_eq!(&['h', 'e', 'l', 'l', 'o'][..], &vec[..]);
298    ///
299    ///     vec.reverse();
300    /// }
301    /// assert_eq!(s, String32::from("olleh"));
302    /// ```
303    #[inline]
304    pub fn as_mut_vec(&mut self) -> &mut GenericVec<S::Item, S> {
305        &mut self.storage
306    }
307
308    /// Splits the string into two at the given byte index.
309    ///
310    /// Returns a newly allocated `String`. `self` contains bytes `[0, at)`, and
311    /// the returned `String` contains bytes `[at, len)`. `at` must be on the
312    /// boundary of a UTF-8 code point.
313    ///
314    /// Note that the capacity of `self` does not change.
315    ///
316    /// # Panics
317    ///
318    /// Panics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last
319    /// code point of the string.
320    ///
321    /// # Examples
322    ///
323    /// ```
324    /// # use generic_str::String32;
325    /// # fn main() {
326    /// let mut hello = String32::from("Hello, World!");
327    /// let world: String32 = hello.split_off(7);
328    /// assert_eq!(hello, String32::from("Hello, "));
329    /// assert_eq!(world, String32::from("World!"));
330    /// # }
331    /// ```
332    #[inline]
333    #[must_use = "use `.truncate()` if you don't need the other half"]
334    pub fn split_off<B: ?Sized + StorageWithCapacity<Item = char>>(
335        &mut self,
336        at: usize,
337    ) -> OwnedString<char, B> {
338        let other = self.storage.split_off(at);
339        StringBase { storage: other }
340    }
341
342    /// Truncates this `String`, removing all contents.
343    ///
344    /// While this means the `String` will have a length of zero, it does not
345    /// touch its capacity.
346    ///
347    /// # Examples
348    ///
349    /// Basic usage:
350    ///
351    /// ```
352    /// # use generic_str::String32;
353    /// let mut s = String32::from("foo");
354    /// let cap = s.capacity();
355    ///
356    /// s.clear();
357    ///
358    /// assert!(s.is_empty());
359    /// assert_eq!(0, s.len());
360    /// assert_eq!(cap, s.capacity());
361    /// ```
362    #[inline]
363    pub fn clear(&mut self) {
364        self.storage.clear()
365    }
366
367    /// Returns this `String`'s capacity, in bytes.
368    ///
369    /// # Examples
370    ///
371    /// Basic usage:
372    ///
373    /// ```
374    /// # use generic_str::String32;
375    /// let s = String32::with_capacity(10);
376    ///
377    /// assert!(s.capacity() >= 10);
378    /// ```
379    #[inline]
380    pub fn capacity(&self) -> usize {
381        self.storage.capacity()
382    }
383}