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}