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 self.assert_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 self.assert_char_boundary(idx);
1373 unsafe { self.insert_bytes(idx, string.as_bytes()) }
1374 }
1375
1376 /// Copies elements from `src` range to the end of the string.
1377 ///
1378 /// # Panics
1379 /// Panics if the allocation fails.
1380 ///
1381 /// Panics if the starting point or end point do not lie on a [`char`]
1382 /// boundary, or if they're out of bounds.
1383 ///
1384 /// # Examples
1385 /// ```
1386 /// # use bump_scope::{Bump, BumpString};
1387 /// # let bump: Bump = Bump::new();
1388 /// let mut string = BumpString::from_str_in("abcde", &bump);
1389 ///
1390 /// string.extend_from_within(2..);
1391 /// assert_eq!(string, "abcdecde");
1392 ///
1393 /// string.extend_from_within(..2);
1394 /// assert_eq!(string, "abcdecdeab");
1395 ///
1396 /// string.extend_from_within(4..8);
1397 /// assert_eq!(string, "abcdecdeabecde");
1398 /// ```
1399 #[inline(always)]
1400 #[cfg(feature = "panic-on-alloc")]
1401 pub fn extend_from_within<R>(&mut self, src: R)
1402 where
1403 R: RangeBounds<usize>,
1404 {
1405 panic_on_error(self.generic_extend_from_within(src));
1406 }
1407
1408 /// Copies elements from `src` range to the end of the string.
1409 ///
1410 /// # Panics
1411 /// Panics if the starting point or end point do not lie on a [`char`]
1412 /// boundary, or if they're out of bounds.
1413 ///
1414 /// # Errors
1415 /// Errors if the allocation fails.
1416 ///
1417 /// # Examples
1418 /// ```
1419 /// # use bump_scope::{Bump, BumpString};
1420 /// # let bump: Bump = Bump::try_new()?;
1421 /// let mut string = BumpString::try_from_str_in("abcde", &bump)?;
1422 ///
1423 /// string.try_extend_from_within(2..)?;
1424 /// assert_eq!(string, "abcdecde");
1425 ///
1426 /// string.try_extend_from_within(..2)?;
1427 /// assert_eq!(string, "abcdecdeab");
1428 ///
1429 /// string.try_extend_from_within(4..8)?;
1430 /// assert_eq!(string, "abcdecdeabecde");
1431 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1432 /// ```
1433 #[inline(always)]
1434 pub fn try_extend_from_within<R>(&mut self, src: R) -> Result<(), AllocError>
1435 where
1436 R: RangeBounds<usize>,
1437 {
1438 self.generic_extend_from_within(src)
1439 }
1440
1441 #[inline]
1442 pub(crate) fn generic_extend_from_within<E: ErrorBehavior, R: RangeBounds<usize>>(&mut self, src: R) -> Result<(), E> {
1443 let src @ Range { start, end } = polyfill::slice::range(src, ..self.len());
1444
1445 self.assert_char_boundary(start);
1446 self.assert_char_boundary(end);
1447
1448 let vec = unsafe { self.as_mut_vec() };
1449 vec.generic_extend_from_within_copy(src)
1450 }
1451
1452 /// Extends this string by pushing `additional` new zero bytes.
1453 ///
1454 /// # Panics
1455 /// Panics if the allocation fails.
1456 ///
1457 /// # Examples
1458 /// ```
1459 /// # use bump_scope::{Bump, BumpString};
1460 /// # let bump: Bump = Bump::new();
1461 /// let mut string = BumpString::from_str_in("What?", &bump);
1462 /// string.extend_zeroed(3);
1463 /// assert_eq!(string, "What?\0\0\0");
1464 /// ```
1465 #[inline(always)]
1466 #[cfg(feature = "panic-on-alloc")]
1467 pub fn extend_zeroed(&mut self, additional: usize) {
1468 panic_on_error(self.generic_extend_zeroed(additional));
1469 }
1470
1471 /// Extends this string by pushing `additional` new zero bytes.
1472 ///
1473 /// # Errors
1474 /// Errors if the allocation fails.
1475 ///
1476 /// # Examples
1477 /// ```
1478 /// # use bump_scope::{Bump, BumpString};
1479 /// # let bump: Bump = Bump::try_new()?;
1480 /// let mut string = BumpString::try_from_str_in("What?", &bump)?;
1481 /// string.try_extend_zeroed(3)?;
1482 /// assert_eq!(string, "What?\0\0\0");
1483 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1484 /// ```
1485 #[inline(always)]
1486 pub fn try_extend_zeroed(&mut self, additional: usize) -> Result<(), AllocError> {
1487 self.generic_extend_zeroed(additional)
1488 }
1489
1490 #[inline]
1491 pub(crate) fn generic_extend_zeroed<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1492 let vec = unsafe { self.as_mut_vec() };
1493
1494 vec.generic_reserve(additional)?;
1495
1496 unsafe {
1497 let ptr = vec.as_mut_ptr();
1498 let len = vec.len();
1499
1500 ptr.add(len).write_bytes(0, additional);
1501 vec.set_len(len + additional);
1502 }
1503
1504 Ok(())
1505 }
1506
1507 /// Removes the specified range in the string,
1508 /// and replaces it with the given string.
1509 /// The given string doesn't need to be the same length as the range.
1510 ///
1511 /// # Panics
1512 /// Panics if the allocation fails.
1513 ///
1514 /// Panics if the starting point or end point do not lie on a [`char`]
1515 /// boundary, or if they're out of bounds.
1516 ///
1517 /// # Examples
1518 /// ```
1519 /// # use bump_scope::{Bump, BumpString};
1520 /// # let bump: Bump = Bump::new();
1521 /// let mut s = BumpString::from_str_in("α is alpha, β is beta", &bump);
1522 /// let beta_offset = s.find('β').unwrap_or(s.len());
1523 ///
1524 /// // Replace the range up until the β from the string
1525 /// s.replace_range(..beta_offset, "Α is capital alpha; ");
1526 /// assert_eq!(s, "Α is capital alpha; β is beta");
1527 /// ```
1528 #[inline(always)]
1529 #[cfg(feature = "panic-on-alloc")]
1530 pub fn replace_range<R>(&mut self, range: R, replace_with: &str)
1531 where
1532 R: RangeBounds<usize>,
1533 {
1534 panic_on_error(self.generic_replace_range(range, replace_with));
1535 }
1536
1537 /// Removes the specified range in the string,
1538 /// and replaces it with the given string.
1539 /// The given string doesn't need to be the same length as the range.
1540 ///
1541 /// # Panics
1542 /// Panics if the starting point or end point do not lie on a [`char`]
1543 /// boundary, or if they're out of bounds.
1544 ///
1545 /// # Errors
1546 /// Errors if the allocation fails.
1547 ///
1548 /// # Examples
1549 /// ```
1550 /// # use bump_scope::{Bump, BumpString};
1551 /// # let bump: Bump = Bump::try_new()?;
1552 /// let mut s = BumpString::try_from_str_in("α is alpha, β is beta", &bump)?;
1553 /// let beta_offset = s.find('β').unwrap_or(s.len());
1554 ///
1555 /// // Replace the range up until the β from the string
1556 /// s.try_replace_range(..beta_offset, "Α is capital alpha; ")?;
1557 /// assert_eq!(s, "Α is capital alpha; β is beta");
1558 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1559 /// ```
1560 #[inline(always)]
1561 pub fn try_replace_range<R>(&mut self, range: R, replace_with: &str) -> Result<(), AllocError>
1562 where
1563 R: RangeBounds<usize>,
1564 {
1565 self.generic_replace_range(range, replace_with)
1566 }
1567
1568 #[inline]
1569 pub(crate) fn generic_replace_range<E: ErrorBehavior, R: RangeBounds<usize>>(
1570 &mut self,
1571 range: R,
1572 replace_with: &str,
1573 ) -> Result<(), E> {
1574 let Range { start, end } = polyfill::slice::range(range, ..self.len());
1575
1576 self.assert_char_boundary(start);
1577 self.assert_char_boundary(end);
1578
1579 let range_len = end - start;
1580 let given_len = replace_with.len();
1581
1582 let additional_len = given_len.saturating_sub(range_len);
1583 self.generic_reserve(additional_len)?;
1584
1585 // move the tail
1586 if range_len != given_len {
1587 unsafe {
1588 let src = self.as_ptr().add(end);
1589 let dst = self.as_mut_ptr().add(start + given_len);
1590 let len = self.len() - end;
1591 src.copy_to(dst, len);
1592 }
1593 }
1594
1595 // fill with given string
1596 unsafe {
1597 let src = replace_with.as_ptr();
1598 let dst = self.as_mut_ptr().add(start);
1599 let len = replace_with.len();
1600 src.copy_to_nonoverlapping(dst, len);
1601 }
1602
1603 // update len
1604 #[expect(clippy::cast_sign_loss, clippy::cast_possible_wrap)]
1605 unsafe {
1606 // Casting to `isize` is fine because per `Layout`'s rules all the `*len`s must be
1607 // less than isize::MAX. Subtracting two positive `isize`s can't overflow.
1608 let len_diff = given_len as isize - range_len as isize;
1609 self.set_len((self.len() as isize + len_diff) as usize);
1610 }
1611
1612 Ok(())
1613 }
1614
1615 /// Reserves capacity for at least `additional` bytes more than the
1616 /// current length. The allocator may reserve more space to speculatively
1617 /// avoid frequent allocations. After calling `reserve`,
1618 /// capacity will be greater than or equal to `self.len() + additional`.
1619 /// Does nothing if capacity is already sufficient.
1620 ///
1621 /// # Panics
1622 /// Panics if the allocation fails.
1623 ///
1624 /// # Examples
1625 /// Basic usage:
1626 ///
1627 /// ```
1628 /// # use bump_scope::{Bump, BumpString};
1629 /// # let bump: Bump = Bump::new();
1630 /// let mut s = BumpString::new_in(&bump);
1631 ///
1632 /// s.reserve(10);
1633 ///
1634 /// assert!(s.capacity() >= 10);
1635 /// ```
1636 ///
1637 /// This might not actually increase the capacity:
1638 ///
1639 /// ```
1640 /// # use bump_scope::{Bump, BumpString};
1641 /// # let bump: Bump = Bump::new();
1642 /// let mut s = BumpString::with_capacity_in(10, &bump);
1643 /// s.push('a');
1644 /// s.push('b');
1645 ///
1646 /// // s now has a length of 2 and a capacity of at least 10
1647 /// let capacity = s.capacity();
1648 /// assert_eq!(2, s.len());
1649 /// assert!(capacity >= 10);
1650 ///
1651 /// // Since we already have at least an extra 8 capacity, calling this...
1652 /// s.reserve(8);
1653 ///
1654 /// // ... doesn't actually increase.
1655 /// assert_eq!(capacity, s.capacity());
1656 /// ```
1657 #[inline(always)]
1658 #[cfg(feature = "panic-on-alloc")]
1659 pub fn reserve(&mut self, additional: usize) {
1660 panic_on_error(self.generic_reserve(additional));
1661 }
1662
1663 /// Reserves capacity for at least `additional` bytes more than the
1664 /// current length. The allocator may reserve more space to speculatively
1665 /// avoid frequent allocations. After calling `reserve`,
1666 /// capacity will be greater than or equal to `self.len() + additional`.
1667 /// Does nothing if capacity is already sufficient.
1668 ///
1669 /// # Errors
1670 /// Errors if the allocation fails.
1671 ///
1672 /// # Examples
1673 /// Basic usage:
1674 ///
1675 /// ```
1676 /// # use bump_scope::{Bump, BumpString};
1677 /// # let bump: Bump = Bump::try_new()?;
1678 /// let mut s = BumpString::new_in(&bump);
1679 ///
1680 /// s.try_reserve(10)?;
1681 ///
1682 /// assert!(s.capacity() >= 10);
1683 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1684 /// ```
1685 ///
1686 /// This might not actually increase the capacity:
1687 ///
1688 /// ```
1689 /// # use bump_scope::{Bump, BumpString};
1690 /// # let bump: Bump = Bump::try_new()?;
1691 /// let mut s = BumpString::try_with_capacity_in(10, &bump)?;
1692 /// s.push('a');
1693 /// s.push('b');
1694 ///
1695 /// // s now has a length of 2 and a capacity of at least 10
1696 /// let capacity = s.capacity();
1697 /// assert_eq!(2, s.len());
1698 /// assert!(capacity >= 10);
1699 ///
1700 /// // Since we already have at least an extra 8 capacity, calling this...
1701 /// s.try_reserve(8)?;
1702 ///
1703 /// // ... doesn't actually increase.
1704 /// assert_eq!(capacity, s.capacity());
1705 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1706 /// ```
1707 #[inline(always)]
1708 pub fn try_reserve(&mut self, additional: usize) -> Result<(), AllocError> {
1709 self.generic_reserve(additional)
1710 }
1711
1712 #[inline]
1713 pub(crate) fn generic_reserve<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1714 let vec = unsafe { self.as_mut_vec() };
1715 vec.generic_reserve(additional)
1716 }
1717
1718 /// Reserves the minimum capacity for at least `additional` bytes more than
1719 /// the current length. Unlike [`reserve`], this will not
1720 /// deliberately over-allocate to speculatively avoid frequent allocations.
1721 /// After calling `reserve_exact`, capacity will be greater than or equal to
1722 /// `self.len() + additional`. Does nothing if the capacity is already
1723 /// sufficient.
1724 ///
1725 /// [`reserve`]: Self::reserve
1726 ///
1727 /// # Panics
1728 /// Panics if the allocation fails.
1729 ///
1730 /// # Examples
1731 /// Basic usage:
1732 ///
1733 /// ```
1734 /// # use bump_scope::{Bump, BumpString};
1735 /// # let bump: Bump = Bump::new();
1736 /// let mut s = BumpString::new_in(&bump);
1737 ///
1738 /// s.reserve_exact(10);
1739 ///
1740 /// assert!(s.capacity() >= 10);
1741 /// ```
1742 ///
1743 /// This might not actually increase the capacity:
1744 ///
1745 /// ```
1746 /// # use bump_scope::{Bump, BumpString};
1747 /// # let bump: Bump = Bump::new();
1748 /// let mut s = BumpString::with_capacity_in(10, &bump);
1749 /// s.push('a');
1750 /// s.push('b');
1751 ///
1752 /// // s now has a length of 2 and a capacity of at least 10
1753 /// let capacity = s.capacity();
1754 /// assert_eq!(2, s.len());
1755 /// assert!(capacity >= 10);
1756 ///
1757 /// // Since we already have at least an extra 8 capacity, calling this...
1758 /// s.reserve_exact(8);
1759 ///
1760 /// // ... doesn't actually increase.
1761 /// assert_eq!(capacity, s.capacity());
1762 /// ```
1763 #[inline(always)]
1764 #[cfg(feature = "panic-on-alloc")]
1765 pub fn reserve_exact(&mut self, additional: usize) {
1766 panic_on_error(self.generic_reserve_exact(additional));
1767 }
1768
1769 /// Reserves the minimum capacity for at least `additional` bytes more than
1770 /// the current length. Unlike [`reserve`], this will not
1771 /// deliberately over-allocate to speculatively avoid frequent allocations.
1772 /// After calling `reserve_exact`, capacity will be greater than or equal to
1773 /// `self.len() + additional`. Does nothing if the capacity is already
1774 /// sufficient.
1775 ///
1776 /// [`reserve`]: Self::reserve
1777 ///
1778 /// # Errors
1779 /// Errors if the allocation fails.
1780 ///
1781 /// # Examples
1782 /// Basic usage:
1783 ///
1784 /// ```
1785 /// # use bump_scope::{Bump, BumpString};
1786 /// # let bump: Bump = Bump::try_new()?;
1787 /// let mut s = BumpString::new_in(&bump);
1788 ///
1789 /// s.try_reserve_exact(10)?;
1790 ///
1791 /// assert!(s.capacity() >= 10);
1792 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1793 /// ```
1794 ///
1795 /// This might not actually increase the capacity:
1796 ///
1797 /// ```
1798 /// # use bump_scope::{Bump, BumpString};
1799 /// # let bump: Bump = Bump::try_new()?;
1800 /// let mut s = BumpString::try_with_capacity_in(10, &bump)?;
1801 /// s.push('a');
1802 /// s.push('b');
1803 ///
1804 /// // s now has a length of 2 and a capacity of at least 10
1805 /// let capacity = s.capacity();
1806 /// assert_eq!(2, s.len());
1807 /// assert!(capacity >= 10);
1808 ///
1809 /// // Since we already have at least an extra 8 capacity, calling this...
1810 /// s.try_reserve_exact(8)?;
1811 ///
1812 /// // ... doesn't actually increase.
1813 /// assert_eq!(capacity, s.capacity());
1814 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1815 /// ```
1816 #[inline(always)]
1817 pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), AllocError> {
1818 self.generic_reserve_exact(additional)
1819 }
1820
1821 #[inline]
1822 pub(crate) fn generic_reserve_exact<E: ErrorBehavior>(&mut self, additional: usize) -> Result<(), E> {
1823 let vec = unsafe { self.as_mut_vec() };
1824 vec.generic_reserve_exact(additional)
1825 }
1826
1827 unsafe fn insert_bytes<B: ErrorBehavior>(&mut self, idx: usize, bytes: &[u8]) -> Result<(), B> {
1828 unsafe {
1829 let vec = self.as_mut_vec();
1830
1831 let len = vec.len();
1832 let amt = bytes.len();
1833 vec.generic_reserve(amt)?;
1834
1835 ptr::copy(vec.as_ptr().add(idx), vec.as_mut_ptr().add(idx + amt), len - idx);
1836 ptr::copy_nonoverlapping(bytes.as_ptr(), vec.as_mut_ptr().add(idx), amt);
1837 vec.set_len(len + amt);
1838
1839 Ok(())
1840 }
1841 }
1842
1843 /// Shrinks the capacity of the string as much as possible.
1844 ///
1845 /// This will also free space for future bump allocations iff this is the most recent allocation.
1846 ///
1847 /// # Examples
1848 /// ```
1849 /// # use bump_scope::{Bump, BumpString};
1850 /// # let bump: Bump = Bump::new();
1851 /// let mut string = BumpString::with_capacity_in(10, &bump);
1852 /// string.push_str("123");
1853 /// assert!(string.capacity() == 10);
1854 /// assert_eq!(bump.stats().allocated(), 10);
1855 /// string.shrink_to_fit();
1856 /// assert!(string.capacity() == 3);
1857 /// assert_eq!(bump.stats().allocated(), 3);
1858 /// ```
1859 pub fn shrink_to_fit(&mut self) {
1860 let vec = unsafe { self.as_mut_vec() };
1861 vec.shrink_to_fit();
1862 }
1863
1864 /// Returns a reference to the allocator.
1865 #[must_use]
1866 #[inline(always)]
1867 pub fn allocator(&self) -> &A {
1868 &self.allocator
1869 }
1870
1871 /// Returns a type which provides statistics about the memory usage of the bump allocator.
1872 ///
1873 /// This is equivalent to calling `.allocator().stats()`.
1874 /// This merely exists for api parity with `Mut*` collections which can't have a `allocator` method.
1875 #[must_use]
1876 #[inline(always)]
1877 pub fn allocator_stats(&self) -> A::Stats<'_> {
1878 self.allocator.stats()
1879 }
1880
1881 pub(crate) fn generic_write_fmt<B: ErrorBehavior>(&mut self, args: fmt::Arguments) -> Result<(), B> {
1882 #[cfg(feature = "panic-on-alloc")]
1883 if B::PANICS_ON_ALLOC {
1884 if fmt::Write::write_fmt(PanicsOnAlloc::from_mut(self), args).is_err() {
1885 // Our `PanicsOnAlloc` wrapped `Write` implementation panics on allocation failure.
1886 // So this can only be an error returned by a `fmt()` implementor.
1887 // Note that `fmt()` implementors *should* not return errors (see `std::fmt::Error`)
1888 return Err(B::format_trait_error());
1889 }
1890
1891 return Ok(());
1892 }
1893
1894 if fmt::Write::write_fmt(self, args).is_err() {
1895 // Either an allocation failed or the `fmt()` implementor returned an error.
1896 // Either way we return an `AllocError`.
1897 // Note that `fmt()` implementors *should* not return errors (see `std::fmt::Error`).
1898 // So it's fine not to have an extra error variant for that.
1899 return Err(B::format_trait_error());
1900 }
1901
1902 Ok(())
1903 }
1904}
1905
1906impl<'a, A: BumpAllocatorScopeExt<'a>> BumpString<A> {
1907 /// Converts this `BumpString` into `&str` that is live for this bump scope.
1908 #[must_use]
1909 #[inline(always)]
1910 pub fn into_str(self) -> &'a mut str {
1911 self.into_boxed_str().into_mut()
1912 }
1913
1914 /// Converts a `BumpString` into a `BumpBox<str>`.
1915 #[must_use]
1916 #[inline(always)]
1917 pub fn into_boxed_str(mut self) -> BumpBox<'a, str> {
1918 self.shrink_to_fit();
1919 self.into_fixed_string().into_boxed_str()
1920 }
1921
1922 /// Turns this `BumpString` into a `FixedBumpString`.
1923 ///
1924 /// This retains the unused capacity unlike <code>[into_](Self::into_str)([boxed_](Self::into_boxed_str))[str](Self::into_str)</code>.
1925 #[must_use]
1926 #[inline(always)]
1927 pub fn into_fixed_string(self) -> FixedBumpString<'a> {
1928 self.into_parts().0
1929 }
1930
1931 /// Converts this `BumpString` into `&CStr` that is live for this bump scope.
1932 ///
1933 /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1934 ///
1935 /// # Panics
1936 /// Panics if the allocation fails.
1937 ///
1938 /// # Examples
1939 /// ```
1940 /// # use bump_scope::{Bump, BumpString};
1941 /// # let bump: Bump = Bump::new();
1942 /// let hello = BumpString::from_str_in("Hello, world!", &bump);
1943 /// assert_eq!(hello.into_cstr(), c"Hello, world!");
1944 ///
1945 /// let abc0def = BumpString::from_str_in("abc\0def", &bump);
1946 /// assert_eq!(abc0def.into_cstr(), c"abc");
1947 /// ```
1948 #[must_use]
1949 #[inline(always)]
1950 #[cfg(feature = "panic-on-alloc")]
1951 pub fn into_cstr(self) -> &'a CStr {
1952 panic_on_error(self.generic_into_cstr())
1953 }
1954
1955 /// Converts this `BumpString` into `&CStr` that is live for this bump scope.
1956 ///
1957 /// If the string contains a `'\0'` then the `CStr` will stop at the first `'\0'`.
1958 ///
1959 /// # Errors
1960 /// Errors if the allocation fails.
1961 ///
1962 /// # Examples
1963 /// ```
1964 /// # use bump_scope::{Bump, BumpString};
1965 /// # let bump: Bump = Bump::try_new()?;
1966 /// let hello = BumpString::try_from_str_in("Hello, world!", &bump)?;
1967 /// assert_eq!(hello.try_into_cstr()?, c"Hello, world!");
1968 ///
1969 /// let abc0def = BumpString::try_from_str_in("abc\0def", &bump)?;
1970 /// assert_eq!(abc0def.try_into_cstr()?, c"abc");
1971 /// # Ok::<(), bump_scope::alloc::AllocError>(())
1972 /// ```
1973 #[inline(always)]
1974 pub fn try_into_cstr(self) -> Result<&'a CStr, AllocError> {
1975 self.generic_into_cstr()
1976 }
1977
1978 #[inline]
1979 pub(crate) fn generic_into_cstr<B: ErrorBehavior>(mut self) -> Result<&'a CStr, B> {
1980 match self.as_bytes().iter().position(|&c| c == b'\0') {
1981 Some(nul) => unsafe { self.fixed.cook_mut().as_mut_vec().truncate(nul + 1) },
1982 None => self.generic_push('\0')?,
1983 }
1984
1985 let bytes_with_nul = self.into_boxed_str().into_ref().as_bytes();
1986 Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes_with_nul) })
1987 }
1988
1989 /// Creates a `BumpString` from its parts.
1990 ///
1991 /// The provided `bump` does not have to be the one the `fixed_string` was allocated in.
1992 ///
1993 /// ```
1994 /// # use bump_scope::{Bump, BumpString, FixedBumpString};
1995 /// # let bump: Bump = Bump::new();
1996 /// let mut fixed_string = FixedBumpString::with_capacity_in(3, &bump);
1997 /// fixed_string.push('a');
1998 /// fixed_string.push('b');
1999 /// fixed_string.push('c');
2000 /// let mut string = BumpString::from_parts(fixed_string, &bump);
2001 /// string.push('d');
2002 /// string.push('e');
2003 /// assert_eq!(string, "abcde");
2004 /// ```
2005 #[must_use]
2006 #[inline(always)]
2007 pub fn from_parts(string: FixedBumpString<'a>, allocator: A) -> Self {
2008 Self {
2009 fixed: unsafe { RawFixedBumpString::from_cooked(string) },
2010 allocator,
2011 }
2012 }
2013
2014 /// Turns this `BumpString` into its parts.
2015 ///
2016 /// ```
2017 /// # use bump_scope::{Bump, BumpString};
2018 /// # let bump: Bump = Bump::new();
2019 /// let mut string = BumpString::new_in(&bump);
2020 /// string.reserve(10);
2021 /// string.push('a');
2022 /// let fixed_string = string.into_parts().0;
2023 /// assert_eq!(fixed_string.capacity(), 10);
2024 /// assert_eq!(fixed_string, "a");
2025 /// ```
2026 #[must_use]
2027 #[inline(always)]
2028 pub fn into_parts(self) -> (FixedBumpString<'a>, A) {
2029 destructure!(let Self { fixed, allocator } = self);
2030 (unsafe { fixed.cook() }, allocator)
2031 }
2032}
2033
2034impl<A: BumpAllocatorExt> fmt::Write for BumpString<A> {
2035 #[inline(always)]
2036 fn write_str(&mut self, s: &str) -> fmt::Result {
2037 self.try_push_str(s).map_err(|_| fmt::Error)
2038 }
2039
2040 #[inline(always)]
2041 fn write_char(&mut self, c: char) -> fmt::Result {
2042 self.try_push(c).map_err(|_| fmt::Error)
2043 }
2044}
2045
2046#[cfg(feature = "panic-on-alloc")]
2047impl<A: BumpAllocatorExt> fmt::Write for PanicsOnAlloc<BumpString<A>> {
2048 #[inline(always)]
2049 fn write_str(&mut self, s: &str) -> fmt::Result {
2050 self.0.push_str(s);
2051 Ok(())
2052 }
2053
2054 #[inline(always)]
2055 fn write_char(&mut self, c: char) -> fmt::Result {
2056 self.0.push(c);
2057 Ok(())
2058 }
2059}
2060
2061impl<A: BumpAllocatorExt> Debug for BumpString<A> {
2062 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2063 Debug::fmt(self.as_str(), f)
2064 }
2065}
2066
2067impl<A: BumpAllocatorExt> Display for BumpString<A> {
2068 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
2069 Display::fmt(self.as_str(), f)
2070 }
2071}
2072
2073impl<A: BumpAllocatorExt> Deref for BumpString<A> {
2074 type Target = str;
2075
2076 #[inline]
2077 fn deref(&self) -> &Self::Target {
2078 self.as_str()
2079 }
2080}
2081
2082impl<A: BumpAllocatorExt> DerefMut for BumpString<A> {
2083 #[inline]
2084 fn deref_mut(&mut self) -> &mut Self::Target {
2085 self.as_mut_str()
2086 }
2087}
2088
2089impl<A: BumpAllocatorExt, I: SliceIndex<str>> Index<I> for BumpString<A> {
2090 type Output = I::Output;
2091
2092 fn index(&self, index: I) -> &Self::Output {
2093 &self.as_str()[index]
2094 }
2095}
2096
2097impl<A: BumpAllocatorExt, I: SliceIndex<str>> IndexMut<I> for BumpString<A> {
2098 fn index_mut(&mut self, index: I) -> &mut Self::Output {
2099 &mut self.as_mut_str()[index]
2100 }
2101}
2102
2103impl<A: BumpAllocatorExt> Drop for BumpString<A> {
2104 fn drop(&mut self) {
2105 // SAFETY:
2106 // The dangling pointer cannot be a valid ptr into a chunk; because
2107 // of the minimum chunk alignment of 16 the smallest address the chunk
2108 // may be at is 16. The bump allocator handles deallocate requests
2109 // from pointers outside its bound just fine by ignoring them.
2110 unsafe {
2111 let ptr = self.fixed.as_non_null().cast();
2112 let layout = Layout::from_size_align_unchecked(self.fixed.capacity(), 1);
2113 self.allocator.deallocate(ptr, layout);
2114 }
2115 }
2116}
2117
2118impl<A: BumpAllocatorExt + Default> Default for BumpString<A> {
2119 fn default() -> Self {
2120 Self::new_in(A::default())
2121 }
2122}
2123
2124#[cfg(feature = "panic-on-alloc")]
2125impl<A: BumpAllocatorExt + Clone> Clone for BumpString<A> {
2126 fn clone(&self) -> Self {
2127 let len = self.len();
2128 let allocator = self.allocator.clone();
2129 let ptr = allocator.allocate_slice::<u8>(len);
2130
2131 unsafe {
2132 self.as_ptr().copy_to_nonoverlapping(ptr.as_ptr(), len);
2133
2134 let slice = non_null::str_from_utf8(NonNull::slice_from_raw_parts(ptr, len));
2135 let fixed = RawFixedBumpString::from_raw_parts(slice, len);
2136
2137 Self { fixed, allocator }
2138 }
2139 }
2140}
2141
2142#[cfg(feature = "panic-on-alloc")]
2143impl<A: BumpAllocatorExt> core::ops::AddAssign<&str> for BumpString<A> {
2144 #[inline]
2145 fn add_assign(&mut self, rhs: &str) {
2146 self.push_str(rhs);
2147 }
2148}
2149
2150impl<A: BumpAllocatorExt> AsRef<str> for BumpString<A> {
2151 #[inline]
2152 fn as_ref(&self) -> &str {
2153 self.as_str()
2154 }
2155}
2156
2157impl<A: BumpAllocatorExt> AsMut<str> for BumpString<A> {
2158 #[inline]
2159 fn as_mut(&mut self) -> &mut str {
2160 self.as_mut_str()
2161 }
2162}
2163
2164impl<A: BumpAllocatorExt> Borrow<str> for BumpString<A> {
2165 #[inline]
2166 fn borrow(&self) -> &str {
2167 self.as_str()
2168 }
2169}
2170
2171impl<A: BumpAllocatorExt> BorrowMut<str> for BumpString<A> {
2172 #[inline]
2173 fn borrow_mut(&mut self) -> &mut str {
2174 self.as_mut_str()
2175 }
2176}
2177
2178impl<A: BumpAllocatorExt> Eq for BumpString<A> {}
2179
2180impl<A: BumpAllocatorExt> PartialOrd for BumpString<A> {
2181 #[inline]
2182 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
2183 Some(self.cmp(other))
2184 }
2185
2186 #[inline]
2187 fn lt(&self, other: &Self) -> bool {
2188 <str as PartialOrd>::lt(self, other)
2189 }
2190
2191 #[inline]
2192 fn le(&self, other: &Self) -> bool {
2193 <str as PartialOrd>::le(self, other)
2194 }
2195
2196 #[inline]
2197 fn gt(&self, other: &Self) -> bool {
2198 <str as PartialOrd>::gt(self, other)
2199 }
2200
2201 #[inline]
2202 fn ge(&self, other: &Self) -> bool {
2203 <str as PartialOrd>::ge(self, other)
2204 }
2205}
2206
2207impl<A: BumpAllocatorExt> Ord for BumpString<A> {
2208 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
2209 <str as Ord>::cmp(self, other)
2210 }
2211}
2212
2213impl<A: BumpAllocatorExt> Hash for BumpString<A> {
2214 #[inline]
2215 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
2216 self.as_str().hash(state);
2217 }
2218}
2219
2220#[cfg(feature = "panic-on-alloc")]
2221impl<'s, A: BumpAllocatorExt> Extend<&'s str> for BumpString<A> {
2222 #[inline]
2223 fn extend<T: IntoIterator<Item = &'s str>>(&mut self, iter: T) {
2224 for str in iter {
2225 self.push_str(str);
2226 }
2227 }
2228}
2229
2230#[cfg(feature = "panic-on-alloc")]
2231impl<A: BumpAllocatorExt> Extend<char> for BumpString<A> {
2232 fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
2233 let iterator = iter.into_iter();
2234 let (lower_bound, _) = iterator.size_hint();
2235 self.reserve(lower_bound);
2236 iterator.for_each(move |c| self.push(c));
2237 }
2238}
2239
2240#[cfg(feature = "panic-on-alloc")]
2241impl<'s, A: BumpAllocatorExt> Extend<&'s char> for BumpString<A> {
2242 fn extend<I: IntoIterator<Item = &'s char>>(&mut self, iter: I) {
2243 self.extend(iter.into_iter().copied());
2244 }
2245}
2246
2247#[cfg(feature = "alloc")]
2248impl<A: BumpAllocatorExt> From<BumpString<A>> for alloc_crate::string::String {
2249 #[inline]
2250 fn from(value: BumpString<A>) -> Self {
2251 value.as_str().into()
2252 }
2253}
2254
2255/// Implements the `+` operator for concatenating two strings.
2256///
2257/// This consumes the `BumpString` on the left-hand side and re-uses its buffer (growing it if
2258/// necessary). This is done to avoid allocating a new `BumpString` and copying the entire contents on
2259/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by
2260/// repeated concatenation.
2261///
2262/// The string on the right-hand side is only borrowed; its contents are copied into the returned
2263/// `BumpString`.
2264///
2265/// # Examples
2266///
2267/// Concatenating two `BumpString`s takes the first by value and borrows the second:
2268///
2269/// ```
2270/// # use bump_scope::{Bump, BumpString};
2271/// # let bump: Bump = Bump::new();
2272/// let a = BumpString::from_str_in("hello", &bump);
2273/// let b = BumpString::from_str_in(" world", &bump);
2274/// let c = a + &b;
2275/// # _ = c;
2276/// // `a` is moved and can no longer be used here.
2277/// ```
2278///
2279/// If you want to keep using the first `BumpString`, you can clone it and append to the clone instead:
2280///
2281/// ```
2282/// # use bump_scope::{Bump, BumpString};
2283/// # let bump: Bump = Bump::new();
2284/// let a = BumpString::from_str_in("hello", &bump);
2285/// let b = BumpString::from_str_in(" world", &bump);
2286/// let c = a.clone() + &b;
2287/// // `a` is still valid here.
2288/// # _ = c;
2289/// ```
2290///
2291/// Concatenating `&str` slices can be done by converting the first to a `BumpString`:
2292///
2293/// ```
2294/// # use bump_scope::{Bump, BumpString};
2295/// # let bump: Bump = Bump::new();
2296/// let a = "hello";
2297/// let b = " world";
2298/// let c = BumpString::from_str_in(a, &bump) + b;
2299/// # _ = c;
2300/// ```
2301#[cfg(feature = "panic-on-alloc")]
2302impl<A: BumpAllocatorExt> core::ops::Add<&str> for BumpString<A> {
2303 type Output = Self;
2304
2305 #[inline]
2306 fn add(mut self, other: &str) -> Self {
2307 self.push_str(other);
2308 self
2309 }
2310}