Skip to main content

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 &bump; 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 &bump; 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 &bump; 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 &bump; 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}