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