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