@@ -1316,7 +1316,7 @@ impl String {
1316
1316
self . vec . clear ( )
1317
1317
}
1318
1318
1319
- /// Create a draining iterator that removes the specified range in the string
1319
+ /// Creates a draining iterator that removes the specified range in the string
1320
1320
/// and yields the removed chars.
1321
1321
///
1322
1322
/// Note: The element range is removed even if the iterator is not
@@ -1382,6 +1382,71 @@ impl String {
1382
1382
}
1383
1383
}
1384
1384
1385
+ /// Creates a splicing iterator that removes the specified range in the string,
1386
+ /// replaces with the given string, and yields the removed chars.
1387
+ /// The given string doesn’t need to be the same length as the range.
1388
+ ///
1389
+ /// Note: The element range is removed when the `Splice` is dropped,
1390
+ /// even if the iterator is not consumed until the end.
1391
+ ///
1392
+ /// # Panics
1393
+ ///
1394
+ /// Panics if the starting point or end point do not lie on a [`char`]
1395
+ /// boundary, or if they're out of bounds.
1396
+ ///
1397
+ /// [`char`]: ../../std/primitive.char.html
1398
+ ///
1399
+ /// # Examples
1400
+ ///
1401
+ /// Basic usage:
1402
+ ///
1403
+ /// ```
1404
+ /// #![feature(splice)]
1405
+ /// let mut s = String::from("α is alpha, β is beta");
1406
+ /// let beta_offset = s.find('β').unwrap_or(s.len());
1407
+ ///
1408
+ /// // Replace the range up until the β from the string
1409
+ /// let t: String = s.splice(..beta_offset, "Α is capital alpha; ").collect();
1410
+ /// assert_eq!(t, "α is alpha, ");
1411
+ /// assert_eq!(s, "Α is capital alpha; β is beta");
1412
+ /// ```
1413
+ #[ unstable( feature = "splice" , reason = "recently added" , issue = "32310" ) ]
1414
+ pub fn splice < ' a , ' b , R > ( & ' a mut self , range : R , replace_with : & ' b str ) -> Splice < ' a , ' b >
1415
+ where R : RangeArgument < usize >
1416
+ {
1417
+ // Memory safety
1418
+ //
1419
+ // The String version of Splice does not have the memory safety issues
1420
+ // of the vector version. The data is just plain bytes.
1421
+ // Because the range removal happens in Drop, if the Splice iterator is leaked,
1422
+ // the removal will not happen.
1423
+ let len = self . len ( ) ;
1424
+ let start = match range. start ( ) {
1425
+ Included ( & n) => n,
1426
+ Excluded ( & n) => n + 1 ,
1427
+ Unbounded => 0 ,
1428
+ } ;
1429
+ let end = match range. end ( ) {
1430
+ Included ( & n) => n + 1 ,
1431
+ Excluded ( & n) => n,
1432
+ Unbounded => len,
1433
+ } ;
1434
+
1435
+ // Take out two simultaneous borrows. The &mut String won't be accessed
1436
+ // until iteration is over, in Drop.
1437
+ let self_ptr = self as * mut _ ;
1438
+ // slicing does the appropriate bounds checks
1439
+ let chars_iter = self [ start..end] . chars ( ) ;
1440
+
1441
+ Splice {
1442
+ start : start,
1443
+ end : end,
1444
+ iter : chars_iter,
1445
+ string : self_ptr,
1446
+ replace_with : replace_with
1447
+ }
1448
+ }
1449
+
1385
1450
/// Converts this `String` into a `Box<str>`.
1386
1451
///
1387
1452
/// This will drop any excess capacity.
@@ -2145,3 +2210,61 @@ impl<'a> DoubleEndedIterator for Drain<'a> {
2145
2210
2146
2211
#[ unstable( feature = "fused" , issue = "35602" ) ]
2147
2212
impl < ' a > FusedIterator for Drain < ' a > { }
2213
+
2214
+ /// A splicing iterator for `String`.
2215
+ ///
2216
+ /// This struct is created by the [`splice()`] method on [`String`]. See its
2217
+ /// documentation for more.
2218
+ ///
2219
+ /// [`splice()`]: struct.String.html#method.splice
2220
+ /// [`String`]: struct.String.html
2221
+ #[ derive( Debug ) ]
2222
+ #[ unstable( feature = "splice" , reason = "recently added" , issue = "32310" ) ]
2223
+ pub struct Splice < ' a , ' b > {
2224
+ /// Will be used as &'a mut String in the destructor
2225
+ string : * mut String ,
2226
+ /// Start of part to remove
2227
+ start : usize ,
2228
+ /// End of part to remove
2229
+ end : usize ,
2230
+ /// Current remaining range to remove
2231
+ iter : Chars < ' a > ,
2232
+ replace_with : & ' b str ,
2233
+ }
2234
+
2235
+ #[ unstable( feature = "splice" , reason = "recently added" , issue = "32310" ) ]
2236
+ unsafe impl < ' a , ' b > Sync for Splice < ' a , ' b > { }
2237
+ #[ unstable( feature = "splice" , reason = "recently added" , issue = "32310" ) ]
2238
+ unsafe impl < ' a , ' b > Send for Splice < ' a , ' b > { }
2239
+
2240
+ #[ unstable( feature = "splice" , reason = "recently added" , issue = "32310" ) ]
2241
+ impl < ' a , ' b > Drop for Splice < ' a , ' b > {
2242
+ fn drop ( & mut self ) {
2243
+ unsafe {
2244
+ let vec = ( * self . string ) . as_mut_vec ( ) ;
2245
+ vec. splice ( self . start ..self . end , self . replace_with . bytes ( ) ) ;
2246
+ }
2247
+ }
2248
+ }
2249
+
2250
+ #[ unstable( feature = "splice" , reason = "recently added" , issue = "32310" ) ]
2251
+ impl < ' a , ' b > Iterator for Splice < ' a , ' b > {
2252
+ type Item = char ;
2253
+
2254
+ #[ inline]
2255
+ fn next ( & mut self ) -> Option < char > {
2256
+ self . iter . next ( )
2257
+ }
2258
+
2259
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
2260
+ self . iter . size_hint ( )
2261
+ }
2262
+ }
2263
+
2264
+ #[ unstable( feature = "splice" , reason = "recently added" , issue = "32310" ) ]
2265
+ impl < ' a , ' b > DoubleEndedIterator for Splice < ' a , ' b > {
2266
+ #[ inline]
2267
+ fn next_back ( & mut self ) -> Option < char > {
2268
+ self . iter . next_back ( )
2269
+ }
2270
+ }
0 commit comments