bump_scope/bump_string.rs
1use core::{
2 alloc::Layout,
3 borrow::{Borrow, BorrowMut},
4 ffi::CStr,
5 fmt::{self, Debug, Display},
6 hash::Hash,
7 ops::{Deref, DerefMut, Index, IndexMut, Range, RangeBounds},
8 ptr::{self, NonNull},
9 slice::SliceIndex,
10 str,
11};
12
13use crate::{
14 BumpBox, BumpVec, ErrorBehavior, FixedBumpString, FromUtf8Error, FromUtf16Error,
15 alloc::AllocError,
16 destructure::destructure,
17 fixed_bump_string::RawFixedBumpString,
18 owned_str,
19 polyfill::{self, transmute_mut, transmute_value},
20 traits::{BumpAllocatorTyped, BumpAllocatorTypedScope},
21};
22
23#[cfg(feature = "panic-on-alloc")]
24use crate::{PanicsOnAlloc, panic_on_error, polyfill::non_null};
25
26/// This is like [`format!`](alloc_crate::format) but allocates inside a bump allocator, returning a [`BumpString`].
27///
28/// If you don't need to push to the string after creation you can also use [`Bump::alloc_fmt`](crate::Bump::alloc_fmt).
29///
30/// # Panics
31/// If used without `try`, panics on allocation failure or if a formatting trait implementation returns an error.
32///
33/// # Errors
34/// If used with `try`, errors on allocation failure or if a formatting trait implementation returns an error.
35///
36/// # Examples
37///
38/// ```
39/// # use bump_scope::{Bump, bump_format};
40/// # let bump: Bump = Bump::new();
41/// #
42/// let greeting = "Hello";
43/// let mut string = bump_format!(in &bump, "{greeting}, world!");
44/// string.push_str(" How are you?");
45///
46/// assert_eq!(string, "Hello, world! How are you?");
47/// ```
48#[macro_export]
49macro_rules! bump_format {
50 (in $bump:expr) => {{
51 $crate::BumpString::new_in($bump)
52 }};
53 (in $bump:expr, $($arg:tt)*) => {
54 $crate::__bump_format_panic_on_alloc!(in $bump, $($arg)*)
55 };
56 (try in $bump:expr) => {{
57 Ok::<_, $crate::alloc::AllocError>($crate::BumpString::new_in($bump))
58 }};
59 (try in $bump:expr, $($arg:tt)*) => {{
60 let mut string = $crate::BumpString::new_in($bump);
61 match $crate::private::core::fmt::Write::write_fmt(&mut string, $crate::private::core::format_args!($($arg)*)) {
62 $crate::private::core::result::Result::Ok(_) => $crate::private::core::result::Result::Ok(string),
63 $crate::private::core::result::Result::Err(_) => $crate::private::core::result::Result::Err($crate::alloc::AllocError),
64 }
65 }};
66}
67
68#[doc(hidden)]
69#[macro_export]
70#[cfg(feature = "panic-on-alloc")]
71macro_rules! __bump_format_panic_on_alloc {
72 (in $bump:expr, $($arg:tt)*) => {{
73 let mut string = $crate::private::PanicsOnAlloc($crate::BumpString::new_in($bump));
74 match $crate::private::core::fmt::Write::write_fmt(&mut string, $crate::private::core::format_args!($($arg)*)) {
75 $crate::private::core::result::Result::Ok(_) => string.0,
76 $crate::private::core::result::Result::Err(_) => $crate::private::format_trait_error(),
77 }
78 }};
79}
80
81#[doc(hidden)]
82#[macro_export]
83#[cfg(not(feature = "panic-on-alloc"))]
84macro_rules! __bump_format_panic_on_alloc {
85 (in $bump:expr, $($arg:tt)*) => {{
86 compile_error!(concat!(
87 "the potentially panicking api of `bump_format!` is not available\n",
88 "help: enable `bump-scope`'s \"panic-on-alloc\" feature or use `try`:\n",
89 " `bump_format!(try in ",
90 stringify!($bump),
91 ", ",
92 stringify!($($arg)*),
93 ")`"
94 ))
95 }};
96}
97
98/// A bump allocated [`String`](alloc_crate::string::String).
99///
100/// When you are done building the string, you can turn it into a `&str` with [`into_str`].
101///
102/// # Examples
103///
104/// You can create a `BumpString` from [a literal string][`&str`] with [`BumpString::from_str_in`]:
105///
106/// [`into_str`]: BumpString::into_str
107///
108/// ```
109/// # use bump_scope::{Bump, BumpString};
110/// # let bump: Bump = Bump::new();
111/// let hello = BumpString::from_str_in("Hello, world!", &bump);
112/// # _ = hello;
113/// ```
114///
115/// You can append a [`char`] to a string with the [`push`] method, and
116/// append a [`&str`] with the [`push_str`] method:
117///
118/// ```
119/// # use bump_scope::{Bump, BumpString};
120/// # let bump: Bump = Bump::new();
121/// let mut hello = BumpString::from_str_in("Hello, ", &bump);
122///
123/// hello.push('w');
124/// hello.push_str("orld!");
125///
126/// assert_eq!(hello.as_str(), "Hello, world!");
127/// ```
128///
129/// [`push`]: BumpString::push
130/// [`push_str`]: BumpString::push_str
131///
132/// If you have a vector of UTF-8 bytes, you can create a `BumpString` from it with
133/// the [`from_utf8`] method:
134///
135/// ```
136/// # use bump_scope::{Bump, BumpString, bump_vec};
137/// # let bump: Bump = Bump::new();
138/// // some bytes, in a vector
139/// let sparkle_heart = bump_vec![in ≎ 240, 159, 146, 150];
140///
141/// // We know these bytes are valid, so we'll use `unwrap()`.
142/// let sparkle_heart = BumpString::from_utf8(sparkle_heart).unwrap();
143///
144/// assert_eq!("💖", sparkle_heart);
145/// ```
146///
147/// [`&str`]: prim@str "&str"
148/// [`from_utf8`]: BumpString::from_utf8
149// `BumpString` and `BumpVec<u8>` have the same repr.
150#[repr(C)]
151pub struct BumpString<A: BumpAllocatorTyped> {
152 fixed: RawFixedBumpString,
153 allocator: A,
154}
155
156impl<A: BumpAllocatorTyped> BumpString<A> {
157 /// Constructs a new empty `BumpString`.
158 ///
159 /// Given that the `BumpString` is empty, this will not allocate any initial
160 /// buffer. While that means that this initial operation is very
161 /// inexpensive, it may cause excessive allocation later when you add
162 /// data. If you have an idea of how much data the `BumpString` will hold,
163 /// consider the [`with_capacity_in`] method to prevent excessive
164 /// re-allocation.
165 ///
166 /// [`with_capacity_in`]: Self::with_capacity_in
167 ///
168 /// # Examples
169 /// ```
170 /// # use bump_scope::{Bump, BumpString};
171 /// # let bump: Bump = Bump::new();
172 /// let string = BumpString::<_>::new_in(&bump);
173 /// assert_eq!(string.len(), 0);
174 /// assert_eq!(string.capacity(), 0);
175 /// ```
176 #[inline]
177 pub fn new_in(allocator: A) -> Self {
178 Self {
179 fixed: RawFixedBumpString::EMPTY,
180 allocator,
181 }
182 }
183
184 /// Converts a vector of bytes to a `BumpString`.
185 ///
186 /// A string ([`BumpString`]) is made of bytes ([`u8`]), and a vector of bytes
187 /// ([`BumpVec<u8>`]) is made of bytes, so this function converts between the
188 /// two. Not all byte slices are valid `BumpString`s, however: `BumpString`
189 /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that
190 /// the bytes are valid UTF-8, and then does the conversion.
191 ///
192 /// If you are sure that the byte slice is valid UTF-8, and you don't want
193 /// to incur the overhead of the validity check, there is an unsafe version
194 /// of this function, [`from_utf8_unchecked`], which has the same behavior
195 /// but skips the check.
196 ///
197 /// This method will take care to not copy the vector, for efficiency's
198 /// sake.
199 ///
200 /// If you need a [`&str`] instead of a `BumpString`, consider
201 /// [`str::from_utf8`].
202 ///
203 /// The inverse of this method is [`into_bytes`].
204 ///
205 /// # Errors
206 ///
207 /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the
208 /// provided bytes are not UTF-8. The vector you moved in is also included.
209 ///
210 /// # Examples
211 ///
212 /// Basic usage:
213 /// ```
214 /// # use bump_scope::{Bump, bump_vec, BumpString};
215 /// # let bump: Bump = Bump::new();
216 /// // some bytes, in a vector
217 /// let sparkle_heart = bump_vec![in ≎ 240, 159, 146, 150];
218 ///
219 /// // We know these bytes are valid, so we'll use `unwrap()`.
220 /// let sparkle_heart = BumpString::from_utf8(sparkle_heart).unwrap();
221 ///
222 /// assert_eq!("💖", sparkle_heart);
223 /// ```
224 ///
225 /// Incorrect bytes:
226 /// ```
227 /// # use bump_scope::{Bump, bump_vec, BumpString};
228 /// # let bump: Bump = Bump::new();
229 /// // some invalid bytes, in a vector
230 /// let sparkle_heart = bump_vec![in ≎ 0, 159, 146, 150];
231 ///
232 /// assert!(BumpString::from_utf8(sparkle_heart).is_err());
233 /// ```
234 ///
235 /// [`from_utf8_unchecked`]: Self::from_utf8_unchecked
236 /// [`BumpVec<u8>`]: BumpVec
237 /// [`&str`]: prim@str "&str"
238 /// [`into_bytes`]: Self::into_bytes
239 pub fn from_utf8(vec: BumpVec<u8, A>) -> Result<Self, FromUtf8Error<BumpVec<u8, A>>> {
240 match str::from_utf8(vec.as_slice()) {
241 // SAFETY: `BumpVec<u8>` and `BumpString` have the same representation;
242 // only the invariant that the bytes are utf8 is different.
243 Ok(_) => Ok(unsafe { transmute_value(vec) }),
244 Err(error) => Err(FromUtf8Error::new(error, vec)),
245 }
246 }
247
248 /// Converts a vector of bytes to a `BumpString` without checking that the
249 /// string contains valid UTF-8.
250 ///
251 /// See the safe version, [`from_utf8`](Self::from_utf8), for more details.
252 ///
253 /// # Safety
254 ///
255 /// The bytes passed in must be valid UTF-8.
256 ///
257 /// # Examples
258 ///
259 /// ```
260 /// # use bump_scope::{Bump, bump_vec, BumpString};
261 /// # let bump: Bump = Bump::new();
262 /// // some bytes, in a vector
263 /// let sparkle_heart = bump_vec![in ≎ 240, 159, 146, 150];
264 ///
265 /// let sparkle_heart = unsafe {
266 /// BumpString::from_utf8_unchecked(sparkle_heart)
267 /// };
268 ///
269 /// assert_eq!("💖", sparkle_heart);
270 /// ```
271 #[must_use]
272 pub unsafe fn from_utf8_unchecked(vec: BumpVec<u8, A>) -> Self {
273 unsafe {
274 debug_assert!(str::from_utf8(vec.as_slice()).is_ok());
275
276 // SAFETY: `BumpVec<u8>` and `BumpString` have the same representation;
277 // only the invariant that the bytes are utf8 is different.
278 transmute_value(vec)
279 }
280 }
281
282 /// Returns this string's capacity, in bytes.
283 #[must_use]
284 #[inline(always)]
285 pub const fn capacity(&self) -> usize {
286 self.fixed.capacity()
287 }
288
289 /// Returns the length of this string, in bytes, not [`char`]s or
290 /// graphemes. In other words, it might not be what a human considers the
291 /// length of the string.
292 ///
293 /// # Examples
294 /// ```
295 /// # use bump_scope::{Bump, BumpString};
296 /// # let bump: Bump = Bump::new();
297 /// let a = BumpString::from_str_in("foo", &bump);
298 /// assert_eq!(a.len(), 3);
299 ///
300 /// let fancy_f = BumpString::from_str_in("ƒoo", &bump);
301 /// assert_eq!(fancy_f.len(), 4);
302 /// assert_eq!(fancy_f.chars().count(), 3);
303 /// ```
304 #[must_use]
305 #[inline(always)]
306 pub const fn len(&self) -> usize {
307 self.fixed.len()
308 }
309
310 /// Returns `true` if this string has a length of zero, and `false` otherwise.
311 ///
312 /// # Examples
313 /// ```
314 /// # use bump_scope::{Bump, BumpString};
315 /// # let bump: Bump = Bump::new();
316 /// let mut v = BumpString::new_in(&bump);
317 /// assert!(v.is_empty());
318 ///
319 /// v.push('a');
320 /// assert!(!v.is_empty());
321 /// ```
322 #[must_use]
323 #[inline(always)]
324 pub const fn is_empty(&self) -> bool {
325 self.fixed.len() == 0
326 }
327
328 /// Converts a `BumpString` into a `BumpVec<u8>`.
329 ///
330 /// This consumes the `BumpString`, so we do not need to copy its contents.
331 ///
332 /// # Examples
333 ///
334 /// ```
335 /// # use bump_scope::{Bump, BumpString};
336 /// # let bump: Bump = Bump::new();
337 /// let mut s = BumpString::new_in(&bump);
338 /// s.push_str("hello");
339 /// let bytes = s.into_bytes();
340 ///
341 /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
342 /// ```
343 #[inline(always)]
344 #[must_use = "`self` will be dropped if the result is not used"]
345 pub fn into_bytes(self) -> BumpVec<u8, A> {
346 // SAFETY: `BumpVec<u8>` and `BumpString` have the same representation;
347 // only the invariant that the bytes are utf8 is different.
348 unsafe { transmute_value(self) }
349 }
350
351 #[track_caller]
352 #[inline(always)]
353 pub(crate) fn assert_char_boundary(&self, index: usize) {
354 unsafe { self.fixed.cook_ref() }.assert_char_boundary(index);
355 }
356
357 /// Splits the string into two by removing the specified range.
358 ///
359 /// This method does not allocate and does not change the order of the elements.
360 ///
361 /// The excess capacity may end up in either string.
362 /// This behavior is different from <code>String::[split_off](alloc_crate::string::String::split_off)</code> which allocates a new string for the split-off bytes
363 /// so the original string keeps its capacity.
364 /// If you rather want that behavior then you can write this instead:
365 /// ```
366 /// # use bump_scope::{Bump, BumpString};
367 /// # let bump: Bump = Bump::new();
368 /// # let mut string = BumpString::from_str_in("abcde", &bump);
369 /// # let start = 1;
370 /// # let end = 4;
371 /// let mut other = BumpString::new_in(*string.allocator());
372 /// other.push_str(&string[start..end]);
373 /// string.drain(start..end);
374 /// # assert_eq!(string, "ae");
375 /// # assert_eq!(other, "bcd");
376 /// ```
377 ///
378 /// # Panics
379 ///
380 /// Panics if the starting point or end point do not lie on a [`char`] boundary, or if they're out of bounds.
381 ///
382 /// # Complexity
383 ///
384 /// This operation takes `O(1)` time if either the range starts at 0, ends at `len`, or is empty.
385 /// Otherwise it takes `O(min(end, len - start))` time.
386 ///
387 /// # Examples
388 ///
389 /// ```
390 /// # use bump_scope::{Bump, BumpString};
391 /// # let bump: Bump = Bump::new();
392 /// let mut string = BumpString::with_capacity_in(10, &bump);
393 /// string.push_str("foobarbazqux");
394 ///
395 /// let foo = string.split_off(..3);
396 /// assert_eq!(foo, "foo");
397 /// assert_eq!(string, "barbazqux");
398 ///
399 /// let qux = string.split_off(6..);
400 /// assert_eq!(qux, "qux");
401 /// assert_eq!(string, "barbaz");
402 ///
403 /// let rb = string.split_off(2..4);
404 /// assert_eq!(rb, "rb");
405 /// assert_eq!(string, "baaz");
406 ///
407 /// let rest = string.split_off(..);
408 /// assert_eq!(rest, "baaz");
409 /// assert_eq!(string, "");
410 /// ```
411 #[inline]
412 #[expect(clippy::return_self_not_must_use)]
413 pub fn split_off(&mut self, range: impl RangeBounds<usize>) -> Self
414 where
415 A: Clone,
416 {
417 let other = unsafe { self.fixed.cook_mut() }.split_off(range);
418
419 Self {
420 fixed: unsafe { RawFixedBumpString::from_cooked(other) },
421 allocator: self.allocator.clone(),
422 }
423 }
424
425 /// Removes the last character from the string buffer and returns it.
426 ///
427 /// Returns [`None`] if this string is empty.
428 ///
429 /// # Examples
430 ///
431 /// ```
432 /// # use bump_scope::{Bump, BumpString};
433 /// # let bump: Bump = Bump::new();
434 /// let mut s = BumpString::from_str_in("abč", &bump);
435 ///
436 /// assert_eq!(s.pop(), Some('č'));
437 /// assert_eq!(s.pop(), Some('b'));
438 /// assert_eq!(s.pop(), Some('a'));
439 ///
440 /// assert_eq!(s.pop(), None);
441 /// ```
442 #[inline]
443 pub fn pop(&mut self) -> Option<char> {
444 unsafe { self.fixed.cook_mut() }.pop()
445 }
446
447 /// Truncates this string, removing all contents.
448 ///
449 /// While this means the string will have a length of zero, it does not
450 /// touch its capacity.
451 ///
452 /// # Examples
453 ///
454 /// ```
455 /// # use bump_scope::{Bump, BumpString};
456 /// # let bump: Bump = Bump::new();
457 /// #
458 /// let mut s = BumpString::from_str_in("foo", &bump);
459 ///
460 /// s.clear();
461 ///
462 /// assert!(s.is_empty());
463 /// assert_eq!(s.len(), 0);
464 /// assert!(s.capacity() >= 3);
465 /// ```
466 #[inline]
467 pub fn clear(&mut self) {
468 unsafe { self.fixed.cook_mut() }.clear();
469 }
470
471 /// Shortens this string to the specified length.
472 ///
473 /// If `new_len` is greater than or equal to the string's current length, this has no
474 /// effect.
475 ///
476 /// Note that this method has no effect on the allocated capacity
477 /// of the string
478 ///
479 /// # Panics
480 ///
481 /// Panics if `new_len` does not lie on a [`char`] boundary.
482 ///
483 /// # Examples
484 ///
485 /// ```
486 /// # use bump_scope::{Bump, BumpString};
487 /// # let bump: Bump = Bump::new();
488 /// let mut s = BumpString::from_str_in("hello", &bump);
489 ///
490 /// s.truncate(2);
491 ///
492 /// assert_eq!(s, "he");
493 /// ```
494 #[inline]
495 pub fn truncate(&mut self, new_len: usize) {
496 unsafe { self.fixed.cook_mut() }.truncate(new_len);
497 }
498
499 /// Removes a [`char`] from this string at a byte position and returns it.
500 ///
501 /// This is an *O*(*n*) operation, as it requires copying every element in the
502 /// buffer.
503 ///
504 /// # Panics
505 ///
506 /// Panics if `idx` is larger than or equal to the string's length,
507 /// or if it does not lie on a [`char`] boundary.
508 ///
509 /// # Examples
510 ///
511 /// ```
512 /// # use bump_scope::{Bump, BumpString};
513 /// # let bump: Bump = Bump::new();
514 /// #
515 /// let mut s = BumpString::from_str_in("abç", &bump);
516 ///
517 /// assert_eq!(s.remove(0), 'a');
518 /// assert_eq!(s.remove(1), 'ç');
519 /// assert_eq!(s.remove(0), 'b');
520 /// ```
521 #[inline]
522 pub fn remove(&mut self, idx: usize) -> char {
523 unsafe { self.fixed.cook_mut() }.remove(idx)
524 }
525
526 /// Retains only the characters specified by the predicate.
527 ///
528 /// In other words, remove all characters `c` such that `f(c)` returns `false`.
529 /// This method operates in place, visiting each character exactly once in the
530 /// original order, and preserves the order of the retained characters.
531 ///
532 /// # Examples
533 ///
534 /// ```
535 /// # use bump_scope::{Bump, BumpString};
536 /// # let bump: Bump = Bump::new();
537 /// let mut s = BumpString::from_str_in("f_o_ob_ar", &bump);
538 ///
539 /// s.retain(|c| c != '_');
540 ///
541 /// assert_eq!(s, "foobar");
542 /// ```
543 ///
544 /// Because the elements are visited exactly once in the original order,
545 /// external state may be used to decide which elements to keep.
546 ///
547 /// ```
548 /// # use bump_scope::{Bump, BumpString};
549 /// # let bump: Bump = Bump::new();
550 /// let mut s = BumpString::from_str_in("abcde", &bump);
551 /// let keep = [false, true, true, false, true];
552 /// let mut iter = keep.iter();
553 /// s.retain(|_| *iter.next().unwrap());
554 /// assert_eq!(s, "bce");
555 /// ```
556 #[inline]
557 pub fn retain<F>(&mut self, f: F)
558 where
559 F: FnMut(char) -> bool,
560 {
561 unsafe { self.fixed.cook_mut() }.retain(f);
562 }
563
564 /// Removes the specified range from the string in bulk, returning all
565 /// removed characters as an iterator.
566 ///
567 /// The returned iterator keeps a mutable borrow on the string to optimize
568 /// its implementation.
569 ///
570 /// # Panics
571 ///
572 /// Panics if the starting point or end point do not lie on a [`char`]
573 /// boundary, or if they're out of bounds.
574 ///
575 /// # Leaking
576 ///
577 /// If the returned iterator goes out of scope without being dropped (due to
578 /// [`core::mem::forget`], for example), the string may still contain a copy
579 /// of any drained characters, or may have lost characters arbitrarily,
580 /// including characters outside the range.
581 ///
582 /// # Examples
583 ///
584 /// Basic usage:
585 ///
586 /// ```
587 /// # use bump_scope::{Bump, BumpString};
588 /// # let bump: Bump = Bump::new();
589 /// let mut s = BumpString::from_str_in("α is alpha, β is beta", &bump);
590 /// let beta_offset = s.find('β').unwrap_or(s.len());
591 ///
592 /// // Remove the range up until the β from the string
593 /// let t: String = s.drain(..beta_offset).collect();
594 /// assert_eq!(t, "α is alpha, ");
595 /// assert_eq!(s, "β is beta");
596 ///
597 /// // A full range clears the string, like `clear()` does
598 /// s.drain(..);
599 /// assert_eq!(s, "");
600 /// ```
601 pub fn drain<R>(&mut self, range: R) -> owned_str::Drain<'_>
602 where
603 R: RangeBounds<usize>,
604 {
605 unsafe { self.fixed.cook_mut() }.drain(range)
606 }
607
608 /// Extracts a string slice containing the entire `BumpString`.
609 #[must_use]
610 #[inline(always)]
611 pub fn as_str(&self) -> &str {
612 unsafe { self.fixed.cook_ref() }.as_str()
613 }
614
615 /// Converts a `BumpString` into a mutable string slice.
616 #[must_use]
617 #[inline(always)]
618 pub fn as_mut_str(&mut self) -> &mut str {
619 unsafe { self.fixed.cook_mut() }.as_mut_str()
620 }
621
622 /// Returns a byte slice of this `BumpString`'s contents.
623 #[must_use]
624 #[inline(always)]
625 pub fn as_bytes(&self) -> &[u8] {
626 unsafe { self.fixed.cook_ref() }.as_bytes()
627 }
628
629 /// Returns a mutable reference to the contents of this `BumpString`.
630 ///
631 /// # Safety
632 ///
633 /// This function is unsafe because the returned `&mut BumpVec<u8>` allows writing
634 /// bytes which are not valid UTF-8. If this constraint is violated, using
635 /// the original `BumpString` after dropping the `&mut BumpVec<u8>` may violate memory
636 /// safety, as `BumpString`s must be valid UTF-8.
637 #[must_use]
638 #[inline(always)]
639 pub unsafe fn as_mut_vec(&mut self) -> &mut BumpVec<u8, A> {
640 // SAFETY: `BumpVec<u8>` and `BumpString` have the same representation;
641 // only the invariant that the bytes are utf8 is different.
642 unsafe { transmute_mut(self) }
643 }
644
645 /// Returns a raw pointer to the slice, or a dangling raw pointer
646 /// valid for zero sized reads.
647 #[inline]
648 #[must_use]
649 pub fn as_ptr(&self) -> *const u8 {
650 self.fixed.as_ptr()
651 }
652
653 /// Returns an unsafe mutable pointer to slice, or a dangling
654 /// raw pointer valid for zero sized reads.
655 #[inline]
656 pub fn as_mut_ptr(&mut self) -> *mut u8 {
657 self.fixed.as_mut_ptr()
658 }
659
660 /// Returns a `NonNull` pointer to the string's buffer, or a dangling
661 /// `NonNull` pointer valid for zero sized reads if the string didn't allocate.
662 ///
663 /// The caller must ensure that the string outlives the pointer this
664 /// function returns, or else it will end up dangling.
665 /// Modifying the string may cause its buffer to be reallocated,
666 /// which would also make any pointers to it invalid.
667 ///
668 /// This method guarantees that for the purpose of the aliasing model, this method
669 /// does not materialize a reference to the underlying slice, and thus the returned pointer
670 /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
671 /// and [`as_non_null`].
672 /// Note that calling other methods that materialize references to the slice,
673 /// or references to specific elements you are planning on accessing through this pointer,
674 /// may still invalidate this pointer.
675 /// See the second example below for how this guarantee can be used.
676 ///
677 /// # Examples
678 ///
679 /// ```
680 /// # use bump_scope::{Bump, BumpString};
681 /// # let bump: Bump = Bump::new();
682 /// // Allocate vector big enough for 4 elements.
683 /// let size = 4;
684 /// let mut x = BumpString::with_capacity_in(size, &bump);
685 /// let x_ptr = x.as_non_null();
686 ///
687 /// // Initialize elements via raw pointer writes, then set length.
688 /// unsafe {
689 /// for i in 0..size {
690 /// x_ptr.add(i).write(i as u8 + b'a');
691 /// }
692 /// x.as_mut_vec().set_len(size);
693 /// }
694 /// assert_eq!(&*x, "abcd");
695 /// ```
696 ///
697 /// Due to the aliasing guarantee, the following code is legal:
698 ///
699 /// ```
700 /// # use bump_scope::{Bump, bump_format};
701 /// # let bump: Bump = Bump::new();
702 /// unsafe {
703 /// let v = bump_format!(in &bump, "a");
704 /// let ptr1 = v.as_non_null();
705 /// ptr1.write(b'b');
706 /// let ptr2 = v.as_non_null();
707 /// ptr2.write(b'c');
708 /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
709 /// ptr1.write(b'd');
710 /// }
711 /// ```
712 ///
713 /// [`as_mut_ptr`]: Self::as_mut_ptr
714 /// [`as_ptr`]: Self::as_ptr
715 /// [`as_non_null`]: Self::as_non_null
716 #[must_use]
717 #[inline(always)]
718 pub const fn as_non_null(&self) -> NonNull<u8> {
719 self.fixed.as_non_null()
720 }
721
722 #[inline(always)]
723 pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
724 unsafe { self.fixed.set_len(new_len) };
725 }
726
727 /// Constructs a new empty `BumpString` with the specified capacity
728 /// in the provided bump allocator.
729 ///
730 /// The string will be able to hold `capacity` bytes without
731 /// reallocating. If `capacity` is 0, the string will not allocate.
732 ///
733 /// # Panics
734 /// Panics if the allocation fails.
735 ///
736 /// # Examples
737 /// ```
738 /// # use bump_scope::{Bump, BumpString};
739 /// # let bump: Bump = Bump::new();
740 /// let mut s = BumpString::<_>::with_capacity_in(10, &bump);
741 ///
742 /// // The String contains no chars, even though it has capacity for more
743 /// assert_eq!(s.len(), 0);
744 ///
745 /// // These are all done without reallocating...
746 /// let cap = s.capacity();
747 /// for _ in 0..10 {
748 /// s.push('a');
749 /// }
750 ///
751 /// assert_eq!(s.capacity(), cap);
752 ///
753 /// // ...but this may make the string reallocate
754 /// s.push('a');
755 /// ```
756 #[must_use]
757 #[inline(always)]
758 #[cfg(feature = "panic-on-alloc")]
759 pub fn with_capacity_in(capacity: usize, allocator: A) -> Self {
760 panic_on_error(Self::generic_with_capacity_in(capacity, allocator))
761 }
762
763 /// Constructs a new empty `BumpString` with the specified capacity
764 /// in the provided bump allocator.
765 ///
766 /// The string will be able to hold `capacity` bytes without
767 /// reallocating. If `capacity` is 0, the string will not allocate.
768 ///
769 /// # Errors
770 /// Errors if the allocation fails.
771 ///
772 /// # Examples
773 /// ```
774 /// # use bump_scope::{Bump, BumpString};
775 /// # let bump: Bump = Bump::new();
776 /// let mut s = BumpString::<_>::try_with_capacity_in(10, &bump)?;
777 ///
778 /// // The String contains no chars, even though it has capacity for more
779 /// assert_eq!(s.len(), 0);
780 ///
781 /// // These are all done without reallocating...
782 /// let cap = s.capacity();
783 /// for _ in 0..10 {
784 /// s.push('a');
785 /// }
786 ///
787 /// assert_eq!(s.capacity(), cap);
788 ///
789 /// // ...but this may make the string reallocate
790 /// s.push('a');
791 /// # Ok::<(), bump_scope::alloc::AllocError>(())
792 /// ```
793 #[inline(always)]
794 pub fn try_with_capacity_in(capacity: usize, allocator: A) -> Result<Self, AllocError> {
795 Self::generic_with_capacity_in(capacity, allocator)
796 }
797
798 #[inline]
799 pub(crate) fn generic_with_capacity_in<E: ErrorBehavior>(capacity: usize, allocator: A) -> Result<Self, E> {
800 if capacity == 0 {
801 return Ok(Self {
802 fixed: RawFixedBumpString::EMPTY,
803 allocator,
804 });
805 }
806
807 Ok(Self {
808 fixed: unsafe { RawFixedBumpString::allocate(&allocator, capacity)? },
809 allocator,
810 })
811 }
812
813 /// Constructs a new `BumpString` from a `&str`.
814 ///
815 /// # Panics
816 /// Panics if the allocation fails.
817 ///
818 /// # Examples
819 /// ```
820 /// # use bump_scope::{Bump, BumpString};
821 /// # let bump: Bump = Bump::new();
822 /// let string = BumpString::from_str_in("Hello!", &bump);
823 /// assert_eq!(string, "Hello!");
824 /// ```
825 #[must_use]
826 #[inline(always)]
827 #[cfg(feature = "panic-on-alloc")]
828 pub fn from_str_in(string: &str, allocator: A) -> Self {
829 panic_on_error(Self::generic_from_str_in(string, allocator))
830 }
831
832 /// Constructs a new `BumpString` from a `&str`.
833 ///
834 /// # Errors
835 /// Errors if the allocation fails.
836 ///
837 /// # Examples
838 /// ```
839 /// # use bump_scope::{Bump, BumpString};
840 /// # let bump: Bump = Bump::new();
841 /// let string = BumpString::try_from_str_in("Hello!", &bump)?;
842 /// assert_eq!(string, "Hello!");
843 /// # Ok::<(), bump_scope::alloc::AllocError>(())
844 /// ```
845 #[inline(always)]
846 pub fn try_from_str_in(string: &str, allocator: A) -> Result<Self, AllocError> {
847 Self::generic_from_str_in(string, allocator)
848 }
849
850 #[inline]
851 pub(crate) fn generic_from_str_in<E: ErrorBehavior>(string: &str, allocator: A) -> Result<Self, E> {
852 let mut this = Self::generic_with_capacity_in(string.len(), allocator)?;
853
854 unsafe {
855 ptr::copy_nonoverlapping(string.as_ptr(), this.fixed.as_mut_ptr(), string.len());
856 this.as_mut_vec().set_len(string.len());
857 }
858
859 Ok(this)
860 }
861
862 /// Converts a slice of bytes to a string, including invalid characters.
863 ///
864 /// Strings are made of bytes ([`u8`]), and a slice of bytes
865 /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts
866 /// between the two. Not all byte slices are valid strings, however: strings
867 /// are required to be valid UTF-8. During this conversion,
868 /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with
869 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: �
870 ///
871 /// [byteslice]: prim@slice
872 /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
873 ///
874 /// If you are sure that the byte slice is valid UTF-8, and you don't want
875 /// to incur the overhead of the conversion, there is an unsafe version
876 /// of this function, [`from_utf8_unchecked`], which has the same behavior
877 /// but skips the checks.
878 ///
879 /// [`from_utf8_unchecked`]: Self::from_utf8_unchecked
880 ///
881 /// # Panics
882 /// Panics if the allocation fails.
883 ///
884 /// # Examples
885 /// Basic usage:
886 ///
887 /// ```
888 /// # use bump_scope::{Bump, BumpString};
889 /// # let bump: Bump = Bump::new();
890 /// // some bytes, in a vector
891 /// let sparkle_heart = [240, 159, 146, 150];
892 ///
893 /// let sparkle_heart = BumpString::from_utf8_lossy_in(&sparkle_heart, &bump);
894 ///
895 /// assert_eq!("💖", sparkle_heart);
896 /// ```
897 ///
898 /// Incorrect bytes:
899 ///
900 /// ```
901 /// # use bump_scope::{Bump, BumpString};
902 /// # let bump: Bump = Bump::new();
903 /// // some invalid bytes
904 /// let input = b"Hello \xF0\x90\x80World";
905 /// let output = BumpString::from_utf8_lossy_in(input, &bump);
906 ///
907 /// assert_eq!("Hello �World", output);
908 /// ```
909 #[must_use]
910 #[inline(always)]
911 #[cfg(feature = "panic-on-alloc")]
912 pub fn from_utf8_lossy_in(v: &[u8], allocator: A) -> Self {
913 panic_on_error(Self::generic_from_utf8_lossy_in(v, allocator))
914 }
915
916 /// Converts a slice of bytes to a string, including invalid characters.
917 ///
918 /// Strings are made of bytes ([`u8`]), and a slice of bytes
919 /// ([`&[u8]`][byteslice]) is made of bytes, so this function converts
920 /// between the two. Not all byte slices are valid strings, however: strings
921 /// are required to be valid UTF-8. During this conversion,
922 /// `from_utf8_lossy()` will replace any invalid UTF-8 sequences with
923 /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: �
924 ///
925 /// [byteslice]: prim@slice
926 /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
927 ///
928 /// If you are sure that the byte slice is valid UTF-8, and you don't want
929 /// to incur the overhead of the conversion, there is an unsafe version
930 /// of this function, [`from_utf8_unchecked`], which has the same behavior
931 /// but skips the checks.
932 ///
933 /// [`from_utf8_unchecked`]: Self::from_utf8_unchecked
934 ///
935 /// # Errors
936 /// Errors if the allocation fails.
937 ///
938 /// # Examples
939 /// Basic usage:
940 ///
941 /// ```
942 /// # use bump_scope::{Bump, BumpString};
943 /// # let bump: Bump = Bump::new();
944 /// // some bytes, in a vector
945 /// let sparkle_heart = [240, 159, 146, 150];
946 ///
947 /// let sparkle_heart = BumpString::try_from_utf8_lossy_in(&sparkle_heart, &bump)?;
948 ///
949 /// assert_eq!("💖", sparkle_heart);
950 /// # Ok::<(), bump_scope::alloc::AllocError>(())
951 /// ```
952 ///
953 /// Incorrect bytes:
954 ///
955 /// ```
956 /// # use bump_scope::{Bump, BumpString};
957 /// # let bump: Bump = Bump::new();
958 /// // some invalid bytes
959 /// let input = b"Hello \xF0\x90\x80World";
960 /// let output = BumpString::try_from_utf8_lossy_in(input, &bump)?;
961 ///
962 /// assert_eq!("Hello �World", output);
963 /// # Ok::<(), bump_scope::alloc::AllocError>(())
964 /// ```
965 #[inline(always)]
966 pub fn try_from_utf8_lossy_in(v: &[u8], allocator: A) -> Result<Self, AllocError> {
967 Self::generic_from_utf8_lossy_in(v, allocator)
968 }
969
970 pub(crate) fn generic_from_utf8_lossy_in<E: ErrorBehavior>(v: &[u8], allocator: A) -> Result<Self, E> {
971 let mut iter = v.utf8_chunks();
972
973 let first_valid = if let Some(chunk) = iter.next() {
974 let valid = chunk.valid();
975 if chunk.invalid().is_empty() {
976 debug_assert_eq!(valid.len(), v.len());
977 return Self::generic_from_str_in(valid, allocator);
978 }
979 valid
980 } else {
981 return Ok(Self::new_in(allocator));
982 };
983
984 const REPLACEMENT: &str = "\u{FFFD}";
985
986 let mut res = Self::generic_with_capacity_in(v.len(), allocator)?;
987 res.generic_push_str(first_valid)?;
988 res.generic_push_str(REPLACEMENT)?;
989
990 for chunk in iter {
991 res.generic_push_str(chunk.valid())?;
992 if !chunk.invalid().is_empty() {
993 res.generic_push_str(REPLACEMENT)?;
994 }
995 }
996
997 Ok(res)
998 }
999
1000 /// Decode a UTF-16–encoded vector `v` into a `BumpString`, returning [`Err`]
1001 /// if `v` contains any invalid data.
1002 ///
1003 /// # Panics
1004 /// Panics if the allocation fails.
1005 ///
1006 /// # Examples
1007 /// ```
1008 /// # use bump_scope::{Bump, BumpString};
1009 /// # let bump: Bump = Bump::new();
1010 /// // 𝄞music
1011 /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
1012 /// 0x0073, 0x0069, 0x0063];
1013 /// assert_eq!(BumpString::from_str_in("𝄞music", &bump),
1014 /// BumpString::from_utf16_in(v, &bump).unwrap());
1015 ///
1016 /// // 𝄞mu<invalid>ic
1017 /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
1018 /// 0xD800, 0x0069, 0x0063];
1019 /// assert!(BumpString::from_utf16_in(v, &bump).is_err());
1020 /// ```
1021 #[inline(always)]
1022 #[cfg(feature = "panic-on-alloc")]
1023 #[expect(clippy::missing_errors_doc)]
1024 pub fn from_utf16_in(v: &[u16], allocator: A) -> Result<Self, FromUtf16Error> {
1025 panic_on_error(Self::generic_from_utf16_in(v, allocator))
1026 }
1027
1028 /// Decode a UTF-16–encoded vector `v` into a `BumpString`, returning [`Err`]
1029 /// if `v` contains any invalid data.
1030 ///
1031 /// # Errors
1032 /// Errors if the allocation fails.
1033 ///
1034 /// # Examples
1035 /// ```
1036 /// # use bump_scope::{Bump, BumpString};
1037 /// # let bump: Bump = Bump::new();
1038 /// // 𝄞music
1039 /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
1040 /// 0x0073, 0x0069, 0x0063];
1041 /// assert_eq!(BumpString::try_from_str_in("𝄞music", &bump)?,
1042 /// BumpString::try_from_utf16_in(v, &bump)?.unwrap());
1043 ///
1044 /// // 𝄞mu<invalid>ic
1045 /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
1046 /// 0xD800, 0x0069, 0x0063];
1047 /// assert!(BumpString::try_from_utf16_in(v, &bump)?.is_err());
1048 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1049 /// ```
1050 #[inline(always)]
1051 pub fn try_from_utf16_in(v: &[u16], allocator: A) -> Result<Result<Self, FromUtf16Error>, AllocError> {
1052 Self::generic_from_utf16_in(v, allocator)
1053 }
1054
1055 pub(crate) fn generic_from_utf16_in<E: ErrorBehavior>(
1056 v: &[u16],
1057 allocator: A,
1058 ) -> Result<Result<Self, FromUtf16Error>, E> {
1059 // This isn't done via collect::<Result<_, _>>() for performance reasons.
1060 // STD-FIXME: the function can be simplified again when #48994 is closed.
1061 let mut ret = Self::generic_with_capacity_in(v.len(), allocator)?;
1062
1063 for c in char::decode_utf16(v.iter().copied()) {
1064 if let Ok(c) = c {
1065 ret.generic_push(c)?;
1066 } else {
1067 return Ok(Err(FromUtf16Error(())));
1068 }
1069 }
1070
1071 Ok(Ok(ret))
1072 }
1073
1074 /// Decode a UTF-16–encoded slice `v` into a `BumpString`, replacing
1075 /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD].
1076 ///
1077 /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
1078 ///
1079 /// # Panics
1080 /// Panics if the allocation fails.
1081 ///
1082 /// # Examples
1083 /// ```
1084 /// # use bump_scope::{Bump, BumpString};
1085 /// # let bump: Bump = Bump::new();
1086 /// // 𝄞mus<invalid>ic<invalid>
1087 /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
1088 /// 0x0073, 0xDD1E, 0x0069, 0x0063,
1089 /// 0xD834];
1090 ///
1091 /// assert_eq!(BumpString::from_str_in("𝄞mus\u{FFFD}ic\u{FFFD}", &bump),
1092 /// BumpString::from_utf16_lossy_in(v, &bump));
1093 /// ```
1094 #[must_use]
1095 #[inline(always)]
1096 #[cfg(feature = "panic-on-alloc")]
1097 pub fn from_utf16_lossy_in(v: &[u16], allocator: A) -> Self {
1098 panic_on_error(Self::generic_from_utf16_lossy_in(v, allocator))
1099 }
1100
1101 /// Decode a UTF-16–encoded slice `v` into a `BumpString`, replacing
1102 /// invalid data with [the replacement character (`U+FFFD`)][U+FFFD].
1103 ///
1104 /// [U+FFFD]: core::char::REPLACEMENT_CHARACTER
1105 ///
1106 /// # Errors
1107 /// Errors if the allocation fails.
1108 ///
1109 /// # Examples
1110 /// ```
1111 /// # use bump_scope::{Bump, BumpString};
1112 /// # let bump: Bump = Bump::new();
1113 /// // 𝄞mus<invalid>ic<invalid>
1114 /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
1115 /// 0x0073, 0xDD1E, 0x0069, 0x0063,
1116 /// 0xD834];
1117 ///
1118 /// assert_eq!(BumpString::try_from_str_in("𝄞mus\u{FFFD}ic\u{FFFD}", &bump)?,
1119 /// BumpString::try_from_utf16_lossy_in(v, &bump)?);
1120 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1121 /// ```
1122 #[inline(always)]
1123 pub fn try_from_utf16_lossy_in(v: &[u16], allocator: A) -> Result<Self, AllocError> {
1124 Self::generic_from_utf16_lossy_in(v, allocator)
1125 }
1126
1127 pub(crate) fn generic_from_utf16_lossy_in<E: ErrorBehavior>(v: &[u16], allocator: A) -> Result<Self, E> {
1128 let iter = char::decode_utf16(v.iter().copied());
1129 let capacity = iter.size_hint().0;
1130 let mut string = Self::generic_with_capacity_in(capacity, allocator)?;
1131
1132 for r in iter {
1133 string.generic_push(r.unwrap_or(char::REPLACEMENT_CHARACTER))?;
1134 }
1135
1136 Ok(string)
1137 }
1138
1139 /// Appends the given [`char`] to the end of this string.
1140 ///
1141 /// # Panics
1142 /// Panics if the allocation fails.
1143 ///
1144 /// # Examples
1145 /// ```
1146 /// # use bump_scope::{Bump, BumpString};
1147 /// # let bump: Bump = Bump::new();
1148 /// let mut s = BumpString::from_str_in("abc", &bump);
1149 ///
1150 /// s.push('1');
1151 /// s.push('2');
1152 /// s.push('3');
1153 ///
1154 /// assert_eq!(s, "abc123");
1155 /// ```
1156 #[inline(always)]
1157 #[cfg(feature = "panic-on-alloc")]
1158 pub fn push(&mut self, ch: char) {
1159 panic_on_error(self.generic_push(ch));
1160 }
1161
1162 /// Appends the given [`char`] to the end of this string.
1163 ///
1164 /// # Errors
1165 /// Errors if the allocation fails.
1166 ///
1167 /// # Examples
1168 /// ```
1169 /// # use bump_scope::{Bump, BumpString};
1170 /// # let bump: Bump = Bump::new();
1171 /// let mut s = BumpString::try_from_str_in("abc", &bump)?;
1172 ///
1173 /// s.try_push('1')?;
1174 /// s.try_push('2')?;
1175 /// s.try_push('3')?;
1176 ///
1177 /// assert_eq!(s, "abc123");
1178 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1179 /// ```
1180 #[inline(always)]
1181 pub fn try_push(&mut self, ch: char) -> Result<(), AllocError> {
1182 self.generic_push(ch)
1183 }
1184
1185 #[inline]
1186 pub(crate) fn generic_push<E: ErrorBehavior>(&mut self, ch: char) -> Result<(), E> {
1187 let vec = unsafe { self.as_mut_vec() };
1188
1189 match ch.len_utf8() {
1190 1 => vec.generic_push(ch as u8),
1191 _ => vec.generic_extend_from_slice_copy(ch.encode_utf8(&mut [0; 4]).as_bytes()),
1192 }
1193 }
1194
1195 /// Appends a given string slice onto the end of this string.
1196 ///
1197 /// # Panics
1198 /// Panics if the allocation fails.
1199 ///
1200 /// # Examples
1201 /// ```
1202 /// # use bump_scope::{Bump, BumpString};
1203 /// # let bump: Bump = Bump::new();
1204 /// let mut s = BumpString::from_str_in("foo", &bump);
1205 ///
1206 /// s.push_str("bar");
1207 ///
1208 /// assert_eq!(s, "foobar");
1209 /// ```
1210 #[inline(always)]
1211 #[cfg(feature = "panic-on-alloc")]
1212 pub fn push_str(&mut self, string: &str) {
1213 panic_on_error(self.generic_push_str(string));
1214 }
1215
1216 /// Appends a given string slice onto the end of this string.
1217 ///
1218 /// # Errors
1219 /// Errors if the allocation fails.
1220 ///
1221 /// # Examples
1222 /// ```
1223 /// # use bump_scope::{Bump, BumpString};
1224 /// # let bump: Bump = Bump::new();
1225 /// let mut s = BumpString::try_from_str_in("foo", &bump)?;
1226 ///
1227 /// s.try_push_str("bar")?;
1228 ///
1229 /// assert_eq!(s, "foobar");
1230 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1231 /// ```
1232 #[inline(always)]
1233 pub fn try_push_str(&mut self, string: &str) -> Result<(), AllocError> {
1234 self.generic_push_str(string)
1235 }
1236
1237 #[inline]
1238 pub(crate) fn generic_push_str<E: ErrorBehavior>(&mut self, string: &str) -> Result<(), E> {
1239 let vec = unsafe { self.as_mut_vec() };
1240 vec.generic_extend_from_slice_copy(string.as_bytes())
1241 }
1242
1243 /// Inserts a character into this string at a byte position.
1244 ///
1245 /// This is an *O*(*n*) operation as it requires copying every element in the
1246 /// buffer.
1247 ///
1248 /// # Panics
1249 /// Panics if the allocation fails.
1250 ///
1251 /// Panics if `idx` is larger than the string's length, or if it does not
1252 /// lie on a [`char`] boundary.
1253 ///
1254 /// # Examples
1255 /// ```
1256 /// # use bump_scope::{Bump, BumpString};
1257 /// # let bump: Bump = Bump::new();
1258 /// let mut s = BumpString::with_capacity_in(3, &bump);
1259 ///
1260 /// s.insert(0, 'f');
1261 /// s.insert(1, 'o');
1262 /// s.insert(2, 'o');
1263 ///
1264 /// assert_eq!("foo", s);
1265 /// ```
1266 #[inline(always)]
1267 #[cfg(feature = "panic-on-alloc")]
1268 pub fn insert(&mut self, idx: usize, ch: char) {
1269 panic_on_error(self.generic_insert(idx, ch));
1270 }
1271
1272 /// Inserts a character into this string at a byte position.
1273 ///
1274 /// This is an *O*(*n*) operation as it requires copying every element in the
1275 /// buffer.
1276 ///
1277 /// # Panics
1278 /// Panics if `idx` is larger than the string's length, or if it does not
1279 /// lie on a [`char`] boundary.
1280 ///
1281 /// # Errors
1282 /// Errors if the allocation fails.
1283 ///
1284 /// # Examples
1285 /// ```
1286 /// # use bump_scope::{Bump, BumpString};
1287 /// # let bump: Bump = Bump::new();
1288 /// let mut s = BumpString::try_with_capacity_in(3, &bump)?;
1289 ///
1290 /// s.try_insert(0, 'f')?;
1291 /// s.try_insert(1, 'o')?;
1292 /// s.try_insert(2, 'o')?;
1293 ///
1294 /// assert_eq!("foo", s);
1295 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1296 /// ```
1297 #[inline(always)]
1298 pub fn try_insert(&mut self, idx: usize, ch: char) -> Result<(), AllocError> {
1299 self.generic_insert(idx, ch)
1300 }
1301
1302 #[inline]
1303 pub(crate) fn generic_insert<E: ErrorBehavior>(&mut self, idx: usize, ch: char) -> Result<(), E> {
1304 self.assert_char_boundary(idx);
1305 let mut bits = [0; 4];
1306 let bits = ch.encode_utf8(&mut bits).as_bytes();
1307
1308 unsafe { self.insert_bytes(idx, bits) }
1309 }
1310
1311 /// Inserts a string slice into this string at a byte position.
1312 ///
1313 /// This is an *O*(*n*) operation as it requires copying every element in the
1314 /// buffer.
1315 ///
1316 /// # Panics
1317 /// Panics if the allocation fails.
1318 ///
1319 /// Panics if `idx` is larger than the string's length, or if it does not
1320 /// lie on a [`char`] boundary.
1321 ///
1322 /// # Examples
1323 /// ```
1324 /// # use bump_scope::{Bump, BumpString};
1325 /// # let bump: Bump = Bump::new();
1326 /// let mut s = BumpString::from_str_in("bar", &bump);
1327 ///
1328 /// s.insert_str(0, "foo");
1329 ///
1330 /// assert_eq!("foobar", s);
1331 /// ```
1332 #[inline(always)]
1333 #[cfg(feature = "panic-on-alloc")]
1334 pub fn insert_str(&mut self, idx: usize, string: &str) {
1335 panic_on_error(self.generic_insert_str(idx, string));
1336 }
1337
1338 /// Inserts a string slice into this string at a byte position.
1339 ///
1340 /// This is an *O*(*n*) operation as it requires copying every element in the
1341 /// buffer.
1342 ///
1343 /// # Panics
1344 /// Panics if `idx` is larger than the string's length, or if it does not
1345 /// lie on a [`char`] boundary.
1346 ///
1347 /// # Errors
1348 /// Errors if the allocation fails.
1349 ///
1350 /// # Examples
1351 /// ```
1352 /// # use bump_scope::{Bump, BumpString};
1353 /// # let bump: Bump = Bump::new();
1354 /// let mut s = BumpString::try_from_str_in("bar", &bump)?;
1355 ///
1356 /// s.try_insert_str(0, "foo")?;
1357 ///
1358 /// assert_eq!("foobar", s);
1359 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1360 /// ```
1361 #[inline(always)]
1362 pub fn try_insert_str(&mut self, idx: usize, string: &str) -> Result<(), AllocError> {
1363 self.generic_insert_str(idx, string)
1364 }
1365
1366 #[inline]
1367 pub(crate) fn generic_insert_str<E: ErrorBehavior>(&mut self, idx: usize, string: &str) -> Result<(), E> {
1368 self.assert_char_boundary(idx);
1369 unsafe { self.insert_bytes(idx, string.as_bytes()) }
1370 }
1371
1372 /// Copies elements from `src` range to the end of the string.
1373 ///
1374 /// # Panics
1375 /// Panics if the allocation fails.
1376 ///
1377 /// Panics if the starting point or end point do not lie on a [`char`]
1378 /// boundary, or if they're out of bounds.
1379 ///
1380 /// # Examples
1381 /// ```
1382 /// # use bump_scope::{Bump, BumpString};
1383 /// # let bump: Bump = Bump::new();
1384 /// let mut string = BumpString::from_str_in("abcde", &bump);
1385 ///
1386 /// string.extend_from_within(2..);
1387 /// assert_eq!(string, "abcdecde");
1388 ///
1389 /// string.extend_from_within(..2);
1390 /// assert_eq!(string, "abcdecdeab");
1391 ///
1392 /// string.extend_from_within(4..8);
1393 /// assert_eq!(string, "abcdecdeabecde");
1394 /// ```
1395 #[inline(always)]
1396 #[cfg(feature = "panic-on-alloc")]
1397 pub fn extend_from_within<R>(&mut self, src: R)
1398 where
1399 R: RangeBounds<usize>,
1400 {
1401 panic_on_error(self.generic_extend_from_within(src));
1402 }
1403
1404 /// Copies elements from `src` range to the end of the string.
1405 ///
1406 /// # Panics
1407 /// Panics if the starting point or end point do not lie on a [`char`]
1408 /// boundary, or if they're out of bounds.
1409 ///
1410 /// # Errors
1411 /// Errors if the allocation fails.
1412 ///
1413 /// # Examples
1414 /// ```
1415 /// # use bump_scope::{Bump, BumpString};
1416 /// # let bump: Bump = Bump::new();
1417 /// let mut string = BumpString::try_from_str_in("abcde", &bump)?;
1418 ///
1419 /// string.try_extend_from_within(2..)?;
1420 /// assert_eq!(string, "abcdecde");
1421 ///
1422 /// string.try_extend_from_within(..2)?;
1423 /// assert_eq!(string, "abcdecdeab");
1424 ///
1425 /// string.try_extend_from_within(4..8)?;
1426 /// assert_eq!(string, "abcdecdeabecde");
1427 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1428 /// ```
1429 #[inline(always)]
1430 pub fn try_extend_from_within<R>(&mut self, src: R) -> Result<(), AllocError>
1431 where
1432 R: RangeBounds<usize>,
1433 {
1434 self.generic_extend_from_within(src)
1435 }
1436
1437 #[inline]
1438 pub(crate) fn generic_extend_from_within<E: ErrorBehavior, R: RangeBounds<usize>>(&mut self, src: R) -> Result<(), E> {
1439 let src @ Range { start, end } = polyfill::slice::range(src, ..self.len());
1440
1441 self.assert_char_boundary(start);
1442 self.assert_char_boundary(end);
1443
1444 let vec = unsafe { self.as_mut_vec() };
1445 vec.generic_extend_from_within_copy(src)
1446 }
1447
1448 /// Extends this string by pushing `additional` new zero bytes.
1449 ///
1450 /// # Panics
1451 /// Panics if the allocation fails.
1452 ///
1453 /// # Examples
1454 /// ```
1455 /// # use bump_scope::{Bump, BumpString};
1456 /// # let bump: Bump = Bump::new();
1457 /// let mut string = BumpString::from_str_in("What?", &bump);
1458 /// string.extend_zeroed(3);
1459 /// assert_eq!(string, "What?\0\0\0");
1460 /// ```
1461 #[inline(always)]
1462 #[cfg(feature = "panic-on-alloc")]
1463 pub fn extend_zeroed(&mut self, additional: usize) {
1464 panic_on_error(self.generic_extend_zeroed(additional));
1465 }
1466
1467 /// Extends this string by pushing `additional` new zero bytes.
1468 ///
1469 /// # Errors
1470 /// Errors if the allocation fails.
1471 ///
1472 /// # Examples
1473 /// ```
1474 /// # use bump_scope::{Bump, BumpString};
1475 /// # let bump: Bump = Bump::new();
1476 /// let mut string = BumpString::try_from_str_in("What?", &bump)?;
1477 /// string.try_extend_zeroed(3)?;
1478 /// assert_eq!(string, "What?\0\0\0");
1479 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1480 /// ```
1481 #[inline(always)]
1482 pub fn try_extend_zeroed(&mut self, additional: usize) -> Result<(), AllocError> {
1483 self.generic_extend_zeroed(additional)
1484 }
1485
1486 #[inline]
1487 pub(crate) fn generic_extend_zeroed<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1488 let vec = unsafe { self.as_mut_vec() };
1489
1490 vec.generic_reserve(additional)?;
1491
1492 unsafe {
1493 let ptr = vec.as_mut_ptr();
1494 let len = vec.len();
1495
1496 ptr.add(len).write_bytes(0, additional);
1497 vec.set_len(len + additional);
1498 }
1499
1500 Ok(())
1501 }
1502
1503 /// Removes the specified range in the string,
1504 /// and replaces it with the given string.
1505 /// The given string doesn't need to be the same length as the range.
1506 ///
1507 /// # Panics
1508 /// Panics if the allocation fails.
1509 ///
1510 /// Panics if the starting point or end point do not lie on a [`char`]
1511 /// boundary, or if they're out of bounds.
1512 ///
1513 /// # Examples
1514 /// ```
1515 /// # use bump_scope::{Bump, BumpString};
1516 /// # let bump: Bump = Bump::new();
1517 /// let mut s = BumpString::from_str_in("α is alpha, β is beta", &bump);
1518 /// let beta_offset = s.find('β').unwrap_or(s.len());
1519 ///
1520 /// // Replace the range up until the β from the string
1521 /// s.replace_range(..beta_offset, "Α is capital alpha; ");
1522 /// assert_eq!(s, "Α is capital alpha; β is beta");
1523 /// ```
1524 #[inline(always)]
1525 #[cfg(feature = "panic-on-alloc")]
1526 pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
1527 where
1528 R: RangeBounds<usize>,
1529 {
1530 panic_on_error(self.generic_replace_range(range, replace_with));
1531 }
1532
1533 /// Removes the specified range in the string,
1534 /// and replaces it with the given string.
1535 /// The given string doesn't need to be the same length as the range.
1536 ///
1537 /// # Panics
1538 /// Panics if the starting point or end point do not lie on a [`char`]
1539 /// boundary, or if they're out of bounds.
1540 ///
1541 /// # Errors
1542 /// Errors if the allocation fails.
1543 ///
1544 /// # Examples
1545 /// ```
1546 /// # use bump_scope::{Bump, BumpString};
1547 /// # let bump: Bump = Bump::new();
1548 /// let mut s = BumpString::try_from_str_in("α is alpha, β is beta", &bump)?;
1549 /// let beta_offset = s.find('β').unwrap_or(s.len());
1550 ///
1551 /// // Replace the range up until the β from the string
1552 /// s.try_replace_range(..beta_offset, "Α is capital alpha; ")?;
1553 /// assert_eq!(s, "Α is capital alpha; β is beta");
1554 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1555 /// ```
1556 #[inline(always)]
1557 pub fn try_replace_range<R>(&mut self, range: R, replace_with: &str) -> Result<(), AllocError>
1558 where
1559 R: RangeBounds<usize>,
1560 {
1561 self.generic_replace_range(range, replace_with)
1562 }
1563
1564 #[inline]
1565 pub(crate) fn generic_replace_range<E: ErrorBehavior, R: RangeBounds<usize>>(
1566 &mut self,
1567 range: R,
1568 replace_with: &str,
1569 ) -> Result<(), E> {
1570 let Range { start, end } = polyfill::slice::range(range, ..self.len());
1571
1572 self.assert_char_boundary(start);
1573 self.assert_char_boundary(end);
1574
1575 let range_len = end - start;
1576 let given_len = replace_with.len();
1577
1578 let additional_len = given_len.saturating_sub(range_len);
1579 self.generic_reserve(additional_len)?;
1580
1581 // move the tail
1582 if range_len != given_len {
1583 unsafe {
1584 let src = self.as_ptr().add(end);
1585 let dst = self.as_mut_ptr().add(start + given_len);
1586 let len = self.len() - end;
1587 src.copy_to(dst, len);
1588 }
1589 }
1590
1591 // fill with given string
1592 unsafe {
1593 let src = replace_with.as_ptr();
1594 let dst = self.as_mut_ptr().add(start);
1595 let len = replace_with.len();
1596 src.copy_to_nonoverlapping(dst, len);
1597 }
1598
1599 // update len
1600 #[expect(clippy::cast_sign_loss, clippy::cast_possible_wrap)]
1601 unsafe {
1602 // Casting to `isize` is fine because per `Layout`'s rules all the `*len`s must be
1603 // less than isize::MAX. Subtracting two positive `isize`s can't overflow.
1604 let len_diff = given_len as isize - range_len as isize;
1605 self.set_len((self.len() as isize + len_diff) as usize);
1606 }
1607
1608 Ok(())
1609 }
1610
1611 /// Reserves capacity for at least `additional` bytes more than the
1612 /// current length. The allocator may reserve more space to speculatively
1613 /// avoid frequent allocations. After calling `reserve`,
1614 /// capacity will be greater than or equal to `self.len() + additional`.
1615 /// Does nothing if capacity is already sufficient.
1616 ///
1617 /// # Panics
1618 /// Panics if the allocation fails.
1619 ///
1620 /// # Examples
1621 /// Basic usage:
1622 ///
1623 /// ```
1624 /// # use bump_scope::{Bump, BumpString};
1625 /// # let bump: Bump = Bump::new();
1626 /// let mut s = BumpString::new_in(&bump);
1627 ///
1628 /// s.reserve(10);
1629 ///
1630 /// assert!(s.capacity() >= 10);
1631 /// ```
1632 ///
1633 /// This might not actually increase the capacity:
1634 ///
1635 /// ```
1636 /// # use bump_scope::{Bump, BumpString};
1637 /// # let bump: Bump = Bump::new();
1638 /// let mut s = BumpString::with_capacity_in(10, &bump);
1639 /// s.push('a');
1640 /// s.push('b');
1641 ///
1642 /// // s now has a length of 2 and a capacity of at least 10
1643 /// let capacity = s.capacity();
1644 /// assert_eq!(2, s.len());
1645 /// assert!(capacity >= 10);
1646 ///
1647 /// // Since we already have at least an extra 8 capacity, calling this...
1648 /// s.reserve(8);
1649 ///
1650 /// // ... doesn't actually increase.
1651 /// assert_eq!(capacity, s.capacity());
1652 /// ```
1653 #[inline(always)]
1654 #[cfg(feature = "panic-on-alloc")]
1655 pub fn reserve(&mut self, additional: usize) {
1656 panic_on_error(self.generic_reserve(additional));
1657 }
1658
1659 /// Reserves capacity for at least `additional` bytes more than the
1660 /// current length. The allocator may reserve more space to speculatively
1661 /// avoid frequent allocations. After calling `reserve`,
1662 /// capacity will be greater than or equal to `self.len() + additional`.
1663 /// Does nothing if capacity is already sufficient.
1664 ///
1665 /// # Errors
1666 /// Errors if the allocation fails.
1667 ///
1668 /// # Examples
1669 /// Basic usage:
1670 ///
1671 /// ```
1672 /// # use bump_scope::{Bump, BumpString};
1673 /// # let bump: Bump = Bump::new();
1674 /// let mut s = BumpString::new_in(&bump);
1675 ///
1676 /// s.try_reserve(10)?;
1677 ///
1678 /// assert!(s.capacity() >= 10);
1679 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1680 /// ```
1681 ///
1682 /// This might not actually increase the capacity:
1683 ///
1684 /// ```
1685 /// # use bump_scope::{Bump, BumpString};
1686 /// # let bump: Bump = Bump::new();
1687 /// let mut s = BumpString::try_with_capacity_in(10, &bump)?;
1688 /// s.push('a');
1689 /// s.push('b');
1690 ///
1691 /// // s now has a length of 2 and a capacity of at least 10
1692 /// let capacity = s.capacity();
1693 /// assert_eq!(2, s.len());
1694 /// assert!(capacity >= 10);
1695 ///
1696 /// // Since we already have at least an extra 8 capacity, calling this...
1697 /// s.try_reserve(8)?;
1698 ///
1699 /// // ... doesn't actually increase.
1700 /// assert_eq!(capacity, s.capacity());
1701 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1702 /// ```
1703 #[inline(always)]
1704 pub fn try_reserve(&mut self, additional: usize) -> Result<(), AllocError> {
1705 self.generic_reserve(additional)
1706 }
1707
1708 #[inline]
1709 pub(crate) fn generic_reserve<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1710 let vec = unsafe { self.as_mut_vec() };
1711 vec.generic_reserve(additional)
1712 }
1713
1714 /// Reserves the minimum capacity for at least `additional` bytes more than
1715 /// the current length. Unlike [`reserve`], this will not
1716 /// deliberately over-allocate to speculatively avoid frequent allocations.
1717 /// After calling `reserve_exact`, capacity will be greater than or equal to
1718 /// `self.len() + additional`. Does nothing if the capacity is already
1719 /// sufficient.
1720 ///
1721 /// [`reserve`]: Self::reserve
1722 ///
1723 /// # Panics
1724 /// Panics if the allocation fails.
1725 ///
1726 /// # Examples
1727 /// Basic usage:
1728 ///
1729 /// ```
1730 /// # use bump_scope::{Bump, BumpString};
1731 /// # let bump: Bump = Bump::new();
1732 /// let mut s = BumpString::new_in(&bump);
1733 ///
1734 /// s.reserve_exact(10);
1735 ///
1736 /// assert!(s.capacity() >= 10);
1737 /// ```
1738 ///
1739 /// This might not actually increase the capacity:
1740 ///
1741 /// ```
1742 /// # use bump_scope::{Bump, BumpString};
1743 /// # let bump: Bump = Bump::new();
1744 /// let mut s = BumpString::with_capacity_in(10, &bump);
1745 /// s.push('a');
1746 /// s.push('b');
1747 ///
1748 /// // s now has a length of 2 and a capacity of at least 10
1749 /// let capacity = s.capacity();
1750 /// assert_eq!(2, s.len());
1751 /// assert!(capacity >= 10);
1752 ///
1753 /// // Since we already have at least an extra 8 capacity, calling this...
1754 /// s.reserve_exact(8);
1755 ///
1756 /// // ... doesn't actually increase.
1757 /// assert_eq!(capacity, s.capacity());
1758 /// ```
1759 #[inline(always)]
1760 #[cfg(feature = "panic-on-alloc")]
1761 pub fn reserve_exact(&mut self, additional: usize) {
1762 panic_on_error(self.generic_reserve_exact(additional));
1763 }
1764
1765 /// Reserves the minimum capacity for at least `additional` bytes more than
1766 /// the current length. Unlike [`reserve`], this will not
1767 /// deliberately over-allocate to speculatively avoid frequent allocations.
1768 /// After calling `reserve_exact`, capacity will be greater than or equal to
1769 /// `self.len() + additional`. Does nothing if the capacity is already
1770 /// sufficient.
1771 ///
1772 /// [`reserve`]: Self::reserve
1773 ///
1774 /// # Errors
1775 /// Errors if the allocation fails.
1776 ///
1777 /// # Examples
1778 /// Basic usage:
1779 ///
1780 /// ```
1781 /// # use bump_scope::{Bump, BumpString};
1782 /// # let bump: Bump = Bump::new();
1783 /// let mut s = BumpString::new_in(&bump);
1784 ///
1785 /// s.try_reserve_exact(10)?;
1786 ///
1787 /// assert!(s.capacity() >= 10);
1788 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1789 /// ```
1790 ///
1791 /// This might not actually increase the capacity:
1792 ///
1793 /// ```
1794 /// # use bump_scope::{Bump, BumpString};
1795 /// # let bump: Bump = Bump::new();
1796 /// let mut s = BumpString::try_with_capacity_in(10, &bump)?;
1797 /// s.push('a');
1798 /// s.push('b');
1799 ///
1800 /// // s now has a length of 2 and a capacity of at least 10
1801 /// let capacity = s.capacity();
1802 /// assert_eq!(2, s.len());
1803 /// assert!(capacity >= 10);
1804 ///
1805 /// // Since we already have at least an extra 8 capacity, calling this...
1806 /// s.try_reserve_exact(8)?;
1807 ///
1808 /// // ... doesn't actually increase.
1809 /// assert_eq!(capacity, s.capacity());
1810 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1811 /// ```
1812 #[inline(always)]
1813 pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), AllocError> {
1814 self.generic_reserve_exact(additional)
1815 }
1816
1817 #[inline]
1818 pub(crate) fn generic_reserve_exact<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1819 let vec = unsafe { self.as_mut_vec() };
1820 vec.generic_reserve_exact(additional)
1821 }
1822
1823 unsafe fn insert_bytes<B: ErrorBehavior>(&mut self, idx: usize, bytes: &[u8]) -> Result<(), B> {
1824 unsafe {
1825 let vec = self.as_mut_vec();
1826
1827 let len = vec.len();
1828 let amt = bytes.len();
1829 vec.generic_reserve(amt)?;
1830
1831 ptr::copy(vec.as_ptr().add(idx), vec.as_mut_ptr().add(idx + amt), len - idx);
1832 ptr::copy_nonoverlapping(bytes.as_ptr(), vec.as_mut_ptr().add(idx), amt);
1833 vec.set_len(len + amt);
1834
1835 Ok(())
1836 }
1837 }
1838
1839 /// Shrinks the capacity of the string as much as possible.
1840 ///
1841 /// This will also free space for future bump allocations iff this is the most recent allocation.
1842 ///
1843 /// # Examples
1844 /// ```
1845 /// # use bump_scope::{Bump, BumpString};
1846 /// # let bump: Bump = Bump::new();
1847 /// let mut string = BumpString::with_capacity_in(10, &bump);
1848 /// string.push_str("123");
1849 /// assert!(string.capacity() == 10);
1850 /// assert_eq!(bump.stats().allocated(), 10);
1851 /// string.shrink_to_fit();
1852 /// assert!(string.capacity() == 3);
1853 /// assert_eq!(bump.stats().allocated(), 3);
1854 /// ```
1855 pub fn shrink_to_fit(&mut self) {
1856 let vec = unsafe { self.as_mut_vec() };
1857 vec.shrink_to_fit();
1858 }
1859
1860 /// Returns a reference to the allocator.
1861 #[must_use]
1862 #[inline(always)]
1863 pub fn allocator(&self) -> &A {
1864 &self.allocator
1865 }
1866
1867 /// Returns a type which provides statistics about the memory usage of the bump allocator.
1868 ///
1869 /// This is equivalent to calling `.allocator().stats()`.
1870 /// This merely exists for api parity with `Mut*` collections which can't have a `allocator` method.
1871 #[must_use]
1872 #[inline(always)]
1873 pub fn allocator_stats(&self) -> A::TypedStats<'_> {
1874 self.allocator.typed_stats()
1875 }
1876
1877 pub(crate) fn generic_write_fmt<B: ErrorBehavior>(&mut self, args: fmt::Arguments) -> Result<(), B> {
1878 #[cfg(feature = "panic-on-alloc")]
1879 if B::PANICS_ON_ALLOC {
1880 if fmt::Write::write_fmt(PanicsOnAlloc::from_mut(self), args).is_err() {
1881 // Our `PanicsOnAlloc` wrapped `Write` implementation panics on allocation failure.
1882 // So this can only be an error returned by a `fmt()` implementor.
1883 // Note that `fmt()` implementors *should* not return errors (see `std::fmt::Error`)
1884 return Err(B::format_trait_error());
1885 }
1886
1887 return Ok(());
1888 }
1889
1890 if fmt::Write::write_fmt(self, args).is_err() {
1891 // Either an allocation failed or the `fmt()` implementor returned an error.
1892 // Either way we return an `AllocError`.
1893 // Note that `fmt()` implementors *should* not return errors (see `std::fmt::Error`).
1894 // So it's fine not to have an extra error variant for that.
1895 return Err(B::format_trait_error());
1896 }
1897
1898 Ok(())
1899 }
1900}
1901
1902impl<'a, A: BumpAllocatorTypedScope<'a>> BumpString<A> {
1903 /// Converts this `BumpString` into `&str` that is live for this bump scope.
1904 #[must_use]
1905 #[inline(always)]
1906 pub fn into_str(self) -> &'a mut str {
1907 self.into_boxed_str().into_mut()
1908 }
1909
1910 /// Converts a `BumpString` into a `BumpBox<str>`.
1911 #[must_use]
1912 #[inline(always)]
1913 pub fn into_boxed_str(mut self) -> BumpBox<'a, str> {
1914 self.shrink_to_fit();
1915 self.into_fixed_string().into_boxed_str()
1916 }
1917
1918 /// Turns this `BumpString` into a `FixedBumpString`.
1919 ///
1920 /// This retains the unused capacity unlike <code>[into_](Self::into_str)([boxed_](Self::into_boxed_str))[str](Self::into_str)</code>.
1921 #[must_use]
1922 #[inline(always)]
1923 pub fn into_fixed_string(self) -> FixedBumpString<'a> {
1924 self.into_parts().0
1925 }
1926
1927 /// Converts this `BumpString` into `&CStr` that is live for this bump scope.
1928 ///
1929 /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1930 ///
1931 /// # Panics
1932 /// Panics if the allocation fails.
1933 ///
1934 /// # Examples
1935 /// ```
1936 /// # use bump_scope::{Bump, BumpString};
1937 /// # let bump: Bump = Bump::new();
1938 /// let hello = BumpString::from_str_in("Hello, world!", &bump);
1939 /// assert_eq!(hello.into_cstr(), c"Hello, world!");
1940 ///
1941 /// let abc0def = BumpString::from_str_in("abc\0def", &bump);
1942 /// assert_eq!(abc0def.into_cstr(), c"abc");
1943 /// ```
1944 #[must_use]
1945 #[inline(always)]
1946 #[cfg(feature = "panic-on-alloc")]
1947 pub fn into_cstr(self) -> &'a CStr {
1948 panic_on_error(self.generic_into_cstr())
1949 }
1950
1951 /// Converts this `BumpString` into `&CStr` that is live for this bump scope.
1952 ///
1953 /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1954 ///
1955 /// # Errors
1956 /// Errors if the allocation fails.
1957 ///
1958 /// # Examples
1959 /// ```
1960 /// # use bump_scope::{Bump, BumpString};
1961 /// # let bump: Bump = Bump::new();
1962 /// let hello = BumpString::try_from_str_in("Hello, world!", &bump)?;
1963 /// assert_eq!(hello.try_into_cstr()?, c"Hello, world!");
1964 ///
1965 /// let abc0def = BumpString::try_from_str_in("abc\0def", &bump)?;
1966 /// assert_eq!(abc0def.try_into_cstr()?, c"abc");
1967 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1968 /// ```
1969 #[inline(always)]
1970 pub fn try_into_cstr(self) -> Result<&'a CStr, AllocError> {
1971 self.generic_into_cstr()
1972 }
1973
1974 #[inline]
1975 pub(crate) fn generic_into_cstr<B: ErrorBehavior>(mut self) -> Result<&'a CStr, B> {
1976 match self.as_bytes().iter().position(|&c| c == b'\0') {
1977 Some(nul) => unsafe { self.fixed.cook_mut().as_mut_vec().truncate(nul + 1) },
1978 None => self.generic_push('\0')?,
1979 }
1980
1981 let bytes_with_nul = self.into_boxed_str().into_ref().as_bytes();
1982 Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes_with_nul) })
1983 }
1984
1985 /// Creates a `BumpString` from its parts.
1986 ///
1987 /// The provided `bump` does not have to be the one the `fixed_string` was allocated in.
1988 ///
1989 /// ```
1990 /// # use bump_scope::{Bump, BumpString, FixedBumpString};
1991 /// # let bump: Bump = Bump::new();
1992 /// let mut fixed_string = FixedBumpString::with_capacity_in(3, &bump);
1993 /// fixed_string.push('a');
1994 /// fixed_string.push('b');
1995 /// fixed_string.push('c');
1996 /// let mut string = BumpString::from_parts(fixed_string, &bump);
1997 /// string.push('d');
1998 /// string.push('e');
1999 /// assert_eq!(string, "abcde");
2000 /// ```
2001 #[must_use]
2002 #[inline(always)]
2003 pub fn from_parts(string: FixedBumpString<'a>, allocator: A) -> Self {
2004 Self {
2005 fixed: unsafe { RawFixedBumpString::from_cooked(string) },
2006 allocator,
2007 }
2008 }
2009
2010 /// Turns this `BumpString` into its parts.
2011 ///
2012 /// ```
2013 /// # use bump_scope::{Bump, BumpString};
2014 /// # let bump: Bump = Bump::new();
2015 /// let mut string = BumpString::new_in(&bump);
2016 /// string.reserve(10);
2017 /// string.push('a');
2018 /// let fixed_string = string.into_parts().0;
2019 /// assert_eq!(fixed_string.capacity(), 10);
2020 /// assert_eq!(fixed_string, "a");
2021 /// ```
2022 #[must_use]
2023 #[inline(always)]
2024 pub fn into_parts(self) -> (FixedBumpString<'a>, A) {
2025 destructure!(let Self { fixed, allocator } = self);
2026 (unsafe { fixed.cook() }, allocator)
2027 }
2028}
2029
2030impl<A: BumpAllocatorTyped> fmt::Write for BumpString<A> {
2031 #[inline(always)]
2032 fn write_str(&mut self, s: &str) -> fmt::Result {
2033 self.try_push_str(s).map_err(|_| fmt::Error)
2034 }
2035
2036 #[inline(always)]
2037 fn write_char(&mut self, c: char) -> fmt::Result {
2038 self.try_push(c).map_err(|_| fmt::Error)
2039 }
2040}
2041
2042#[cfg(feature = "panic-on-alloc")]
2043impl<A: BumpAllocatorTyped> fmt::Write for PanicsOnAlloc<BumpString<A>> {
2044 #[inline(always)]
2045 fn write_str(&mut self, s: &str) -> fmt::Result {
2046 self.0.push_str(s);
2047 Ok(())
2048 }
2049
2050 #[inline(always)]
2051 fn write_char(&mut self, c: char) -> fmt::Result {
2052 self.0.push(c);
2053 Ok(())
2054 }
2055}
2056
2057impl<A: BumpAllocatorTyped> Debug for BumpString<A> {
2058 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2059 Debug::fmt(self.as_str(), f)
2060 }
2061}
2062
2063impl<A: BumpAllocatorTyped> Display for BumpString<A> {
2064 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2065 Display::fmt(self.as_str(), f)
2066 }
2067}
2068
2069impl<A: BumpAllocatorTyped> Deref for BumpString<A> {
2070 type Target = str;
2071
2072 #[inline]
2073 fn deref(&self) -> &Self::Target {
2074 self.as_str()
2075 }
2076}
2077
2078impl<A: BumpAllocatorTyped> DerefMut for BumpString<A> {
2079 #[inline]
2080 fn deref_mut(&mut self) -> &mut Self::Target {
2081 self.as_mut_str()
2082 }
2083}
2084
2085impl<A: BumpAllocatorTyped, I: SliceIndex<str>> Index<I> for BumpString<A> {
2086 type Output = I::Output;
2087
2088 fn index(&self, index: I) -> &Self::Output {
2089 &self.as_str()[index]
2090 }
2091}
2092
2093impl<A: BumpAllocatorTyped, I: SliceIndex<str>> IndexMut<I> for BumpString<A> {
2094 fn index_mut(&mut self, index: I) -> &mut Self::Output {
2095 &mut self.as_mut_str()[index]
2096 }
2097}
2098
2099impl<A: BumpAllocatorTyped> Drop for BumpString<A> {
2100 fn drop(&mut self) {
2101 // SAFETY:
2102 // The dangling pointer cannot be a valid ptr into a chunk; because
2103 // of the minimum chunk alignment of 16 the smallest address the chunk
2104 // may be at is 16. The bump allocator handles deallocate requests
2105 // from pointers outside its bound just fine by ignoring them.
2106 //
2107 // This is documented as an invariant in the `BumpAllocatorCore` docs.
2108 unsafe {
2109 let ptr = self.fixed.as_non_null().cast();
2110 let layout = Layout::from_size_align_unchecked(self.fixed.capacity(), 1);
2111 self.allocator.deallocate(ptr, layout);
2112 }
2113 }
2114}
2115
2116impl<A: BumpAllocatorTyped + Default> Default for BumpString<A> {
2117 fn default() -> Self {
2118 Self::new_in(A::default())
2119 }
2120}
2121
2122#[cfg(feature = "panic-on-alloc")]
2123impl<A: BumpAllocatorTyped + Clone> Clone for BumpString<A> {
2124 fn clone(&self) -> Self {
2125 let len = self.len();
2126 let allocator = self.allocator.clone();
2127 let ptr = allocator.allocate_slice::<u8>(len);
2128
2129 unsafe {
2130 self.as_ptr().copy_to_nonoverlapping(ptr.as_ptr(), len);
2131
2132 let slice = non_null::str_from_utf8(NonNull::slice_from_raw_parts(ptr, len));
2133 let fixed = RawFixedBumpString::from_raw_parts(slice, len);
2134
2135 Self { fixed, allocator }
2136 }
2137 }
2138}
2139
2140#[cfg(feature = "panic-on-alloc")]
2141impl<A: BumpAllocatorTyped> core::ops::AddAssign<&str> for BumpString<A> {
2142 #[inline]
2143 fn add_assign(&mut self, rhs: &str) {
2144 self.push_str(rhs);
2145 }
2146}
2147
2148impl<A: BumpAllocatorTyped> AsRef<str> for BumpString<A> {
2149 #[inline]
2150 fn as_ref(&self) -> &str {
2151 self.as_str()
2152 }
2153}
2154
2155impl<A: BumpAllocatorTyped> AsMut<str> for BumpString<A> {
2156 #[inline]
2157 fn as_mut(&mut self) -> &mut str {
2158 self.as_mut_str()
2159 }
2160}
2161
2162impl<A: BumpAllocatorTyped> Borrow<str> for BumpString<A> {
2163 #[inline]
2164 fn borrow(&self) -> &str {
2165 self.as_str()
2166 }
2167}
2168
2169impl<A: BumpAllocatorTyped> BorrowMut<str> for BumpString<A> {
2170 #[inline]
2171 fn borrow_mut(&mut self) -> &mut str {
2172 self.as_mut_str()
2173 }
2174}
2175
2176impl<A: BumpAllocatorTyped> Eq for BumpString<A> {}
2177
2178impl<A: BumpAllocatorTyped> PartialOrd for BumpString<A> {
2179 #[inline]
2180 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2181 Some(self.cmp(other))
2182 }
2183
2184 #[inline]
2185 fn lt(&self, other: &Self) -> bool {
2186 <str as PartialOrd>::lt(self, other)
2187 }
2188
2189 #[inline]
2190 fn le(&self, other: &Self) -> bool {
2191 <str as PartialOrd>::le(self, other)
2192 }
2193
2194 #[inline]
2195 fn gt(&self, other: &Self) -> bool {
2196 <str as PartialOrd>::gt(self, other)
2197 }
2198
2199 #[inline]
2200 fn ge(&self, other: &Self) -> bool {
2201 <str as PartialOrd>::ge(self, other)
2202 }
2203}
2204
2205impl<A: BumpAllocatorTyped> Ord for BumpString<A> {
2206 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2207 <str as Ord>::cmp(self, other)
2208 }
2209}
2210
2211impl<A: BumpAllocatorTyped> Hash for BumpString<A> {
2212 #[inline]
2213 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
2214 self.as_str().hash(state);
2215 }
2216}
2217
2218#[cfg(feature = "panic-on-alloc")]
2219impl<'s, A: BumpAllocatorTyped> Extend<&'s str> for BumpString<A> {
2220 #[inline]
2221 fn extend<T: IntoIterator<Item = &'s str>>(&mut self, iter: T) {
2222 for str in iter {
2223 self.push_str(str);
2224 }
2225 }
2226}
2227
2228#[cfg(feature = "panic-on-alloc")]
2229impl<A: BumpAllocatorTyped> Extend<char> for BumpString<A> {
2230 fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
2231 let iterator = iter.into_iter();
2232 let (lower_bound, _) = iterator.size_hint();
2233 self.reserve(lower_bound);
2234 iterator.for_each(move |c| self.push(c));
2235 }
2236}
2237
2238#[cfg(feature = "panic-on-alloc")]
2239impl<'s, A: BumpAllocatorTyped> Extend<&'s char> for BumpString<A> {
2240 fn extend<I: IntoIterator<Item = &'s char>>(&mut self, iter: I) {
2241 self.extend(iter.into_iter().copied());
2242 }
2243}
2244
2245#[cfg(feature = "alloc")]
2246impl<A: BumpAllocatorTyped> From<BumpString<A>> for alloc_crate::string::String {
2247 #[inline]
2248 fn from(value: BumpString<A>) -> Self {
2249 value.as_str().into()
2250 }
2251}
2252
2253/// Implements the `+` operator for concatenating two strings.
2254///
2255/// This consumes the `BumpString` on the left-hand side and re-uses its buffer (growing it if
2256/// necessary). This is done to avoid allocating a new `BumpString` and copying the entire contents on
2257/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by
2258/// repeated concatenation.
2259///
2260/// The string on the right-hand side is only borrowed; its contents are copied into the returned
2261/// `BumpString`.
2262///
2263/// # Examples
2264///
2265/// Concatenating two `BumpString`s takes the first by value and borrows the second:
2266///
2267/// ```
2268/// # use bump_scope::{Bump, BumpString};
2269/// # let bump: Bump = Bump::new();
2270/// let a = BumpString::from_str_in("hello", &bump);
2271/// let b = BumpString::from_str_in(" world", &bump);
2272/// let c = a + &b;
2273/// # _ = c;
2274/// // `a` is moved and can no longer be used here.
2275/// ```
2276///
2277/// If you want to keep using the first `BumpString`, you can clone it and append to the clone instead:
2278///
2279/// ```
2280/// # use bump_scope::{Bump, BumpString};
2281/// # let bump: Bump = Bump::new();
2282/// let a = BumpString::from_str_in("hello", &bump);
2283/// let b = BumpString::from_str_in(" world", &bump);
2284/// let c = a.clone() + &b;
2285/// // `a` is still valid here.
2286/// # _ = c;
2287/// ```
2288///
2289/// Concatenating `&str` slices can be done by converting the first to a `BumpString`:
2290///
2291/// ```
2292/// # use bump_scope::{Bump, BumpString};
2293/// # let bump: Bump = Bump::new();
2294/// let a = "hello";
2295/// let b = " world";
2296/// let c = BumpString::from_str_in(a, &bump) + b;
2297/// # _ = c;
2298/// ```
2299#[cfg(feature = "panic-on-alloc")]
2300impl<A: BumpAllocatorTyped> core::ops::Add<&str> for BumpString<A> {
2301 type Output = Self;
2302
2303 #[inline]
2304 fn add(mut self, other: &str) -> Self {
2305 self.push_str(other);
2306 self
2307 }
2308}