@@ -1043,7 +1043,7 @@ impl String {
1043
1043
#[ inline]
1044
1044
#[ must_use = "`self` will be dropped if the result is not used" ]
1045
1045
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1046
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1046
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1047
1047
#[ rustc_allow_const_fn_unstable( const_precise_live_drops) ]
1048
1048
pub const fn into_bytes ( self ) -> Vec < u8 > {
1049
1049
self . vec
@@ -1062,7 +1062,7 @@ impl String {
1062
1062
#[ must_use]
1063
1063
#[ stable( feature = "string_as_str" , since = "1.7.0" ) ]
1064
1064
#[ rustc_diagnostic_item = "string_as_str" ]
1065
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1065
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1066
1066
pub const fn as_str ( & self ) -> & str {
1067
1067
// SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error
1068
1068
// at construction.
@@ -1085,7 +1085,7 @@ impl String {
1085
1085
#[ must_use]
1086
1086
#[ stable( feature = "string_as_str" , since = "1.7.0" ) ]
1087
1087
#[ rustc_diagnostic_item = "string_as_mut_str" ]
1088
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1088
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1089
1089
pub const fn as_mut_str ( & mut self ) -> & mut str {
1090
1090
// SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error
1091
1091
// at construction.
@@ -1134,7 +1134,7 @@ impl String {
1134
1134
/// assert_eq!(string, "abcdecdeabecde");
1135
1135
/// ```
1136
1136
#[ cfg( not( no_global_oom_handling) ) ]
1137
- #[ stable( feature = "string_extend_from_within" , since = "CURRENT_RUSTC_VERSION " ) ]
1137
+ #[ stable( feature = "string_extend_from_within" , since = "1.87.0 " ) ]
1138
1138
pub fn extend_from_within < R > ( & mut self , src : R )
1139
1139
where
1140
1140
R : RangeBounds < usize > ,
@@ -1159,7 +1159,7 @@ impl String {
1159
1159
#[ inline]
1160
1160
#[ must_use]
1161
1161
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1162
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1162
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1163
1163
pub const fn capacity ( & self ) -> usize {
1164
1164
self . vec . capacity ( )
1165
1165
}
@@ -1401,11 +1401,14 @@ impl String {
1401
1401
#[ inline]
1402
1402
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1403
1403
pub fn push ( & mut self , ch : char ) {
1404
- match ch. len_utf8 ( ) {
1405
- 1 => self . vec . push ( ch as u8 ) ,
1406
- _ => {
1407
- self . vec . extend_from_slice ( ch. encode_utf8 ( & mut [ 0 ; char:: MAX_LEN_UTF8 ] ) . as_bytes ( ) )
1408
- }
1404
+ let len = self . len ( ) ;
1405
+ let ch_len = ch. len_utf8 ( ) ;
1406
+ self . reserve ( ch_len) ;
1407
+
1408
+ // SAFETY: Just reserved capacity for at least the length needed to encode `ch`.
1409
+ unsafe {
1410
+ core:: char:: encode_utf8_raw_unchecked ( ch as u32 , self . vec . as_mut_ptr ( ) . add ( self . len ( ) ) ) ;
1411
+ self . vec . set_len ( len + ch_len) ;
1409
1412
}
1410
1413
}
1411
1414
@@ -1425,7 +1428,7 @@ impl String {
1425
1428
#[ inline]
1426
1429
#[ must_use]
1427
1430
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1428
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1431
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1429
1432
pub const fn as_bytes ( & self ) -> & [ u8 ] {
1430
1433
self . vec . as_slice ( )
1431
1434
}
@@ -1702,24 +1705,31 @@ impl String {
1702
1705
#[ rustc_confusables( "set" ) ]
1703
1706
pub fn insert ( & mut self , idx : usize , ch : char ) {
1704
1707
assert ! ( self . is_char_boundary( idx) ) ;
1705
- let mut bits = [ 0 ; char:: MAX_LEN_UTF8 ] ;
1706
- let bits = ch. encode_utf8 ( & mut bits) . as_bytes ( ) ;
1707
1708
1709
+ let len = self . len ( ) ;
1710
+ let ch_len = ch. len_utf8 ( ) ;
1711
+ self . reserve ( ch_len) ;
1712
+
1713
+ // SAFETY: Move the bytes starting from `idx` to their new location `ch_len`
1714
+ // bytes ahead. This is safe because sufficient capacity was reserved, and `idx`
1715
+ // is a char boundary.
1708
1716
unsafe {
1709
- self . insert_bytes ( idx, bits) ;
1717
+ ptr:: copy (
1718
+ self . vec . as_ptr ( ) . add ( idx) ,
1719
+ self . vec . as_mut_ptr ( ) . add ( idx + ch_len) ,
1720
+ len - idx,
1721
+ ) ;
1710
1722
}
1711
- }
1712
1723
1713
- # [ cfg ( not ( no_global_oom_handling ) ) ]
1714
- unsafe fn insert_bytes ( & mut self , idx : usize , bytes : & [ u8 ] ) {
1715
- let len = self . len ( ) ;
1716
- let amt = bytes . len ( ) ;
1717
- self . vec . reserve ( amt ) ;
1724
+ // SAFETY: Encode the character into the vacated region if `idx != len`,
1725
+ // or into the uninitialized spare capacity otherwise.
1726
+ unsafe {
1727
+ core :: char :: encode_utf8_raw_unchecked ( ch as u32 , self . vec . as_mut_ptr ( ) . add ( idx ) ) ;
1728
+ }
1718
1729
1730
+ // SAFETY: Update the length to include the newly added bytes.
1719
1731
unsafe {
1720
- ptr:: copy ( self . vec . as_ptr ( ) . add ( idx) , self . vec . as_mut_ptr ( ) . add ( idx + amt) , len - idx) ;
1721
- ptr:: copy_nonoverlapping ( bytes. as_ptr ( ) , self . vec . as_mut_ptr ( ) . add ( idx) , amt) ;
1722
- self . vec . set_len ( len + amt) ;
1732
+ self . vec . set_len ( len + ch_len) ;
1723
1733
}
1724
1734
}
1725
1735
@@ -1749,8 +1759,27 @@ impl String {
1749
1759
pub fn insert_str ( & mut self , idx : usize , string : & str ) {
1750
1760
assert ! ( self . is_char_boundary( idx) ) ;
1751
1761
1762
+ let len = self . len ( ) ;
1763
+ let amt = string. len ( ) ;
1764
+ self . reserve ( amt) ;
1765
+
1766
+ // SAFETY: Move the bytes starting from `idx` to their new location `amt` bytes
1767
+ // ahead. This is safe because sufficient capacity was just reserved, and `idx`
1768
+ // is a char boundary.
1769
+ unsafe {
1770
+ ptr:: copy ( self . vec . as_ptr ( ) . add ( idx) , self . vec . as_mut_ptr ( ) . add ( idx + amt) , len - idx) ;
1771
+ }
1772
+
1773
+ // SAFETY: Copy the new string slice into the vacated region if `idx != len`,
1774
+ // or into the uninitialized spare capacity otherwise. The borrow checker
1775
+ // ensures that the source and destination do not overlap.
1776
+ unsafe {
1777
+ ptr:: copy_nonoverlapping ( string. as_ptr ( ) , self . vec . as_mut_ptr ( ) . add ( idx) , amt) ;
1778
+ }
1779
+
1780
+ // SAFETY: Update the length to include the newly added bytes.
1752
1781
unsafe {
1753
- self . insert_bytes ( idx , string . as_bytes ( ) ) ;
1782
+ self . vec . set_len ( len + amt ) ;
1754
1783
}
1755
1784
}
1756
1785
@@ -1779,7 +1808,7 @@ impl String {
1779
1808
/// ```
1780
1809
#[ inline]
1781
1810
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1782
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1811
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1783
1812
pub const unsafe fn as_mut_vec ( & mut self ) -> & mut Vec < u8 > {
1784
1813
& mut self . vec
1785
1814
}
@@ -1801,7 +1830,7 @@ impl String {
1801
1830
#[ inline]
1802
1831
#[ must_use]
1803
1832
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1804
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1833
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1805
1834
#[ rustc_confusables( "length" , "size" ) ]
1806
1835
pub const fn len ( & self ) -> usize {
1807
1836
self . vec . len ( )
@@ -1821,7 +1850,7 @@ impl String {
1821
1850
#[ inline]
1822
1851
#[ must_use]
1823
1852
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1824
- #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "CURRENT_RUSTC_VERSION " ) ]
1853
+ #[ rustc_const_stable( feature = "const_vec_string_slice" , since = "1.87.0 " ) ]
1825
1854
pub const fn is_empty ( & self ) -> bool {
1826
1855
self . len ( ) == 0
1827
1856
}
@@ -3140,7 +3169,7 @@ impl From<String> for Vec<u8> {
3140
3169
}
3141
3170
}
3142
3171
3143
- #[ stable( feature = "try_from_vec_u8_for_string" , since = "CURRENT_RUSTC_VERSION " ) ]
3172
+ #[ stable( feature = "try_from_vec_u8_for_string" , since = "1.87.0 " ) ]
3144
3173
impl TryFrom < Vec < u8 > > for String {
3145
3174
type Error = FromUtf8Error ;
3146
3175
/// Converts the given [`Vec<u8>`] into a [`String`] if it contains valid UTF-8 data.
0 commit comments