@@ -582,15 +582,10 @@ impl<'a> DoubleEndedIterator for Split<'a> {
582
582
pub struct Lines < ' a > {
583
583
string : & ' a AsciiStr ,
584
584
}
585
-
586
585
impl < ' a > Iterator for Lines < ' a > {
587
586
type Item = & ' a AsciiStr ;
588
587
589
588
fn next ( & mut self ) -> Option < & ' a AsciiStr > {
590
- if self . string . is_empty ( ) {
591
- return None ;
592
- }
593
-
594
589
if let Some ( idx) = self . string
595
590
. chars ( )
596
591
. position ( |& chr| chr == AsciiChar :: LineFeed )
@@ -602,15 +597,34 @@ impl<'a> Iterator for Lines<'a> {
602
597
} ;
603
598
self . string = & self . string [ idx + 1 ..] ;
604
599
Some ( line)
600
+ } else if self . string . is_empty ( ) {
601
+ None
605
602
} else {
606
- if !self . string . is_empty ( ) {
607
- let line = self . string ;
608
- self . string = & self . string [ ..0 ] ;
609
- Some ( line)
610
- } else {
611
- None
603
+ let line = self . string ;
604
+ self . string = & self . string [ ..0 ] ;
605
+ Some ( line)
606
+ }
607
+ }
608
+ }
609
+ impl < ' a > DoubleEndedIterator for Lines < ' a > {
610
+ fn next_back ( & mut self ) -> Option < & ' a AsciiStr > {
611
+ if self . string . is_empty ( ) {
612
+ return None ;
613
+ }
614
+ let mut i = self . string . len ( ) ;
615
+ if self . string [ i-1 ] == AsciiChar :: LineFeed {
616
+ i -= 1 ;
617
+ if i > 0 && self . string [ i-1 ] == AsciiChar :: CarriageReturn {
618
+ i -= 1 ;
612
619
}
613
620
}
621
+ self . string = & self . string [ ..i] ;
622
+ while i > 0 && self . string [ i-1 ] != AsciiChar :: LineFeed {
623
+ i -= 1 ;
624
+ }
625
+ let line = & self . string [ i..] ;
626
+ self . string = & self . string [ ..i] ;
627
+ Some ( line)
614
628
}
615
629
}
616
630
@@ -946,13 +960,15 @@ mod tests {
946
960
for ( asciiline, line) in ascii. lines ( ) . zip ( & lines) {
947
961
assert_eq ! ( asciiline, * line) ;
948
962
}
963
+ assert_eq ! ( ascii. lines( ) . count( ) , lines. len( ) ) ;
949
964
950
965
let lines: [ & str ; 4 ] = [ "foo" , "bar" , "" , "baz" ] ;
951
966
let joined = "foo\r \n bar\n \n baz" ;
952
967
let ascii = AsciiStr :: from_ascii ( joined. as_bytes ( ) ) . unwrap ( ) ;
953
968
for ( asciiline, line) in ascii. lines ( ) . zip ( & lines) {
954
969
assert_eq ! ( asciiline, * line) ;
955
970
}
971
+ assert_eq ! ( ascii. lines( ) . count( ) , lines. len( ) ) ;
956
972
957
973
let trailing_line_break = b"\n " ;
958
974
let ascii = AsciiStr :: from_ascii ( & trailing_line_break) . unwrap ( ) ;
@@ -970,6 +986,29 @@ mod tests {
970
986
assert_eq ! ( 4 , iter_count) ;
971
987
}
972
988
989
+ #[ test]
990
+ fn lines_iter_rev ( ) {
991
+ let joined = "foo\r \n bar\n \n baz\n " ;
992
+ let ascii = AsciiStr :: from_ascii ( joined. as_bytes ( ) ) . unwrap ( ) ;
993
+ assert_eq ! ( ascii. lines( ) . rev( ) . count( ) , 4 ) ;
994
+ assert_eq ! ( ascii. lines( ) . rev( ) . count( ) , joined. lines( ) . rev( ) . count( ) ) ;
995
+ for ( asciiline, line) in ascii. lines ( ) . rev ( ) . zip ( joined. lines ( ) . rev ( ) ) {
996
+ assert_eq ! ( asciiline, line) ;
997
+ }
998
+ let mut iter = ascii. lines ( ) ;
999
+ assert_eq ! ( iter. next( ) , Some ( "foo" . as_ascii_str( ) . unwrap( ) ) ) ;
1000
+ assert_eq ! ( iter. next_back( ) , Some ( "baz" . as_ascii_str( ) . unwrap( ) ) ) ;
1001
+ assert_eq ! ( iter. next_back( ) , Some ( "" . as_ascii_str( ) . unwrap( ) ) ) ;
1002
+ assert_eq ! ( iter. next( ) , Some ( "bar" . as_ascii_str( ) . unwrap( ) ) ) ;
1003
+ }
1004
+
1005
+ #[ test]
1006
+ fn lines_iter_empty ( ) {
1007
+ assert_eq ! ( "" . as_ascii_str( ) . unwrap( ) . lines( ) . next( ) , None ) ;
1008
+ assert_eq ! ( "" . as_ascii_str( ) . unwrap( ) . lines( ) . next_back( ) , None ) ;
1009
+ assert_eq ! ( "" . lines( ) . next( ) , None ) ;
1010
+ }
1011
+
973
1012
#[ test]
974
1013
fn split_str ( ) {
975
1014
fn split_equals_str ( haystack : & str , needle : char ) {
0 commit comments