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