@@ -111,7 +111,24 @@ macro_rules! delegate_iter {
111
111
self . 0 . size_hint( )
112
112
}
113
113
}
114
- }
114
+ } ;
115
+ ( pattern reverse $te: ty : $ti: ty) => {
116
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
117
+ impl <' a, P : Pattern <' a>> Iterator for $ti
118
+ where P :: Searcher : ReverseSearcher <' a>
119
+ {
120
+ type Item = $te;
121
+
122
+ #[ inline]
123
+ fn next( & mut self ) -> Option <$te> {
124
+ self . 0 . next( )
125
+ }
126
+ #[ inline]
127
+ fn size_hint( & self ) -> ( usize , Option <usize >) {
128
+ self . 0 . size_hint( )
129
+ }
130
+ }
131
+ } ;
115
132
}
116
133
117
134
/// A trait to abstract the idea of creating a new instance of a type from a
@@ -550,7 +567,26 @@ struct CharSplitsN<'a, P: Pattern<'a>> {
550
567
iter : CharSplits < ' a , P > ,
551
568
/// The number of splits remaining
552
569
count : usize ,
553
- invert : bool ,
570
+ }
571
+
572
+ /// An iterator over the substrings of a string, separated by a
573
+ /// pattern, in reverse order.
574
+ struct RCharSplits < ' a , P : Pattern < ' a > > {
575
+ /// The slice remaining to be iterated
576
+ start : usize ,
577
+ end : usize ,
578
+ matcher : P :: Searcher ,
579
+ /// Whether an empty string at the end of iteration is allowed
580
+ allow_final_empty : bool ,
581
+ finished : bool ,
582
+ }
583
+
584
+ /// An iterator over the substrings of a string, separated by a
585
+ /// pattern, splitting at most `count` times, in reverse order.
586
+ struct RCharSplitsN < ' a , P : Pattern < ' a > > {
587
+ iter : RCharSplits < ' a , P > ,
588
+ /// The number of splits remaining
589
+ count : usize ,
554
590
}
555
591
556
592
/// An iterator over the lines of a string, separated by `\n`.
@@ -631,21 +667,74 @@ where P::Searcher: DoubleEndedSearcher<'a> {
631
667
}
632
668
633
669
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
634
- impl < ' a , P : Pattern < ' a > > Iterator for CharSplitsN < ' a , P >
635
- where P :: Searcher : DoubleEndedSearcher < ' a > {
670
+ impl < ' a , P : Pattern < ' a > > Iterator for CharSplitsN < ' a , P > {
636
671
type Item = & ' a str ;
637
672
638
673
#[ inline]
639
674
fn next ( & mut self ) -> Option < & ' a str > {
640
675
if self . count != 0 {
641
676
self . count -= 1 ;
642
- if self . invert { self . iter . next_back ( ) } else { self . iter . next ( ) }
677
+ self . iter . next ( )
643
678
} else {
644
679
self . iter . get_end ( )
645
680
}
646
681
}
647
682
}
648
683
684
+ impl < ' a , P : Pattern < ' a > > RCharSplits < ' a , P > {
685
+ #[ inline]
686
+ fn get_remainder ( & mut self ) -> Option < & ' a str > {
687
+ if !self . finished && ( self . allow_final_empty || self . end - self . start > 0 ) {
688
+ self . finished = true ;
689
+ unsafe {
690
+ let string = self . matcher . haystack ( ) . slice_unchecked ( self . start , self . end ) ;
691
+ Some ( string)
692
+ }
693
+ } else {
694
+ None
695
+ }
696
+ }
697
+ }
698
+
699
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
700
+ impl < ' a , P : Pattern < ' a > > Iterator for RCharSplits < ' a , P >
701
+ where P :: Searcher : ReverseSearcher < ' a >
702
+ {
703
+ type Item = & ' a str ;
704
+
705
+ #[ inline]
706
+ fn next ( & mut self ) -> Option < & ' a str > {
707
+ if self . finished { return None }
708
+
709
+ let haystack = self . matcher . haystack ( ) ;
710
+ match self . matcher . next_match_back ( ) {
711
+ Some ( ( a, b) ) => unsafe {
712
+ let elt = haystack. slice_unchecked ( b, self . end ) ;
713
+ self . end = a;
714
+ Some ( elt)
715
+ } ,
716
+ None => self . get_remainder ( ) ,
717
+ }
718
+ }
719
+ }
720
+
721
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
722
+ impl < ' a , P : Pattern < ' a > > Iterator for RCharSplitsN < ' a , P >
723
+ where P :: Searcher : ReverseSearcher < ' a >
724
+ {
725
+ type Item = & ' a str ;
726
+
727
+ #[ inline]
728
+ fn next ( & mut self ) -> Option < & ' a str > {
729
+ if self . count != 0 {
730
+ self . count -= 1 ;
731
+ self . iter . next ( )
732
+ } else {
733
+ self . iter . get_remainder ( )
734
+ }
735
+ }
736
+ }
737
+
649
738
/// The internal state of an iterator that searches for matches of a substring
650
739
/// within a larger string using two-way search
651
740
#[ derive( Clone ) ]
@@ -1293,23 +1382,7 @@ impl<'a, S: ?Sized> Str for &'a S where S: Str {
1293
1382
/// Return type of `StrExt::split`
1294
1383
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1295
1384
pub struct Split < ' a , P : Pattern < ' a > > ( CharSplits < ' a , P > ) ;
1296
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1297
- impl < ' a , P : Pattern < ' a > > Iterator for Split < ' a , P > {
1298
- type Item = & ' a str ;
1299
-
1300
- #[ inline]
1301
- fn next ( & mut self ) -> Option < & ' a str > {
1302
- self . 0 . next ( )
1303
- }
1304
- }
1305
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1306
- impl < ' a , P : Pattern < ' a > > DoubleEndedIterator for Split < ' a , P >
1307
- where P :: Searcher : DoubleEndedSearcher < ' a > {
1308
- #[ inline]
1309
- fn next_back ( & mut self ) -> Option < & ' a str > {
1310
- self . 0 . next_back ( )
1311
- }
1312
- }
1385
+ delegate_iter ! { pattern & ' a str : Split <' a, P >}
1313
1386
1314
1387
/// Return type of `StrExt::split_terminator`
1315
1388
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1321,10 +1394,15 @@ delegate_iter!{pattern &'a str : SplitTerminator<'a, P>}
1321
1394
pub struct SplitN < ' a , P : Pattern < ' a > > ( CharSplitsN < ' a , P > ) ;
1322
1395
delegate_iter ! { pattern forward & ' a str : SplitN <' a, P >}
1323
1396
1397
+ /// Return type of `StrExt::rsplit`
1398
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1399
+ pub struct RSplit < ' a , P : Pattern < ' a > > ( RCharSplits < ' a , P > ) ;
1400
+ delegate_iter ! { pattern reverse & ' a str : RSplit <' a, P >}
1401
+
1324
1402
/// Return type of `StrExt::rsplitn`
1325
1403
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1326
- pub struct RSplitN < ' a , P : Pattern < ' a > > ( CharSplitsN < ' a , P > ) ;
1327
- delegate_iter ! { pattern forward & ' a str : RSplitN <' a, P >}
1404
+ pub struct RSplitN < ' a , P : Pattern < ' a > > ( RCharSplitsN < ' a , P > ) ;
1405
+ delegate_iter ! { pattern reverse & ' a str : RSplitN <' a, P >}
1328
1406
1329
1407
/// Methods for string slices
1330
1408
#[ allow( missing_docs) ]
@@ -1340,7 +1418,10 @@ pub trait StrExt {
1340
1418
fn split < ' a , P : Pattern < ' a > > ( & ' a self , pat : P ) -> Split < ' a , P > ;
1341
1419
fn splitn < ' a , P : Pattern < ' a > > ( & ' a self , count : usize , pat : P ) -> SplitN < ' a , P > ;
1342
1420
fn split_terminator < ' a , P : Pattern < ' a > > ( & ' a self , pat : P ) -> SplitTerminator < ' a , P > ;
1343
- fn rsplitn < ' a , P : Pattern < ' a > > ( & ' a self , count : usize , pat : P ) -> RSplitN < ' a , P > ;
1421
+ fn rsplit < ' a , P : Pattern < ' a > > ( & ' a self , pat : P ) -> RSplit < ' a , P >
1422
+ where P :: Searcher : ReverseSearcher < ' a > ;
1423
+ fn rsplitn < ' a , P : Pattern < ' a > > ( & ' a self , count : usize , pat : P ) -> RSplitN < ' a , P >
1424
+ where P :: Searcher : ReverseSearcher < ' a > ;
1344
1425
fn match_indices < ' a , P : Pattern < ' a > > ( & ' a self , pat : P ) -> MatchIndices < ' a , P > ;
1345
1426
#[ allow( deprecated) /* for SplitStr */ ]
1346
1427
fn split_str < ' a , P : Pattern < ' a > > ( & ' a self , pat : P ) -> SplitStr < ' a , P > ;
@@ -1424,7 +1505,6 @@ impl StrExt for str {
1424
1505
SplitN ( CharSplitsN {
1425
1506
iter : self . split ( pat) . 0 ,
1426
1507
count : count,
1427
- invert : false ,
1428
1508
} )
1429
1509
}
1430
1510
@@ -1437,11 +1517,25 @@ impl StrExt for str {
1437
1517
}
1438
1518
1439
1519
#[ inline]
1440
- fn rsplitn < ' a , P : Pattern < ' a > > ( & ' a self , count : usize , pat : P ) -> RSplitN < ' a , P > {
1441
- RSplitN ( CharSplitsN {
1442
- iter : self . split ( pat) . 0 ,
1520
+ fn rsplit < ' a , P : Pattern < ' a > > ( & ' a self , pat : P ) -> RSplit < ' a , P >
1521
+ where P :: Searcher : ReverseSearcher < ' a >
1522
+ {
1523
+ RSplit ( RCharSplits {
1524
+ start : 0 ,
1525
+ end : self . len ( ) ,
1526
+ matcher : pat. into_searcher ( self ) ,
1527
+ allow_final_empty : true ,
1528
+ finished : false ,
1529
+ } )
1530
+ }
1531
+
1532
+ #[ inline]
1533
+ fn rsplitn < ' a , P : Pattern < ' a > > ( & ' a self , count : usize , pat : P ) -> RSplitN < ' a , P >
1534
+ where P :: Searcher : ReverseSearcher < ' a >
1535
+ {
1536
+ RSplitN ( RCharSplitsN {
1537
+ iter : self . rsplit ( pat) . 0 ,
1443
1538
count : count,
1444
- invert : true ,
1445
1539
} )
1446
1540
}
1447
1541
0 commit comments