@@ -335,7 +335,7 @@ where
335
335
#[ inline]
336
336
#[ cfg_attr( all( feature = "no-panic" , not( debug_assertions) ) , no_panic) ]
337
337
pub fn as_str ( & self ) -> & str {
338
- trace ! ( "As str: {self} " ) ;
338
+ trace ! ( "As str" ) ;
339
339
self . as_ref ( )
340
340
}
341
341
@@ -429,13 +429,9 @@ where
429
429
#[ cfg_attr( all( feature = "no-panic" , not( debug_assertions) ) , no_panic) ]
430
430
pub fn try_push_str ( & mut self , string : impl AsRef < str > ) -> Result < ( ) , OutOfBounds > {
431
431
trace ! ( "Push str: {}" , string. as_ref( ) ) ;
432
- let str = string. as_ref ( ) ;
433
- if str. is_empty ( ) {
434
- return Ok ( ( ) ) ;
435
- }
436
- is_inside_boundary ( str. len ( ) + self . len ( ) , Self :: capacity ( ) ) ?;
437
- unsafe { self . push_str_unchecked ( str. as_bytes ( ) ) } ;
438
- Ok ( ( ) )
432
+ let len = self . len ( ) ;
433
+ self . replace_range ( len..len, string)
434
+ . map_err ( |_| OutOfBounds )
439
435
}
440
436
441
437
/// Pushes string slice to the end of the `ArrayString` truncating total size if bigger than [`capacity`].
@@ -460,23 +456,7 @@ where
460
456
#[ cfg_attr( all( feature = "no-panic" , not( debug_assertions) ) , no_panic) ]
461
457
pub fn push_str_truncate ( & mut self , string : impl AsRef < str > ) {
462
458
trace ! ( "Push str truncate: {}" , string. as_ref( ) ) ;
463
- let str = string. as_ref ( ) . as_bytes ( ) ;
464
- let size = Self :: capacity ( ) . saturating_sub ( self . len ( ) ) ;
465
- if size == 0 || str. is_empty ( ) {
466
- return ;
467
- }
468
- let str = truncate_str ( str, size) ;
469
- unsafe { self . push_str_unchecked ( str) } ;
470
- }
471
-
472
- #[ inline]
473
- unsafe fn push_str_unchecked ( & mut self , bytes : & [ u8 ] ) {
474
- core:: ptr:: copy_nonoverlapping (
475
- bytes. as_ptr ( ) ,
476
- self . array . as_mut_ptr ( ) . add ( self . len ( ) ) ,
477
- bytes. len ( ) ,
478
- ) ;
479
- self . size += bytes. len ( ) . into_lossy ( ) ;
459
+ let _ = self . try_push_str ( truncate_str ( string. as_ref ( ) , Self :: capacity ( ) - self . len ( ) ) ) ;
480
460
}
481
461
482
462
/// Inserts character to the end of the `ArrayString` erroring if total size if bigger than [`capacity`].
@@ -574,7 +554,7 @@ where
574
554
#[ inline]
575
555
#[ cfg_attr( all( feature = "no-panic" , not( debug_assertions) ) , no_panic) ]
576
556
pub fn trim ( & mut self ) {
577
- trace ! ( "Trim" ) ;
557
+ trace ! ( "Trim: {self:?} " ) ;
578
558
let mut start = self . len ( ) ;
579
559
for ( pos, char) in self . as_str ( ) . char_indices ( ) {
580
560
if !char. is_whitespace ( ) {
@@ -594,12 +574,9 @@ where
594
574
end = pos;
595
575
}
596
576
597
- self . size = end. saturating_sub ( start) . into_lossy ( ) ;
598
-
599
- unsafe {
600
- let ptr = self . array . as_mut_ptr ( ) ;
601
- core:: ptr:: copy ( ptr. add ( start) , ptr, self . len ( ) ) ;
602
- }
577
+ let _ = self . replace_range ( ..start, "" ) ;
578
+ // Note: Garanteed to not overflow but that should not be the bottleneck
579
+ let _ = self . replace_range ( end. saturating_sub ( start) .., "" ) ;
603
580
}
604
581
605
582
/// Removes specified char from `ArrayString`
@@ -623,21 +600,23 @@ where
623
600
#[ cfg_attr( all( feature = "no-panic" , not( debug_assertions) ) , no_panic) ]
624
601
pub fn remove ( & mut self , idx : usize ) -> Result < char , Error > {
625
602
debug ! ( "Remove: {}" , idx) ;
626
- is_inside_boundary ( idx, self . len ( ) ) ?;
603
+ is_inside_boundary ( idx. saturating_add ( 1 ) , self . len ( ) ) ?;
627
604
is_char_boundary ( self , idx) ?;
628
- let char = unsafe {
629
- self . as_str ( )
630
- . get_unchecked ( idx..)
631
- . chars ( )
632
- . next ( )
633
- . ok_or ( OutOfBounds ) ?
634
- } ;
635
- let len = char. len_utf8 ( ) ;
636
- if idx + len < self . len ( ) {
637
- self . array . copy_within ( idx + len.., idx) ;
605
+
606
+ let mut end = if idx == self . len ( ) { idx } else { idx + 1 } ;
607
+ while !self . as_str ( ) . is_char_boundary ( end) {
608
+ end += 1 ;
638
609
}
639
- self . size -= len. into_lossy ( ) ;
640
- Ok ( char)
610
+
611
+ let ch = self
612
+ . as_str ( )
613
+ . get ( idx..end)
614
+ . ok_or ( Error :: OutOfBounds ) ?
615
+ . chars ( )
616
+ . next ( )
617
+ . ok_or ( Error :: Utf8 ) ?;
618
+ self . replace_range ( idx..idx + ch. len_utf8 ( ) , "" ) ?;
619
+ Ok ( ch)
641
620
}
642
621
643
622
/// Retains only the characters specified by the predicate.
@@ -707,8 +686,7 @@ where
707
686
/// let mut s = ArrayString::<23>::try_from_str("ABCD🤔")?;
708
687
/// s.try_insert_str(1, "AB")?;
709
688
/// s.try_insert_str(1, "BC")?;
710
- /// assert_eq!(s.try_insert_str(1, "0".repeat(ArrayString::<23>::capacity())),
711
- /// Err(Error::OutOfBounds));
689
+ /// assert_eq!(s.try_insert_str(1, "0".repeat(ArrayString::<23>::capacity())), Err(Error::OutOfBounds));
712
690
/// assert_eq!(s.as_str(), "ABCABBCD🤔");
713
691
/// assert_eq!(s.try_insert_str(20, "C"), Err(Error::OutOfBounds));
714
692
/// assert_eq!(s.try_insert_str(10, "D"), Err(Error::Utf8));
@@ -718,23 +696,9 @@ where
718
696
#[ inline]
719
697
#[ cfg_attr( all( feature = "no-panic" , not( debug_assertions) ) , no_panic) ]
720
698
pub fn try_insert_str ( & mut self , idx : usize , string : impl AsRef < str > ) -> Result < ( ) , Error > {
721
- trace ! ( "Try insert at {idx} str: {}" , string. as_ref( ) ) ;
722
- let str = string. as_ref ( ) . as_bytes ( ) ;
699
+ trace ! ( "Try insert at {idx} str: {:?} to {self:?}" , string. as_ref( ) ) ;
723
700
is_inside_boundary ( idx, self . len ( ) ) ?;
724
- is_inside_boundary ( idx + str. len ( ) + self . len ( ) , Self :: capacity ( ) ) ?;
725
- is_char_boundary ( self , idx) ?;
726
- if str. is_empty ( ) {
727
- return Ok ( ( ) ) ;
728
- }
729
-
730
- unsafe {
731
- let ptr = self . array . as_mut_ptr ( ) . add ( idx) ;
732
- core:: ptr:: copy ( ptr, ptr. add ( str. len ( ) ) , self . len ( ) . saturating_sub ( idx) ) ;
733
- core:: ptr:: copy ( str. as_ptr ( ) , ptr, str. len ( ) ) ;
734
- }
735
- self . size = self . len ( ) . saturating_add ( str. len ( ) ) . into_lossy ( ) ;
736
-
737
- Ok ( ( ) )
701
+ self . replace_range ( idx..idx, string)
738
702
}
739
703
740
704
/// Inserts string slice at specified index, truncating size if bigger than [`capacity`].
@@ -770,24 +734,11 @@ where
770
734
idx : usize ,
771
735
string : impl AsRef < str > ,
772
736
) -> Result < ( ) , Error > {
773
- trace ! ( "Insert str at {idx}: {}" , string. as_ref( ) ) ;
774
- is_inside_boundary ( idx, self . len ( ) ) ?;
775
- is_char_boundary ( self , idx) ?;
776
- let size = Self :: capacity ( ) . saturating_sub ( idx) ;
777
- if size == 0 {
778
- return Ok ( ( ) ) ;
779
- }
780
- let str = truncate_str ( string. as_ref ( ) . as_bytes ( ) , size) ;
781
- if str. is_empty ( ) {
782
- return Ok ( ( ) ) ;
783
- }
784
-
785
- unsafe {
786
- let ptr = self . array . as_mut_ptr ( ) . add ( idx) ;
787
- core:: ptr:: copy ( ptr, ptr. add ( str. len ( ) ) , self . len ( ) . saturating_sub ( idx) ) ;
788
- core:: ptr:: copy ( str. as_ptr ( ) , ptr, str. len ( ) ) ;
789
- }
790
- self . size = self . len ( ) . saturating_add ( str. len ( ) ) . into_lossy ( ) ;
737
+ trace ! ( "Insert str at {idx}: {} to {self}" , string. as_ref( ) ) ;
738
+ self . try_insert_str (
739
+ idx,
740
+ truncate_str ( string. as_ref ( ) , Self :: capacity ( ) - self . len ( ) ) ,
741
+ ) ?;
791
742
Ok ( ( ) )
792
743
}
793
744
@@ -855,13 +806,8 @@ where
855
806
#[ cfg_attr( all( feature = "no-panic" , not( debug_assertions) ) , no_panic) ]
856
807
pub fn split_off ( & mut self , at : usize ) -> Result < Self , Error > {
857
808
debug ! ( "Split off" ) ;
858
- is_inside_boundary ( at, self . len ( ) ) ?;
859
- is_char_boundary ( self , at) ?;
860
- debug_assert ! ( at <= self . len( ) && self . as_str( ) . is_char_boundary( at) ) ;
861
- let new =
862
- unsafe { Self :: try_from_str ( self . as_str ( ) . get_unchecked ( at..) ) . unwrap_unchecked ( ) } ;
863
- self . size = at. into_lossy ( ) ;
864
- Ok ( new)
809
+ let drained = self . drain ( at..) ?. 0 ;
810
+ Ok ( drained)
865
811
}
866
812
867
813
/// Empties `ArrayString`
@@ -926,7 +872,7 @@ where
926
872
927
873
let drain = unsafe {
928
874
let slice = self . as_str ( ) . get_unchecked ( start..end) ;
929
- Self :: try_from_str ( slice) . unwrap_unchecked ( )
875
+ Self :: try_from_str ( slice) ?
930
876
} ;
931
877
self . array . copy_within ( end.., start) ;
932
878
self . size = self
@@ -943,7 +889,7 @@ where
943
889
/// # #[cfg(not(miri))] let _ = env_logger::try_init();
944
890
/// let mut s = ArrayString::<23>::try_from_str("ABCD🤔")?;
945
891
/// s.replace_range(2..4, "EFGHI")?;
946
- /// assert_eq!(s.as_bytes() , "ABEFGHI🤔".as_bytes() );
892
+ /// assert_eq!(s, "ABEFGHI🤔");
947
893
///
948
894
/// assert_eq!(s.replace_range(9.., "J"), Err(Error::Utf8));
949
895
/// assert_eq!(s.replace_range(..90, "K"), Err(Error::OutOfBounds));
@@ -982,20 +928,30 @@ where
982
928
}
983
929
is_inside_boundary ( start, end) ?;
984
930
is_inside_boundary ( end, self . len ( ) ) ?;
931
+ is_inside_boundary ( str. len ( ) , Self :: capacity ( ) ) ?;
985
932
is_char_boundary ( self , start) ?;
986
933
is_char_boundary ( self , end) ?;
987
- is_inside_boundary (
988
- ( start + str. len ( ) + self . len ( ) ) . saturating_sub ( end) ,
989
- Self :: capacity ( ) ,
990
- ) ?;
934
+ // Will never overflow since start < end and str.len() cannot be bigger than 255
935
+ is_inside_boundary ( self . len ( ) + str. len ( ) + start - end, Self :: capacity ( ) ) ?;
991
936
992
937
let this_len = self . len ( ) ;
993
938
unsafe {
994
939
let ptr = self . array . as_mut_ptr ( ) ;
995
- core:: ptr:: copy ( ptr. add ( end) , ptr. add ( str. len ( ) . saturating_add ( start) ) , this_len. saturating_sub ( end) ) ;
996
- core:: ptr:: copy ( str. as_ptr ( ) , ptr. add ( start) , str. len ( ) ) ;
940
+ core:: ptr:: copy (
941
+ ptr. add ( end) ,
942
+ ptr. add ( str. len ( ) . saturating_add ( start) ) ,
943
+ this_len. saturating_sub ( end) ,
944
+ ) ;
945
+ if !str. is_empty ( ) {
946
+ core:: ptr:: copy ( str. as_ptr ( ) , ptr. add ( start) , str. len ( ) ) ;
947
+ }
997
948
}
998
- self . size = self . len ( ) . saturating_add ( str. len ( ) ) . saturating_add ( start) . saturating_sub ( end) . into_lossy ( ) ;
949
+ self . size = self
950
+ . len ( )
951
+ . saturating_add ( str. len ( ) )
952
+ . saturating_add ( start)
953
+ . saturating_sub ( end)
954
+ . into_lossy ( ) ;
999
955
Ok ( ( ) )
1000
956
}
1001
957
}
0 commit comments