bump_scope/
fixed_bump_string.rs

1use core::{
2    borrow::{Borrow, BorrowMut},
3    fmt::{self, Debug, Display},
4    hash::Hash,
5    mem::{self, MaybeUninit},
6    ops::{self, Deref, DerefMut, Range, RangeBounds},
7    ptr::{self, NonNull},
8    str,
9};
10
11use crate::{
12    BumpAllocatorScopeExt, BumpBox, BumpString, ErrorBehavior, FixedBumpVec, FromUtf8Error, NoDrop,
13    alloc::AllocError,
14    owned_str,
15    polyfill::{self, non_null, transmute_mut},
16};
17
18#[cfg(feature = "panic-on-alloc")]
19use crate::panic_on_error;
20
21/// A type like [`BumpString`](crate::BumpString) but with a fixed capacity.
22///
23/// It can be constructed using [`with_capacity_in`] or from a `BumpBox` via [`from_init`] or [`from_uninit`].
24///
25/// ## Using it like `BumpString`
26///
27/// This type is also useful when you want a growing `BumpString` but don't want to carry around a reference to
28/// the `Bump(Scope)`. You can use it this way by first converting it to a `BumpString` using [`BumpString::from_parts`],
29/// making your changes and then turning it back into a `FixedBumpString` with [`BumpString::into_fixed_string`].
30///
31/// Not storing the `Bump(Scope)` allows you to call bump allocator methods that require `&mut`,
32/// like [`scoped`](crate::Bump::scoped).
33///
34/// # Examples
35/// ```
36/// # use bump_scope::{Bump, FixedBumpString};
37/// # let bump: Bump = Bump::new();
38/// let mut string = FixedBumpString::with_capacity_in(9, &bump);
39///
40/// string.push_str("foo");
41/// string.push_str("bar");
42/// string.push_str("baz");
43///
44/// let str = string.into_str();
45///
46/// assert_eq!(str, "foobarbaz");
47/// ```
48///
49/// Growing it via `BumpString`:
50///
51/// ```
52/// # use bump_scope::{Bump, BumpScope, BumpString, FixedBumpString};
53/// struct MyBuilder<'a, 'b> {
54///     bump: &'b mut BumpScope<'a>,
55///     string: FixedBumpString<'a>,
56/// }
57///
58/// impl<'a, 'b> MyBuilder<'a, 'b> {
59///     fn push_str(&mut self, value: &str) {
60///         let fixed_string = core::mem::take(&mut self.string);
61///         let mut string = BumpString::from_parts(fixed_string, &mut *self.bump);
62///         string.push_str(value);
63///         self.string = string.into_fixed_string();
64///     }
65/// }
66///
67/// let mut bump: Bump = Bump::new();
68///
69/// let mut builder = MyBuilder {
70///     bump: bump.as_mut_scope(),
71///     string: FixedBumpString::new(),
72/// };
73///
74/// builder.push_str("hello");
75/// assert_eq!(builder.string, "hello");
76/// ```
77///
78/// [`with_capacity_in`]: Self::with_capacity_in
79/// [`from_uninit`]: Self::from_uninit
80/// [`from_init`]: Self::from_init
81// `FixedBumpString` and `FixedBumpVec<u8>` have the same repr.
82#[repr(C)]
83pub struct FixedBumpString<'a> {
84    initialized: BumpBox<'a, str>,
85    capacity: usize,
86}
87
88unsafe impl Send for FixedBumpString<'_> {}
89unsafe impl Sync for FixedBumpString<'_> {}
90
91impl<'a> FixedBumpString<'a> {
92    #[doc(hidden)]
93    #[deprecated = "use `FixedBumpString::new()` instead"]
94    /// Empty fixed string.
95    pub const EMPTY: Self = Self {
96        initialized: BumpBox::EMPTY_STR,
97        capacity: 0,
98    };
99
100    /// Constructs a new empty `FixedBumpString`.
101    ///
102    /// This will not allocate.
103    ///
104    /// # Examples
105    /// ```
106    /// # use bump_scope::FixedBumpString;
107    /// let string = FixedBumpString::new();
108    /// assert_eq!(string.len(), 0);
109    /// assert_eq!(string.capacity(), 0);
110    /// ```
111    #[inline]
112    #[must_use]
113    pub const fn new() -> Self {
114        Self {
115            initialized: BumpBox::EMPTY_STR,
116            capacity: 0,
117        }
118    }
119
120    /// Constructs a new empty `FixedBumpString` with the specified capacity
121    /// in the provided bump allocator.
122    ///
123    /// The string will be able to hold `capacity` bytes.
124    /// If `capacity` is 0, the string will not allocate.
125    ///
126    /// # Panics
127    /// Panics if the allocation fails.
128    ///
129    /// # Examples
130    /// ```
131    /// # use bump_scope::{Bump, FixedBumpString};
132    /// # let bump: Bump = Bump::new();
133    /// let mut s = FixedBumpString::with_capacity_in(10, &bump);
134    ///
135    /// // The String contains no chars, even though it has capacity for more
136    /// assert_eq!(s.len(), 0);
137    ///
138    /// // The string has capacity for 10 bytes...
139    /// for _ in 0..10 {
140    ///     s.push('a');
141    /// }
142    ///
143    /// // ...but another byte will not fit
144    /// assert!(s.try_push('a').is_err());
145    /// ```
146    #[must_use]
147    #[inline(always)]
148    #[cfg(feature = "panic-on-alloc")]
149    pub fn with_capacity_in(capacity: usize, allocator: impl BumpAllocatorScopeExt<'a>) -> Self {
150        panic_on_error(Self::generic_with_capacity_in(capacity, allocator))
151    }
152
153    /// Constructs a new empty `FixedBumpString` with the specified capacity
154    /// in the provided bump allocator.
155    ///
156    /// The string will be able to hold `capacity` bytes.
157    /// If `capacity` is 0, the string will not allocate.
158    ///
159    /// # Errors
160    /// Errors if the allocation fails.
161    ///
162    /// # Examples
163    /// ```
164    /// # use bump_scope::{Bump, FixedBumpString};
165    /// # let bump: Bump = Bump::new();
166    /// let mut s = FixedBumpString::try_with_capacity_in(10, &bump)?;
167    ///
168    /// // The String contains no chars, even though it has capacity for more
169    /// assert_eq!(s.len(), 0);
170    ///
171    /// // The string has capacity for 10 bytes...
172    /// for _ in 0..10 {
173    ///     s.push('a');
174    /// }
175    ///
176    /// // ...but another byte will not fit
177    /// assert!(s.try_push('a').is_err());
178    /// # Ok::<(), bump_scope::alloc::AllocError>(())
179    /// ```
180    #[inline(always)]
181    pub fn try_with_capacity_in(capacity: usize, allocator: impl BumpAllocatorScopeExt<'a>) -> Result<Self, AllocError> {
182        Self::generic_with_capacity_in(capacity, allocator)
183    }
184
185    #[inline]
186    pub(crate) fn generic_with_capacity_in<E: ErrorBehavior>(
187        capacity: usize,
188        allocator: impl BumpAllocatorScopeExt<'a>,
189    ) -> Result<Self, E> {
190        Ok(BumpString::generic_with_capacity_in(capacity, allocator)?.into_fixed_string())
191    }
192
193    /// Turns a `BumpBox<str>` into a full `FixedBumpString`.
194    #[must_use]
195    pub fn from_init(initialized: BumpBox<'a, str>) -> Self {
196        let capacity = initialized.len();
197        Self { initialized, capacity }
198    }
199
200    /// Turns a `BumpBox<[MaybeUninit<u8>]>` into a `FixedBumpString` with a length of `0`.
201    #[must_use]
202    pub fn from_uninit(uninitialized: BumpBox<'a, [MaybeUninit<u8>]>) -> Self {
203        let uninitialized = uninitialized.into_raw();
204        let capacity = uninitialized.len();
205
206        let ptr = non_null::as_non_null_ptr(uninitialized).cast::<u8>();
207        let initialized = unsafe { BumpBox::from_raw(non_null::str_from_utf8(NonNull::slice_from_raw_parts(ptr, 0))) };
208
209        Self { initialized, capacity }
210    }
211
212    /// Converts a vector of bytes to a `FixedBumpString`.
213    ///
214    /// A string ([`FixedBumpString`]) is made of bytes ([`u8`]), and a vector of bytes
215    /// ([`FixedBumpVec<u8>`]) is made of bytes, so this function converts between the
216    /// two. Not all byte slices are valid `FixedBumpString`s, however: `FixedBumpString`
217    /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that
218    /// the bytes are valid UTF-8, and then does the conversion.
219    ///
220    /// If you are sure that the byte slice is valid UTF-8, and you don't want
221    /// to incur the overhead of the validity check, there is an unsafe version
222    /// of this function, [`from_utf8_unchecked`], which has the same behavior
223    /// but skips the check.
224    ///
225    /// This method will take care to not copy the vector, for efficiency's
226    /// sake.
227    ///
228    /// If you need a [`&str`] instead of a `FixedBumpString`, consider
229    /// [`str::from_utf8`].
230    ///
231    /// The inverse of this method is [`into_bytes`].
232    ///
233    /// # Errors
234    ///
235    /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the
236    /// provided bytes are not UTF-8. The vector you moved in is also included.
237    ///
238    /// # Examples
239    ///
240    /// Basic usage:
241    /// ```
242    /// # use bump_scope::{Bump, FixedBumpVec, FixedBumpString};
243    /// # let bump: Bump = Bump::new();
244    /// // some bytes, in a vector
245    /// let mut sparkle_heart = FixedBumpVec::with_capacity_in(4, &bump);
246    /// sparkle_heart.extend_from_slice_copy(&[240, 159, 146, 150]);
247    ///
248    /// // We know these bytes are valid, so we'll use `unwrap()`.
249    /// let sparkle_heart = FixedBumpString::from_utf8(sparkle_heart).unwrap();
250    ///
251    /// assert_eq!("💖", sparkle_heart);
252    /// ```
253    ///
254    /// Incorrect bytes:
255    /// ```
256    /// # use bump_scope::{Bump, FixedBumpVec, FixedBumpString};
257    /// # let bump: Bump = Bump::new();
258    /// // some invalid bytes, in a vector
259    /// let mut sparkle_heart = FixedBumpVec::with_capacity_in(4, &bump);
260    /// sparkle_heart.extend_from_slice_copy(&[0, 159, 146, 150]);
261    ///
262    /// assert!(FixedBumpString::from_utf8(sparkle_heart).is_err());
263    /// ```
264    ///
265    /// [`from_utf8_unchecked`]: Self::from_utf8_unchecked
266    /// [`FixedBumpVec<u8>`]: FixedBumpVec
267    /// [`&str`]: prim@str "&str"
268    /// [`into_bytes`]: Self::into_bytes
269    pub fn from_utf8(vec: FixedBumpVec<'a, u8>) -> Result<Self, FromUtf8Error<FixedBumpVec<'a, u8>>> {
270        match core::str::from_utf8(vec.as_slice()) {
271            // SAFETY: `FixedBumpVec<u8>` and `FixedBumpString` have the same representation;
272            // only the invariant that the bytes are utf8 is different.
273            Ok(_) => Ok(unsafe { mem::transmute(vec) }),
274            Err(error) => Err(FromUtf8Error::new(error, vec)),
275        }
276    }
277
278    /// Converts a vector of bytes to a `FixedBumpString` without checking that the
279    /// string contains valid UTF-8.
280    ///
281    /// See the safe version, [`from_utf8`](Self::from_utf8), for more details.
282    ///
283    /// # Safety
284    ///
285    /// The bytes passed in must be valid UTF-8.
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// # use bump_scope::{Bump, FixedBumpVec, FixedBumpString};
291    /// # let bump: Bump = Bump::new();
292    ///
293    /// // some bytes, in a vector
294    /// let mut sparkle_heart = FixedBumpVec::with_capacity_in(4, &bump);
295    /// sparkle_heart.extend_from_slice_copy(&[240, 159, 146, 150]);
296    ///
297    /// let sparkle_heart = unsafe {
298    ///     FixedBumpString::from_utf8_unchecked(sparkle_heart)
299    /// };
300    ///
301    /// assert_eq!("💖", sparkle_heart);
302    /// ```
303    #[must_use]
304    pub unsafe fn from_utf8_unchecked(vec: FixedBumpVec<'a, u8>) -> Self {
305        debug_assert!(str::from_utf8(vec.as_slice()).is_ok());
306
307        // SAFETY: `FixedBumpVec<u8>` and `FixedBumpString` have the same representation;
308        // only the invariant that the bytes are utf8 is different.
309        unsafe { mem::transmute(vec) }
310    }
311
312    /// Returns this string's capacity, in bytes.
313    #[must_use]
314    #[inline(always)]
315    pub const fn capacity(&self) -> usize {
316        self.capacity
317    }
318
319    /// Returns the length of this string, in bytes, not [`char`]s or
320    /// graphemes. In other words, it might not be what a human considers the
321    /// length of the string.
322    #[must_use]
323    #[inline(always)]
324    pub const fn len(&self) -> usize {
325        self.initialized.len()
326    }
327
328    /// Returns `true` if this string has a length of zero, and `false` otherwise.
329    #[must_use]
330    #[inline(always)]
331    pub const fn is_empty(&self) -> bool {
332        self.initialized.is_empty()
333    }
334
335    /// Converts this `FixedBumpString` into `&str` that is live for this bump scope.
336    #[must_use]
337    #[inline(always)]
338    pub fn into_str(self) -> &'a mut str {
339        self.initialized.into_mut()
340    }
341
342    /// Converts a `FixedBumpString` into a `BumpBox<str>`.
343    #[must_use]
344    #[inline(always)]
345    pub fn into_boxed_str(self) -> BumpBox<'a, str> {
346        self.initialized
347    }
348
349    /// Turns this `FixedBumpString` into a `BumpString`.
350    #[must_use]
351    #[inline(always)]
352    pub fn into_string<A: BumpAllocatorScopeExt<'a>>(self, allocator: A) -> BumpString<A> {
353        BumpString::from_parts(self, allocator)
354    }
355
356    /// Converts a `FixedBumpString` into a `FixedBumpVec<u8>`.
357    ///
358    /// This consumes the `FixedBumpString`, so we do not need to copy its contents.
359    ///
360    /// # Examples
361    ///
362    /// ```
363    /// # use bump_scope::{Bump, FixedBumpString};
364    /// # let bump: Bump = Bump::new();
365    /// let mut s = FixedBumpString::with_capacity_in(5, &bump);
366    /// s.push_str("hello");
367    /// let bytes = s.into_bytes();
368    ///
369    /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
370    /// ```
371    #[inline(always)]
372    #[must_use = "`self` will be dropped if the result is not used"]
373    pub fn into_bytes(self) -> FixedBumpVec<'a, u8> {
374        // SAFETY: `FixedBumpVec<u8>` and `FixedBumpString` have the same representation;
375        // only the invariant that the bytes are utf8 is different.
376        unsafe { mem::transmute(self) }
377    }
378
379    #[track_caller]
380    #[inline(always)]
381    pub(crate) fn assert_char_boundary(&self, index: usize) {
382        self.initialized.assert_char_boundary(index);
383    }
384
385    /// Splits the string into two by removing the specified range.
386    ///
387    /// This method does not allocate and does not change the order of the elements.
388    ///
389    /// The excess capacity may end up in either string.
390    /// 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
391    /// so the original string keeps its capacity.
392    /// If you rather want that behavior then you can write this instead:
393    /// ```
394    /// # use bump_scope::{Bump, FixedBumpString};
395    /// # let bump: Bump = Bump::new();
396    /// # let mut string = FixedBumpString::with_capacity_in(5, &bump);
397    /// # string.push_str("abcde");
398    /// # let start = 1;
399    /// # let end = 4;
400    /// let mut other = FixedBumpString::with_capacity_in(end - start, &bump);
401    /// other.push_str(&string[start..end]);
402    /// string.drain(start..end);
403    /// # assert_eq!(string, "ae");
404    /// # assert_eq!(other, "bcd");
405    /// ```
406    ///
407    /// # Panics
408    ///
409    /// Panics if the starting point or end point do not lie on a [`char`] boundary, or if they're out of bounds.
410    ///
411    /// # Complexity
412    ///
413    /// This operation takes `O(1)` time if either the range starts at 0, ends at `len`, or is empty.
414    /// Otherwise it takes `O(min(end, len - start))` time.
415    ///
416    /// # Examples
417    ///
418    /// ```
419    /// # use bump_scope::{Bump, FixedBumpString};
420    /// # let bump: Bump = Bump::new();
421    /// let mut string = FixedBumpString::with_capacity_in(20, &bump);
422    /// string.push_str("foobarbazqux");
423    ///
424    /// let foo = string.split_off(..3);
425    /// assert_eq!(foo, "foo");
426    /// assert_eq!(string, "barbazqux");
427    ///
428    /// let qux = string.split_off(6..);
429    /// assert_eq!(qux, "qux");
430    /// assert_eq!(string, "barbaz");
431    ///
432    /// let rb = string.split_off(2..4);
433    /// assert_eq!(rb, "rb");
434    /// assert_eq!(string, "baaz");
435    ///
436    /// let rest = string.split_off(..);
437    /// assert_eq!(rest, "baaz");
438    /// assert_eq!(string, "");
439    /// ```
440    #[inline]
441    #[allow(clippy::return_self_not_must_use)]
442    pub fn split_off(&mut self, range: impl RangeBounds<usize>) -> Self {
443        let len = self.len();
444        let ops::Range { start, end } = polyfill::slice::range(range, ..len);
445        let ptr = non_null::as_non_null_ptr(non_null::str_bytes(self.initialized.ptr()));
446
447        unsafe {
448            if end == len {
449                self.assert_char_boundary(start);
450
451                let lhs = ptr;
452                let rhs = ptr.add(start);
453
454                let lhs_len = start;
455                let rhs_len = len - start;
456
457                let lhs_cap = start;
458                let rhs_cap = self.capacity - lhs_cap;
459
460                self.set_ptr(lhs);
461                self.set_len(lhs_len);
462                self.set_cap(lhs_cap);
463
464                return FixedBumpString {
465                    initialized: BumpBox::from_raw(non_null::str_from_utf8(NonNull::slice_from_raw_parts(rhs, rhs_len))),
466                    capacity: rhs_cap,
467                };
468            }
469
470            if start == 0 {
471                self.assert_char_boundary(end);
472
473                let lhs = ptr;
474                let rhs = ptr.add(end);
475
476                let lhs_len = end;
477                let rhs_len = len - end;
478
479                let lhs_cap = end;
480                let rhs_cap = self.capacity - lhs_cap;
481
482                self.set_ptr(rhs);
483                self.set_len(rhs_len);
484                self.set_cap(rhs_cap);
485
486                return FixedBumpString {
487                    initialized: BumpBox::from_raw(non_null::str_from_utf8(NonNull::slice_from_raw_parts(lhs, lhs_len))),
488                    capacity: lhs_cap,
489                };
490            }
491
492            if start == end {
493                return FixedBumpString::new();
494            }
495
496            self.assert_char_boundary(start);
497            self.assert_char_boundary(end);
498
499            let head_len = start;
500            let tail_len = len - end;
501
502            let range_len = end - start;
503            let remaining_len = len - range_len;
504
505            if head_len < tail_len {
506                // move the range of elements to split off to the start
507                self.as_mut_vec().get_unchecked_mut(..end).rotate_right(range_len);
508
509                let lhs = ptr;
510                let rhs = ptr.add(range_len);
511
512                let lhs_len = range_len;
513                let rhs_len = remaining_len;
514
515                let lhs_cap = range_len;
516                let rhs_cap = self.capacity - lhs_cap;
517
518                self.set_ptr(rhs);
519                self.set_len(rhs_len);
520                self.set_cap(rhs_cap);
521
522                FixedBumpString {
523                    initialized: BumpBox::from_raw(non_null::str_from_utf8(NonNull::slice_from_raw_parts(lhs, lhs_len))),
524                    capacity: lhs_cap,
525                }
526            } else {
527                // move the range of elements to split off to the end
528                self.as_mut_vec().get_unchecked_mut(start..).rotate_left(range_len);
529
530                let lhs = ptr;
531                let rhs = ptr.add(remaining_len);
532
533                let lhs_len = remaining_len;
534                let rhs_len = range_len;
535
536                let lhs_cap = remaining_len;
537                let rhs_cap = self.capacity - lhs_cap;
538
539                self.set_ptr(lhs);
540                self.set_len(lhs_len);
541                self.set_cap(lhs_cap);
542
543                FixedBumpString {
544                    initialized: BumpBox::from_raw(non_null::str_from_utf8(NonNull::slice_from_raw_parts(rhs, rhs_len))),
545                    capacity: rhs_cap,
546                }
547            }
548        }
549    }
550
551    /// Removes the last character from the string buffer and returns it.
552    ///
553    /// Returns [`None`] if this string is empty.
554    ///
555    /// # Examples
556    ///
557    /// ```
558    /// # use bump_scope::{Bump, FixedBumpString};
559    /// # let bump: Bump = Bump::new();
560    /// let mut s = FixedBumpString::with_capacity_in(4, &bump);
561    /// s.push_str("abč");
562    ///
563    /// assert_eq!(s.pop(), Some('č'));
564    /// assert_eq!(s.pop(), Some('b'));
565    /// assert_eq!(s.pop(), Some('a'));
566    ///
567    /// assert_eq!(s.pop(), None);
568    /// ```
569    #[inline]
570    pub fn pop(&mut self) -> Option<char> {
571        self.initialized.pop()
572    }
573
574    /// Truncates this string, removing all contents.
575    ///
576    /// While this means the string will have a length of zero, it does not
577    /// touch its capacity.
578    ///
579    /// # Examples
580    ///
581    /// ```
582    /// # use bump_scope::{Bump, FixedBumpString};
583    /// # let bump: Bump = Bump::new();
584    /// #
585    /// let mut s = FixedBumpString::with_capacity_in(3, &bump);
586    /// s.push_str("foo");
587    ///
588    /// s.clear();
589    ///
590    /// assert!(s.is_empty());
591    /// assert_eq!(s.len(), 0);
592    /// assert!(s.capacity() == 3);
593    /// ```
594    #[inline]
595    pub fn clear(&mut self) {
596        self.initialized.clear();
597    }
598
599    /// Shortens this string to the specified length.
600    ///
601    /// If `new_len` is greater than or equal to the string's current length, this has no
602    /// effect.
603    ///
604    /// Note that this method has no effect on the allocated capacity
605    /// of the string
606    ///
607    /// # Panics
608    ///
609    /// Panics if `new_len` does not lie on a [`char`] boundary.
610    ///
611    /// # Examples
612    ///
613    /// ```
614    /// # use bump_scope::{Bump, FixedBumpString};
615    /// # let bump: Bump = Bump::new();
616    /// let mut s = FixedBumpString::with_capacity_in(5, &bump);
617    /// s.push_str("hello");
618    ///
619    /// s.truncate(2);
620    ///
621    /// assert_eq!(s, "he");
622    /// ```
623    #[inline]
624    pub fn truncate(&mut self, new_len: usize) {
625        self.initialized.truncate(new_len);
626    }
627
628    /// Removes a [`char`] from this string at a byte position and returns it.
629    ///
630    /// This is an *O*(*n*) operation, as it requires copying every element in the
631    /// buffer.
632    ///
633    /// # Panics
634    ///
635    /// Panics if `idx` is larger than or equal to the string's length,
636    /// or if it does not lie on a [`char`] boundary.
637    ///
638    /// # Examples
639    ///
640    /// ```
641    /// # use bump_scope::{Bump, FixedBumpString};
642    /// # let bump: Bump = Bump::new();
643    /// let mut s = FixedBumpString::with_capacity_in(4, &bump);
644    /// s.push_str("abç");
645    ///
646    /// assert_eq!(s.remove(0), 'a');
647    /// assert_eq!(s.remove(1), 'ç');
648    /// assert_eq!(s.remove(0), 'b');
649    /// ```
650    #[inline]
651    pub fn remove(&mut self, idx: usize) -> char {
652        self.initialized.remove(idx)
653    }
654
655    /// Retains only the characters specified by the predicate.
656    ///
657    /// In other words, remove all characters `c` such that `f(c)` returns `false`.
658    /// This method operates in place, visiting each character exactly once in the
659    /// original order, and preserves the order of the retained characters.
660    ///
661    /// # Examples
662    ///
663    /// ```
664    /// # use bump_scope::{Bump, FixedBumpString};
665    /// # let bump: Bump = Bump::new();
666    /// let mut s = FixedBumpString::with_capacity_in(50, &bump);
667    /// s.push_str("f_o_ob_ar");
668    ///
669    /// s.retain(|c| c != '_');
670    ///
671    /// assert_eq!(s, "foobar");
672    /// ```
673    ///
674    /// Because the elements are visited exactly once in the original order,
675    /// external state may be used to decide which elements to keep.
676    ///
677    /// ```
678    /// # use bump_scope::{Bump, FixedBumpString};
679    /// # let bump: Bump = Bump::new();
680    /// let mut s = FixedBumpString::with_capacity_in(50, &bump);
681    /// s.push_str("abcde");
682    ///
683    /// let keep = [false, true, true, false, true];
684    /// let mut iter = keep.iter();
685    /// s.retain(|_| *iter.next().unwrap());
686    /// assert_eq!(s, "bce");
687    /// ```
688    #[inline]
689    pub fn retain<F>(&mut self, f: F)
690    where
691        F: FnMut(char) -> bool,
692    {
693        self.initialized.retain(f);
694    }
695
696    /// Removes the specified range from the string in bulk, returning all
697    /// removed characters as an iterator.
698    ///
699    /// The returned iterator keeps a mutable borrow on the string to optimize
700    /// its implementation.
701    ///
702    /// # Panics
703    ///
704    /// Panics if the starting point or end point do not lie on a [`char`]
705    /// boundary, or if they're out of bounds.
706    ///
707    /// # Leaking
708    ///
709    /// If the returned iterator goes out of scope without being dropped (due to
710    /// [`core::mem::forget`], for example), the string may still contain a copy
711    /// of any drained characters, or may have lost characters arbitrarily,
712    /// including characters outside the range.
713    ///
714    /// # Examples
715    ///
716    /// Basic usage:
717    ///
718    /// ```
719    /// # use bump_scope::{Bump, FixedBumpString};
720    /// # let bump: Bump = Bump::new();
721    /// let mut s = FixedBumpString::with_capacity_in(50, &bump);
722    /// s.push_str("α is alpha, β is beta");
723    ///
724    /// let beta_offset = s.find('β').unwrap_or(s.len());
725    ///
726    /// // Remove the range up until the β from the string
727    /// let t: String = s.drain(..beta_offset).collect();
728    /// assert_eq!(t, "α is alpha, ");
729    /// assert_eq!(s, "β is beta");
730    ///
731    /// // A full range clears the string, like `clear()` does
732    /// s.drain(..);
733    /// assert_eq!(s, "");
734    /// ```
735    pub fn drain<R>(&mut self, range: R) -> owned_str::Drain<'_>
736    where
737        R: RangeBounds<usize>,
738    {
739        self.initialized.drain(range)
740    }
741
742    /// Extracts a string slice containing the entire `FixedBumpString`.
743    #[must_use]
744    #[inline(always)]
745    pub fn as_str(&self) -> &str {
746        &self.initialized
747    }
748
749    /// Converts a `FixedBumpString` into a mutable string slice.
750    #[must_use]
751    #[inline(always)]
752    pub fn as_mut_str(&mut self) -> &mut str {
753        &mut self.initialized
754    }
755
756    /// Returns a `NonNull` pointer to the string's buffer, or a dangling
757    /// `NonNull` pointer valid for zero sized reads if the string didn't allocate.
758    ///
759    /// The caller must ensure that the string outlives the pointer this
760    /// function returns, or else it will end up dangling.
761    /// Modifying the string may cause its buffer to be reallocated,
762    /// which would also make any pointers to it invalid.
763    ///
764    /// This method guarantees that for the purpose of the aliasing model, this method
765    /// does not materialize a reference to the underlying slice, and thus the returned pointer
766    /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
767    /// and [`as_non_null`].
768    /// Note that calling other methods that materialize references to the slice,
769    /// or references to specific elements you are planning on accessing through this pointer,
770    /// may still invalidate this pointer.
771    /// See the second example below for how this guarantee can be used.
772    ///
773    /// # Examples
774    ///
775    /// ```
776    /// # use bump_scope::{Bump, FixedBumpString};
777    /// # let bump: Bump = Bump::new();
778    /// // Allocate vector big enough for 4 elements.
779    /// let size = 4;
780    /// let mut x = FixedBumpString::with_capacity_in(size, &bump);
781    /// let x_ptr = x.as_non_null();
782    ///
783    /// // Initialize elements via raw pointer writes, then set length.
784    /// unsafe {
785    ///     for i in 0..size {
786    ///         x_ptr.add(i).write(i as u8 + b'a');
787    ///     }
788    ///     x.as_mut_vec().set_len(size);
789    /// }
790    /// assert_eq!(&*x, "abcd");
791    /// ```
792    ///
793    /// Due to the aliasing guarantee, the following code is legal:
794    ///
795    /// ```
796    /// # use bump_scope::{Bump, bump_format};
797    /// # let bump: Bump = Bump::new();
798    /// unsafe {
799    ///     let v = bump_format!(in &bump, "a").into_fixed_string();
800    ///     let ptr1 = v.as_non_null();
801    ///     ptr1.write(b'b');
802    ///     let ptr2 = v.as_non_null();
803    ///     ptr2.write(b'c');
804    ///     // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
805    ///     ptr1.write(b'd');
806    /// }
807    /// ```
808    ///
809    /// [`as_mut_ptr`]: Self::as_mut_ptr
810    /// [`as_ptr`]: Self::as_ptr
811    /// [`as_non_null`]: Self::as_non_null
812    #[must_use]
813    #[inline(always)]
814    pub const fn as_non_null(&self) -> NonNull<u8> {
815        self.initialized.as_non_null()
816    }
817
818    /// Returns a byte slice of this `FixedBumpString`'s contents.
819    #[must_use]
820    #[inline(always)]
821    pub fn as_bytes(&self) -> &[u8] {
822        self.initialized.as_bytes()
823    }
824
825    /// Returns a mutable reference to the contents of this `FixedBumpString`.
826    ///
827    /// # Safety
828    ///
829    /// This function is unsafe because the returned `&mut FixedBumpVec<u8>` allows writing
830    /// bytes which are not valid UTF-8. If this constraint is violated, using
831    /// the original `FixedBumpString` after dropping the `&mut FixedBumpVec<u8>` may violate memory
832    /// safety, as `FixedBumpString`s must be valid UTF-8.
833    #[must_use]
834    #[inline(always)]
835    pub unsafe fn as_mut_vec(&mut self) -> &mut FixedBumpVec<'a, u8> {
836        unsafe {
837            // SAFETY: `FixedBumpVec<u8>` and `FixedBumpString` have the same representation;
838            // only the invariant that the bytes are utf8 is different.
839            transmute_mut(self)
840        }
841    }
842
843    /// Returns a raw pointer to the slice, or a dangling raw pointer
844    /// valid for zero sized reads.
845    #[inline]
846    #[must_use]
847    pub fn as_ptr(&self) -> *const u8 {
848        self.initialized.as_ptr()
849    }
850
851    /// Returns an unsafe mutable pointer to slice, or a dangling
852    /// raw pointer valid for zero sized reads.
853    #[inline]
854    pub fn as_mut_ptr(&mut self) -> *mut u8 {
855        self.initialized.as_mut_ptr()
856    }
857
858    #[inline(always)]
859    pub(crate) unsafe fn set_ptr(&mut self, new_ptr: NonNull<u8>) {
860        unsafe { self.initialized.set_ptr(new_ptr) };
861    }
862
863    #[inline(always)]
864    pub(crate) unsafe fn set_len(&mut self, new_len: usize) {
865        unsafe { self.initialized.set_len(new_len) };
866    }
867
868    #[inline(always)]
869    pub(crate) unsafe fn set_cap(&mut self, new_cap: usize) {
870        self.capacity = new_cap;
871    }
872}
873
874impl FixedBumpString<'_> {
875    /// Appends the given [`char`] to the end of this string.
876    ///
877    /// # Panics
878    /// Panics if the string does not have enough capacity.
879    ///
880    /// # Examples
881    /// ```
882    /// # use bump_scope::{Bump, FixedBumpString};
883    /// # let bump: Bump = Bump::new();
884    /// let mut s = FixedBumpString::with_capacity_in(3, &bump);
885    ///
886    /// s.push('a');
887    /// s.push('b');
888    /// s.push('c');
889    ///
890    /// assert_eq!(s, "abc");
891    /// ```
892    #[inline(always)]
893    #[cfg(feature = "panic-on-alloc")]
894    pub fn push(&mut self, ch: char) {
895        panic_on_error(self.generic_push(ch));
896    }
897
898    /// Appends the given [`char`] to the end of this string.
899    ///
900    /// # Errors
901    /// Errors if the string does not have enough capacity.
902    ///
903    /// # Examples
904    /// ```
905    /// # use bump_scope::{Bump, FixedBumpString};
906    /// # let bump: Bump = Bump::try_new()?;
907    /// let mut s = FixedBumpString::try_with_capacity_in(3, &bump)?;
908    ///
909    /// s.try_push('a')?;
910    /// s.try_push('b')?;
911    /// s.try_push('c')?;
912    ///
913    /// assert_eq!(s, "abc");
914    /// # Ok::<(), bump_scope::alloc::AllocError>(())
915    /// ```
916    #[inline(always)]
917    pub fn try_push(&mut self, ch: char) -> Result<(), AllocError> {
918        self.generic_push(ch)
919    }
920
921    #[inline]
922    pub(crate) fn generic_push<E: ErrorBehavior>(&mut self, ch: char) -> Result<(), E> {
923        let vec = unsafe { self.as_mut_vec() };
924
925        match ch.len_utf8() {
926            1 => vec.generic_push(ch as u8),
927            _ => vec.generic_extend_from_slice_copy(ch.encode_utf8(&mut [0; 4]).as_bytes()),
928        }
929    }
930
931    /// Appends a given string slice onto the end of this string.
932    ///
933    /// # Panics
934    /// Panics if the string does not have enough capacity.
935    ///
936    /// # Examples
937    /// ```
938    /// # use bump_scope::{Bump, FixedBumpString};
939    /// # let bump: Bump = Bump::new();
940    /// let mut s = FixedBumpString::with_capacity_in(6, &bump);
941    ///
942    /// s.push_str("foo");
943    /// s.push_str("bar");
944    ///
945    /// assert_eq!(s, "foobar");
946    /// ```
947    #[inline(always)]
948    #[cfg(feature = "panic-on-alloc")]
949    pub fn push_str(&mut self, string: &str) {
950        panic_on_error(self.generic_push_str(string));
951    }
952
953    /// Appends a given string slice onto the end of this string.
954    ///
955    /// # Errors
956    /// Errors if the string does not have enough capacity.
957    ///
958    /// # Examples
959    /// ```
960    /// # use bump_scope::{Bump, FixedBumpString};
961    /// # let bump: Bump = Bump::try_new()?;
962    /// let mut s = FixedBumpString::try_with_capacity_in(6, &bump)?;
963    ///
964    /// s.try_push_str("foo")?;
965    /// s.try_push_str("bar")?;
966    ///
967    /// assert_eq!(s, "foobar");
968    /// # Ok::<(), bump_scope::alloc::AllocError>(())
969    /// ```
970    #[inline(always)]
971    pub fn try_push_str(&mut self, string: &str) -> Result<(), AllocError> {
972        self.generic_push_str(string)
973    }
974
975    #[inline]
976    pub(crate) fn generic_push_str<E: ErrorBehavior>(&mut self, string: &str) -> Result<(), E> {
977        let vec = unsafe { self.as_mut_vec() };
978        vec.generic_extend_from_slice_copy(string.as_bytes())
979    }
980
981    /// Inserts a character into this string at a byte position.
982    ///
983    /// This is an *O*(*n*) operation as it requires copying every element in the
984    /// buffer.
985    ///
986    /// # Panics
987    /// Panics if the string does not have enough capacity.
988    ///
989    /// Panics if `idx` is larger than the string's length, or if it does not
990    /// lie on a [`char`] boundary.
991    ///
992    /// # Examples
993    /// ```
994    /// # use bump_scope::{Bump, FixedBumpString};
995    /// # let bump: Bump = Bump::new();
996    /// let mut s = FixedBumpString::with_capacity_in(3, &bump);
997    ///
998    /// s.insert(0, 'f');
999    /// s.insert(1, 'o');
1000    /// s.insert(2, 'o');
1001    ///
1002    /// assert_eq!("foo", s);
1003    /// ```
1004    #[inline(always)]
1005    #[cfg(feature = "panic-on-alloc")]
1006    pub fn insert(&mut self, idx: usize, ch: char) {
1007        panic_on_error(self.generic_insert(idx, ch));
1008    }
1009
1010    /// Inserts a character into this string at a byte position.
1011    ///
1012    /// This is an *O*(*n*) operation as it requires copying every element in the
1013    /// buffer.
1014    ///
1015    /// # Panics
1016    /// Panics if `idx` is larger than the string's length, or if it does not
1017    /// lie on a [`char`] boundary.
1018    ///
1019    /// # Errors
1020    /// Errors if the string does not have enough capacity.
1021    ///
1022    /// # Examples
1023    /// ```
1024    /// # use bump_scope::{Bump, FixedBumpString};
1025    /// # let bump: Bump = Bump::try_new()?;
1026    /// let mut s = FixedBumpString::try_with_capacity_in(3, &bump)?;
1027    ///
1028    /// s.try_insert(0, 'f')?;
1029    /// s.try_insert(1, 'o')?;
1030    /// s.try_insert(2, 'o')?;
1031    ///
1032    /// assert_eq!("foo", s);
1033    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1034    /// ```
1035    #[inline(always)]
1036    pub fn try_insert(&mut self, idx: usize, ch: char) -> Result<(), AllocError> {
1037        self.generic_insert(idx, ch)
1038    }
1039
1040    #[inline]
1041    pub(crate) fn generic_insert<E: ErrorBehavior>(&mut self, idx: usize, ch: char) -> Result<(), E> {
1042        assert!(self.is_char_boundary(idx));
1043        let mut bits = [0; 4];
1044        let bits = ch.encode_utf8(&mut bits).as_bytes();
1045
1046        unsafe { self.insert_bytes(idx, bits) }
1047    }
1048
1049    /// Inserts a string slice into this string at a byte position.
1050    ///
1051    /// This is an *O*(*n*) operation as it requires copying every element in the
1052    /// buffer.
1053    ///
1054    /// # Panics
1055    /// Panics if the string does not have enough capacity.
1056    ///
1057    /// Panics if `idx` is larger than the string's length, or if it does not
1058    /// lie on a [`char`] boundary.
1059    ///
1060    /// # Examples
1061    /// ```
1062    /// # use bump_scope::{Bump, FixedBumpString};
1063    /// # let bump: Bump = Bump::new();
1064    /// let mut s = FixedBumpString::with_capacity_in(6, &bump);
1065    /// s.push_str("bar");
1066    ///
1067    /// s.insert_str(0, "foo");
1068    ///
1069    /// assert_eq!("foobar", s);
1070    /// ```
1071    #[inline(always)]
1072    #[cfg(feature = "panic-on-alloc")]
1073    pub fn insert_str(&mut self, idx: usize, string: &str) {
1074        panic_on_error(self.generic_insert_str(idx, string));
1075    }
1076
1077    /// Inserts a string slice into this string at a byte position.
1078    ///
1079    /// This is an *O*(*n*) operation as it requires copying every element in the
1080    /// buffer.
1081    ///
1082    /// # Panics
1083    /// Panics if `idx` is larger than the string's length, or if it does not
1084    /// lie on a [`char`] boundary.
1085    ///
1086    /// # Errors
1087    /// Errors if the string does not have enough capacity.
1088    ///
1089    /// # Examples
1090    /// ```
1091    /// # use bump_scope::{Bump, FixedBumpString};
1092    /// # let bump: Bump = Bump::try_new()?;
1093    /// let mut s = FixedBumpString::try_with_capacity_in(6, &bump)?;
1094    /// s.try_push_str("bar")?;
1095    ///
1096    /// s.try_insert_str(0, "foo")?;
1097    ///
1098    /// assert_eq!("foobar", s);
1099    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1100    /// ```
1101    #[inline(always)]
1102    pub fn try_insert_str(&mut self, idx: usize, string: &str) -> Result<(), AllocError> {
1103        self.generic_insert_str(idx, string)
1104    }
1105
1106    #[inline]
1107    pub(crate) fn generic_insert_str<E: ErrorBehavior>(&mut self, idx: usize, string: &str) -> Result<(), E> {
1108        assert!(self.is_char_boundary(idx));
1109
1110        unsafe { self.insert_bytes(idx, string.as_bytes()) }
1111    }
1112
1113    /// Copies elements from `src` range to the end of the string.
1114    ///
1115    /// # Panics
1116    /// Panics if the string does not have enough capacity.
1117    ///
1118    /// Panics if the starting point or end point do not lie on a [`char`]
1119    /// boundary, or if they're out of bounds.
1120    ///
1121    /// # Examples
1122    /// ```
1123    /// # use bump_scope::{Bump, FixedBumpString};
1124    /// # let bump: Bump = Bump::new();
1125    /// let mut string = FixedBumpString::with_capacity_in(14, &bump);
1126    /// string.push_str("abcde");
1127    ///
1128    /// string.extend_from_within(2..);
1129    /// assert_eq!(string, "abcdecde");
1130    ///
1131    /// string.extend_from_within(..2);
1132    /// assert_eq!(string, "abcdecdeab");
1133    ///
1134    /// string.extend_from_within(4..8);
1135    /// assert_eq!(string, "abcdecdeabecde");
1136    /// ```
1137    #[inline(always)]
1138    #[cfg(feature = "panic-on-alloc")]
1139    pub fn extend_from_within<R>(&mut self, src: R)
1140    where
1141        R: RangeBounds<usize>,
1142    {
1143        panic_on_error(self.generic_extend_from_within(src));
1144    }
1145
1146    /// Copies elements from `src` range to the end of the string.
1147    ///
1148    /// # Panics
1149    /// Panics if the starting point or end point do not lie on a [`char`]
1150    /// boundary, or if they're out of bounds.
1151    ///
1152    /// # Errors
1153    /// Errors if the string does not have enough capacity.
1154    ///
1155    /// # Examples
1156    /// ```
1157    /// # use bump_scope::{Bump, FixedBumpString};
1158    /// # let bump: Bump = Bump::try_new()?;
1159    /// let mut string = FixedBumpString::try_with_capacity_in(14, &bump)?;
1160    /// string.try_push_str("abcde")?;
1161    ///
1162    /// string.try_extend_from_within(2..)?;
1163    /// assert_eq!(string, "abcdecde");
1164    ///
1165    /// string.try_extend_from_within(..2)?;
1166    /// assert_eq!(string, "abcdecdeab");
1167    ///
1168    /// string.try_extend_from_within(4..8)?;
1169    /// assert_eq!(string, "abcdecdeabecde");
1170    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1171    /// ```
1172    #[inline(always)]
1173    pub fn try_extend_from_within<R>(&mut self, src: R) -> Result<(), AllocError>
1174    where
1175        R: RangeBounds<usize>,
1176    {
1177        self.generic_extend_from_within(src)
1178    }
1179
1180    #[inline]
1181    pub(crate) fn generic_extend_from_within<E: ErrorBehavior, R: RangeBounds<usize>>(&mut self, src: R) -> Result<(), E> {
1182        let src @ Range { start, end } = polyfill::slice::range(src, ..self.len());
1183
1184        assert!(self.is_char_boundary(start));
1185        assert!(self.is_char_boundary(end));
1186
1187        let vec = unsafe { self.as_mut_vec() };
1188        vec.generic_extend_from_within_copy(src)
1189    }
1190
1191    /// Extends this string by pushing `additional` new zero bytes.
1192    ///
1193    /// # Panics
1194    /// Panics if the string does not have enough capacity.
1195    ///
1196    /// # Examples
1197    /// ```
1198    /// # use bump_scope::{Bump, FixedBumpString};
1199    /// # let bump: Bump = Bump::new();
1200    /// let mut string = FixedBumpString::with_capacity_in(8, &bump);
1201    /// string.push_str("What?");
1202    /// string.extend_zeroed(3);
1203    /// assert_eq!(string, "What?\0\0\0");
1204    /// ```
1205    #[inline(always)]
1206    #[cfg(feature = "panic-on-alloc")]
1207    pub fn extend_zeroed(&mut self, additional: usize) {
1208        panic_on_error(self.generic_extend_zeroed(additional));
1209    }
1210
1211    /// Extends this string by pushing `additional` new zero bytes.
1212    ///
1213    /// # Errors
1214    /// Errors if the string does not have enough capacity.
1215    ///
1216    /// # Examples
1217    /// ```
1218    /// # use bump_scope::{Bump, FixedBumpString};
1219    /// # let bump: Bump = Bump::try_new()?;
1220    /// let mut string = FixedBumpString::try_with_capacity_in(8, &bump)?;
1221    /// string.try_push_str("What?")?;
1222    /// string.try_extend_zeroed(3)?;
1223    /// assert_eq!(string, "What?\0\0\0");
1224    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1225    /// ```
1226    #[inline(always)]
1227    pub fn try_extend_zeroed(&mut self, additional: usize) -> Result<(), AllocError> {
1228        self.generic_extend_zeroed(additional)
1229    }
1230
1231    #[inline]
1232    pub(crate) fn generic_extend_zeroed<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1233        let vec = unsafe { self.as_mut_vec() };
1234
1235        vec.generic_reserve(additional)?;
1236
1237        unsafe {
1238            let ptr = vec.as_mut_ptr();
1239            let len = vec.len();
1240
1241            ptr.add(len).write_bytes(0, additional);
1242            vec.set_len(len + additional);
1243        }
1244
1245        Ok(())
1246    }
1247
1248    /// Removes the specified range in the string,
1249    /// and replaces it with the given string.
1250    /// The given string doesn't need to be the same length as the range.
1251    ///
1252    /// # Panics
1253    /// Panics if the string does not have enough capacity.
1254    ///
1255    /// Panics if the starting point or end point do not lie on a [`char`]
1256    /// boundary, or if they're out of bounds.
1257    ///
1258    /// # Examples
1259    /// ```
1260    /// # use bump_scope::{Bump, FixedBumpString};
1261    /// # let bump: Bump = Bump::new();
1262    /// let mut s = FixedBumpString::with_capacity_in(50, &bump);
1263    /// s.push_str("α is alpha, β is beta");
1264    /// let beta_offset = s.find('β').unwrap_or(s.len());
1265    ///
1266    /// // Replace the range up until the β from the string
1267    /// s.replace_range(..beta_offset, "Α is capital alpha; ");
1268    /// assert_eq!(s, "Α is capital alpha; β is beta");
1269    /// ```
1270    #[inline(always)]
1271    #[cfg(feature = "panic-on-alloc")]
1272    pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
1273    where
1274        R: RangeBounds<usize>,
1275    {
1276        panic_on_error(self.generic_replace_range(range, replace_with));
1277    }
1278
1279    /// Removes the specified range in the string,
1280    /// and replaces it with the given string.
1281    /// The given string doesn't need to be the same length as the range.
1282    ///
1283    /// # Panics
1284    /// Panics if the starting point or end point do not lie on a [`char`]
1285    /// boundary, or if they're out of bounds.
1286    ///
1287    /// # Errors
1288    /// Errors if the string does not have enough capacity.
1289    ///
1290    /// # Examples
1291    /// ```
1292    /// # use bump_scope::{Bump, FixedBumpString};
1293    /// # let bump: Bump = Bump::try_new()?;
1294    /// let mut s = FixedBumpString::try_with_capacity_in(50, &bump)?;
1295    /// s.push_str("α is alpha, β is beta");
1296    /// let beta_offset = s.find('β').unwrap_or(s.len());
1297    ///
1298    /// // Replace the range up until the β from the string
1299    /// s.try_replace_range(..beta_offset, "Α is capital alpha; ")?;
1300    /// assert_eq!(s, "Α is capital alpha; β is beta");
1301    ///
1302    /// // An error will be returned when the capacity does not suffice
1303    /// let mut s = FixedBumpString::try_with_capacity_in(5, &bump)?;
1304    /// s.push_str("hello");
1305    /// assert!(s.try_replace_range(4..=4, " n").is_err());
1306    /// # Ok::<(), bump_scope::alloc::AllocError>(())
1307    /// ```
1308    #[inline(always)]
1309    pub fn try_replace_range<R>(&mut self, range: R, replace_with: &str) -> Result<(), AllocError>
1310    where
1311        R: RangeBounds<usize>,
1312    {
1313        self.generic_replace_range(range, replace_with)
1314    }
1315
1316    #[inline]
1317    pub(crate) fn generic_replace_range<E: ErrorBehavior, R: RangeBounds<usize>>(
1318        &mut self,
1319        range: R,
1320        replace_with: &str,
1321    ) -> Result<(), E> {
1322        let Range { start, end } = polyfill::slice::range(range, ..self.len());
1323
1324        self.assert_char_boundary(start);
1325        self.assert_char_boundary(end);
1326
1327        let range_len = end - start;
1328        let given_len = replace_with.len();
1329
1330        let additional_len = given_len.saturating_sub(range_len);
1331        self.generic_reserve(additional_len)?;
1332
1333        // move the tail
1334        if range_len != given_len {
1335            unsafe {
1336                let src = self.as_ptr().add(end);
1337                let dst = self.as_mut_ptr().add(start + given_len);
1338                let len = self.len() - end;
1339                src.copy_to(dst, len);
1340            }
1341        }
1342
1343        // fill with given string
1344        unsafe {
1345            let src = replace_with.as_ptr();
1346            let dst = self.as_mut_ptr().add(start);
1347            let len = replace_with.len();
1348            src.copy_to_nonoverlapping(dst, len);
1349        }
1350
1351        // update len
1352        #[allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)]
1353        unsafe {
1354            // Casting to `isize` is fine because per `Layout`'s rules all the `*len`s must be
1355            // less than isize::MAX. Subtracting two positive `isize`s can't overflow.
1356            let len_diff = given_len as isize - range_len as isize;
1357            self.set_len((self.len() as isize + len_diff) as usize);
1358        }
1359
1360        Ok(())
1361    }
1362
1363    /// Checks if at least `additional` more bytes can be inserted
1364    /// in the given `FixedBumpString` due to capacity.
1365    ///
1366    /// # Panics
1367    /// Panics if the string does not have enough capacity.
1368    #[inline(always)]
1369    #[cfg(feature = "panic-on-alloc")]
1370    pub fn reserve(&mut self, additional: usize) {
1371        panic_on_error(self.generic_reserve(additional));
1372    }
1373
1374    /// Checks if at least `additional` more bytes can be inserted
1375    /// in the given `FixedBumpString` due to capacity.
1376    ///
1377    /// # Errors
1378    /// Errors if the string does not have enough capacity.
1379    #[inline(always)]
1380    pub fn try_reserve(&mut self, additional: usize) -> Result<(), AllocError> {
1381        self.generic_reserve(additional)
1382    }
1383
1384    #[inline]
1385    pub(crate) fn generic_reserve<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1386        let vec = unsafe { self.as_mut_vec() };
1387        vec.generic_reserve(additional)
1388    }
1389
1390    unsafe fn insert_bytes<B: ErrorBehavior>(&mut self, idx: usize, bytes: &[u8]) -> Result<(), B> {
1391        unsafe {
1392            let vec = self.as_mut_vec();
1393
1394            let len = vec.len();
1395            let amt = bytes.len();
1396            vec.generic_reserve(amt)?;
1397
1398            ptr::copy(vec.as_ptr().add(idx), vec.as_mut_ptr().add(idx + amt), len - idx);
1399            ptr::copy_nonoverlapping(bytes.as_ptr(), vec.as_mut_ptr().add(idx), amt);
1400            vec.set_len(len + amt);
1401
1402            Ok(())
1403        }
1404    }
1405}
1406
1407impl fmt::Write for FixedBumpString<'_> {
1408    #[inline(always)]
1409    fn write_str(&mut self, s: &str) -> fmt::Result {
1410        self.try_push_str(s).map_err(|_| fmt::Error)
1411    }
1412
1413    #[inline(always)]
1414    fn write_char(&mut self, c: char) -> fmt::Result {
1415        self.try_push(c).map_err(|_| fmt::Error)
1416    }
1417}
1418
1419impl Debug for FixedBumpString<'_> {
1420    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1421        Debug::fmt(self.as_str(), f)
1422    }
1423}
1424
1425impl Display for FixedBumpString<'_> {
1426    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1427        Display::fmt(self.as_str(), f)
1428    }
1429}
1430
1431impl Default for FixedBumpString<'_> {
1432    fn default() -> Self {
1433        Self::new()
1434    }
1435}
1436
1437impl Deref for FixedBumpString<'_> {
1438    type Target = str;
1439
1440    #[inline]
1441    fn deref(&self) -> &Self::Target {
1442        self.as_str()
1443    }
1444}
1445
1446impl DerefMut for FixedBumpString<'_> {
1447    #[inline]
1448    fn deref_mut(&mut self) -> &mut Self::Target {
1449        self.as_mut_str()
1450    }
1451}
1452
1453#[cfg(feature = "panic-on-alloc")]
1454impl core::ops::AddAssign<&str> for FixedBumpString<'_> {
1455    #[inline]
1456    fn add_assign(&mut self, rhs: &str) {
1457        self.push_str(rhs);
1458    }
1459}
1460
1461impl AsRef<str> for FixedBumpString<'_> {
1462    #[inline]
1463    fn as_ref(&self) -> &str {
1464        self.as_str()
1465    }
1466}
1467
1468impl AsMut<str> for FixedBumpString<'_> {
1469    #[inline]
1470    fn as_mut(&mut self) -> &mut str {
1471        self.as_mut_str()
1472    }
1473}
1474
1475impl Borrow<str> for FixedBumpString<'_> {
1476    #[inline]
1477    fn borrow(&self) -> &str {
1478        self.as_str()
1479    }
1480}
1481
1482impl BorrowMut<str> for FixedBumpString<'_> {
1483    #[inline]
1484    fn borrow_mut(&mut self) -> &mut str {
1485        self.as_mut_str()
1486    }
1487}
1488
1489impl PartialEq for FixedBumpString<'_> {
1490    #[inline]
1491    fn eq(&self, other: &Self) -> bool {
1492        <str as PartialEq>::eq(self, other)
1493    }
1494
1495    #[inline]
1496    fn ne(&self, other: &Self) -> bool {
1497        <str as PartialEq>::ne(self, other)
1498    }
1499}
1500
1501macro_rules! impl_partial_eq {
1502    (
1503        $(
1504            $(#[$attr:meta])*
1505            $string_like:ty,
1506        )*
1507    ) => {
1508        $(
1509            $(#[$attr])*
1510            impl<'a> PartialEq<$string_like> for FixedBumpString<'a> {
1511                #[inline]
1512                fn eq(&self, other: &$string_like) -> bool {
1513                    <str as PartialEq>::eq(self, other)
1514                }
1515
1516                #[inline]
1517                fn ne(&self, other: &$string_like) -> bool {
1518                    <str as PartialEq>::ne(self, other)
1519                }
1520            }
1521
1522            $(#[$attr])*
1523            impl<'a> PartialEq<FixedBumpString<'a>> for $string_like {
1524                #[inline]
1525                fn eq(&self, other: &FixedBumpString<'a>) -> bool {
1526                    <str as PartialEq>::eq(self, other)
1527                }
1528
1529                #[inline]
1530                fn ne(&self, other: &FixedBumpString<'a>) -> bool {
1531                    <str as PartialEq>::ne(self, other)
1532                }
1533            }
1534        )*
1535    };
1536}
1537
1538impl_partial_eq! {
1539    str,
1540
1541    &str,
1542
1543    #[cfg(feature = "alloc")]
1544    alloc_crate::string::String,
1545
1546    #[cfg(feature = "alloc")]
1547    alloc_crate::borrow::Cow<'_, str>,
1548}
1549
1550impl Eq for FixedBumpString<'_> {}
1551
1552impl PartialOrd for FixedBumpString<'_> {
1553    #[inline]
1554    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
1555        Some(self.cmp(other))
1556    }
1557
1558    #[inline]
1559    fn lt(&self, other: &Self) -> bool {
1560        <str as PartialOrd>::lt(self, other)
1561    }
1562
1563    #[inline]
1564    fn le(&self, other: &Self) -> bool {
1565        <str as PartialOrd>::le(self, other)
1566    }
1567
1568    #[inline]
1569    fn gt(&self, other: &Self) -> bool {
1570        <str as PartialOrd>::gt(self, other)
1571    }
1572
1573    #[inline]
1574    fn ge(&self, other: &Self) -> bool {
1575        <str as PartialOrd>::ge(self, other)
1576    }
1577}
1578
1579impl Ord for FixedBumpString<'_> {
1580    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1581        <str as Ord>::cmp(self, other)
1582    }
1583}
1584
1585impl Hash for FixedBumpString<'_> {
1586    #[inline]
1587    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1588        self.as_str().hash(state);
1589    }
1590}
1591
1592#[cfg(feature = "panic-on-alloc")]
1593impl<'s> Extend<&'s str> for FixedBumpString<'_> {
1594    #[inline]
1595    fn extend<T: IntoIterator<Item = &'s str>>(&mut self, iter: T) {
1596        for str in iter {
1597            self.push_str(str);
1598        }
1599    }
1600}
1601
1602#[cfg(feature = "panic-on-alloc")]
1603impl Extend<char> for FixedBumpString<'_> {
1604    fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
1605        let iterator = iter.into_iter();
1606        let (lower_bound, _) = iterator.size_hint();
1607        self.reserve(lower_bound);
1608        iterator.for_each(move |c| self.push(c));
1609    }
1610}
1611
1612#[cfg(feature = "panic-on-alloc")]
1613impl<'s> Extend<&'s char> for FixedBumpString<'_> {
1614    fn extend<I: IntoIterator<Item = &'s char>>(&mut self, iter: I) {
1615        self.extend(iter.into_iter().copied());
1616    }
1617}
1618
1619#[cfg(feature = "alloc")]
1620impl<'a> From<FixedBumpString<'a>> for alloc_crate::string::String {
1621    #[inline]
1622    fn from(value: FixedBumpString<'a>) -> Self {
1623        value.as_str().into()
1624    }
1625}
1626
1627impl NoDrop for FixedBumpString<'_> {}