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