@@ -353,46 +353,10 @@ impl Repr {
353353 // SAFETY: We know this is a valid length which falls on a char boundary
354354 let new_len = self . len ( ) - ch. len_utf8 ( ) ;
355355
356- if self . is_heap_buffer ( ) {
357- // SAFETY: We just checked that `self` is HeapBuffer
358- let heap = unsafe { self . as_heap_buffer_mut ( ) } ;
359-
360- if !heap. is_len_on_heap ( ) {
361- // Since len is inlined and we don't modify the buffer by popping a char, it is ok
362- // to just set the new length.
363- // SAFETY: `new_len <= len <= capacity`
364- unsafe { heap. set_len ( new_len) } ;
365- } else {
366- // See `reverse` method for the explanation of the ordering.
367- if heap. reference_count ( ) . fetch_sub ( 1 , Release ) == 1 {
368- // `heap` is unique, we can set the new length in place.
369-
370- // See `reverse` method for the explanation of the ordering.
371- heap. reference_count ( ) . fetch_add ( 1 , Acquire ) ;
372-
373- // SAFETY: `heap` is unique, we can reallocate in place.
374- unsafe { heap. set_len ( new_len) } ;
375- } else {
376- // SAFETY: `ptr` is valid for `len` bytes, and `HeapBuffer` contains valid UTF-8.
377- let str = unsafe {
378- let ptr = self . 0 as * mut u8 ;
379- let slice = slice:: from_raw_parts_mut ( ptr, new_len) ;
380- str:: from_utf8_unchecked_mut ( slice)
381- } ;
382- * self = Repr :: from_str ( str) ?;
383- }
384- }
385- } else if self . is_static_buffer ( ) {
386- // SAFETY:
387- // - We just checked that `self` is StaticBuffer
388- // - `new_len <= len <= capacity`
389- unsafe { self . as_static_buffer_mut ( ) . set_len ( new_len) } ;
390- } else {
391- // SAFETY:
392- // - The number of types of buffer is 3, and the remaining is InlineBuffer.
393- // - From `#Safety`, `new_len <= MAX_INLINE_SIZE` is true.
394- unsafe { self . as_inline_buffer_mut ( ) . set_len ( new_len) } ;
395- }
356+ // SAFETY:
357+ // - `new_len` is less than `len()` because we calculated it from `len() - ch.len_utf8()`.
358+ // - `new_len` is a valid char boundary because `ch` is a valid char.
359+ unsafe { self . truncate_unchecked ( new_len) } ?;
396360
397361 Ok ( Some ( ch) )
398362 }
@@ -516,6 +480,74 @@ impl Repr {
516480 Ok ( ( ) )
517481 }
518482
483+ #[ inline]
484+ pub ( crate ) fn truncate ( & mut self , new_len : usize ) -> Result < ( ) , ReserveError > {
485+ if new_len >= self . len ( ) {
486+ return Ok ( ( ) ) ;
487+ }
488+
489+ let str = self . as_str ( ) ;
490+ assert ! (
491+ str . is_char_boundary( new_len) ,
492+ "index is not a char boundary or out of bounds (index: {new_len})" ,
493+ ) ;
494+
495+ // SAFETY: We just checked that `new_len < len()` and `new_len` is a valid char
496+ unsafe { self . truncate_unchecked ( new_len) }
497+ }
498+
499+ /// # Safety
500+ ///
501+ /// - `new_len` must be less than or equal to `len()`
502+ /// - `new_len` must be a valid char boundary.
503+ unsafe fn truncate_unchecked ( & mut self , new_len : usize ) -> Result < ( ) , ReserveError > {
504+ debug_assert ! ( new_len <= self . len( ) ) ;
505+ debug_assert ! ( self . as_str( ) . is_char_boundary( new_len) ) ;
506+
507+ if self . is_heap_buffer ( ) {
508+ // SAFETY: We just checked that `self` is HeapBuffer
509+ let heap = unsafe { self . as_heap_buffer_mut ( ) } ;
510+
511+ if !heap. is_len_on_heap ( ) {
512+ // Since len is inlined and we don't modify the buffer by popping a char, it is ok
513+ // to just set the new length.
514+ // SAFETY: `new_len <= len <= capacity`
515+ unsafe { heap. set_len ( new_len) } ;
516+ } else {
517+ // See `reverse` method for the explanation of the ordering.
518+ if heap. reference_count ( ) . fetch_sub ( 1 , Release ) == 1 {
519+ // `heap` is unique, we can set the new length in place.
520+
521+ // See `reverse` method for the explanation of the ordering.
522+ heap. reference_count ( ) . fetch_add ( 1 , Acquire ) ;
523+
524+ // SAFETY: `heap` is unique, we can reallocate in place.
525+ unsafe { heap. set_len ( new_len) } ;
526+ } else {
527+ // SAFETY: `ptr` is valid for `len` bytes, and `HeapBuffer` contains valid UTF-8.
528+ let str = unsafe {
529+ let ptr = self . 0 as * mut u8 ;
530+ let slice = slice:: from_raw_parts_mut ( ptr, new_len) ;
531+ str:: from_utf8_unchecked_mut ( slice)
532+ } ;
533+ * self = Repr :: from_str ( str) ?;
534+ }
535+ }
536+ } else if self . is_static_buffer ( ) {
537+ // SAFETY:
538+ // - We just checked that `self` is StaticBuffer
539+ // - `new_len <= len <= capacity`
540+ unsafe { self . as_static_buffer_mut ( ) . set_len ( new_len) } ;
541+ } else {
542+ // SAFETY:
543+ // - The number of types of buffer is 3, and the remaining is InlineBuffer.
544+ // - From `#Safety`, `new_len <= MAX_INLINE_SIZE` is true.
545+ unsafe { self . as_inline_buffer_mut ( ) . set_len ( new_len) } ;
546+ }
547+
548+ Ok ( ( ) )
549+ }
550+
519551 #[ inline]
520552 pub ( crate ) fn is_unique ( & self ) -> bool {
521553 if self . is_heap_buffer ( ) {
0 commit comments