22
33use std:: {
44 borrow:: Cow ,
5- collections:: VecDeque ,
65 hash:: Hash ,
76 ops:: { Bound , RangeBounds } ,
87 rc:: Rc ,
@@ -134,13 +133,24 @@ impl<'a> Rope<'a> {
134133 iter : s. char_indices ( ) ,
135134 } ,
136135 } ,
137- Repr :: Full ( data) => CharIndices {
138- iter : CharIndicesEnum :: Full {
139- chunks : data,
140- char_indices : VecDeque :: new ( ) ,
141- chunk_index : 0 ,
142- } ,
143- } ,
136+ Repr :: Full ( vec) => {
137+ let right_byte_offset = vec. iter ( ) . map ( |( s, _) | s. len ( ) as u32 ) . sum ( ) ;
138+
139+ CharIndices {
140+ iter : CharIndicesEnum :: Full {
141+ iters : vec
142+ . iter ( )
143+ . map ( |( s, _) | s. char_indices ( ) )
144+ . collect :: < Vec < _ > > ( ) ,
145+ left_chunk_index : 0 ,
146+ left_byte_offset : 0 ,
147+ last_left_indice : None ,
148+ right_chunk_index : ( vec. len ( ) - 1 ) as u32 ,
149+ right_byte_offset,
150+ right_byte_offset_for : vec. len ( ) as u32 ,
151+ } ,
152+ }
153+ }
144154 }
145155 }
146156
@@ -658,9 +668,13 @@ enum CharIndicesEnum<'a, 'b> {
658668 iter : std:: str:: CharIndices < ' b > ,
659669 } ,
660670 Full {
661- chunks : & ' a [ ( & ' b str , usize ) ] ,
662- char_indices : VecDeque < ( usize , char ) > ,
663- chunk_index : usize ,
671+ iters : Vec < std:: str:: CharIndices < ' a > > ,
672+ left_chunk_index : u32 ,
673+ left_byte_offset : u32 ,
674+ last_left_indice : Option < ( usize , char ) > ,
675+ right_chunk_index : u32 ,
676+ right_byte_offset : u32 ,
677+ right_byte_offset_for : u32 ,
664678 } ,
665679}
666680
@@ -675,29 +689,59 @@ impl Iterator for CharIndices<'_, '_> {
675689 match & mut self . iter {
676690 CharIndicesEnum :: Light { iter } => iter. next ( ) ,
677691 CharIndicesEnum :: Full {
678- chunks,
679- char_indices,
680- chunk_index,
692+ iters,
693+ left_chunk_index,
694+ left_byte_offset,
695+ last_left_indice,
696+ ..
681697 } => {
682- if let Some ( item) = char_indices. pop_front ( ) {
683- return Some ( item) ;
684- }
685-
686- if * chunk_index >= chunks. len ( ) {
698+ if ( * left_chunk_index as usize ) >= iters. len ( ) {
687699 return None ;
688700 }
689-
690- // skip empty chunks
691- while * chunk_index < chunks. len ( ) && chunks[ * chunk_index] . 0 . is_empty ( ) {
692- * chunk_index += 1 ;
701+ if let Some ( ( byte_index, char) ) =
702+ iters[ * left_chunk_index as usize ] . next ( )
703+ {
704+ * last_left_indice = Some ( ( byte_index, char) ) ;
705+ Some ( ( byte_index + ( * left_byte_offset as usize ) , char) )
706+ } else {
707+ * left_chunk_index += 1 ;
708+ if let Some ( ( byte_index, char) ) = last_left_indice. take ( ) {
709+ * left_byte_offset =
710+ * left_byte_offset + byte_index as u32 + char. len_utf8 ( ) as u32 ;
711+ }
712+ self . next ( )
693713 }
714+ }
715+ }
716+ }
717+ }
694718
695- let ( chunk, start_pos) = chunks[ * chunk_index] ;
696-
697- char_indices
698- . extend ( chunk. char_indices ( ) . map ( |( i, c) | ( start_pos + i, c) ) ) ;
699- * chunk_index += 1 ;
700- char_indices. pop_front ( )
719+ impl DoubleEndedIterator for CharIndices < ' _ , ' _ > {
720+ fn next_back ( & mut self ) -> Option < Self :: Item > {
721+ match & mut self . iter {
722+ CharIndicesEnum :: Light { iter } => iter. next_back ( ) ,
723+ CharIndicesEnum :: Full {
724+ iters,
725+ right_chunk_index,
726+ right_byte_offset,
727+ right_byte_offset_for,
728+ ..
729+ } => {
730+ if let Some ( ( byte_index, char) ) =
731+ iters[ * right_chunk_index as usize ] . next_back ( )
732+ {
733+ if * right_byte_offset_for != * right_chunk_index {
734+ * right_byte_offset =
735+ * right_byte_offset - byte_index as u32 - char. len_utf8 ( ) as u32 ;
736+ * right_byte_offset_for = * right_chunk_index;
737+ }
738+ Some ( ( byte_index + ( * right_byte_offset as usize ) , char) )
739+ } else if * right_chunk_index > 0 {
740+ * right_chunk_index -= 1 ;
741+ self . next_back ( )
742+ } else {
743+ None
744+ }
701745 }
702746 }
703747 }
@@ -1168,6 +1212,29 @@ mod tests {
11681212 ) ;
11691213 }
11701214
1215+ #[ test]
1216+ fn reverse_char_indices ( ) {
1217+ let mut a = Rope :: new ( ) ;
1218+ a. add ( "abc" ) ;
1219+ a. add ( "def" ) ;
1220+ assert_eq ! (
1221+ a. char_indices( ) . rev( ) . collect:: <Vec <_>>( ) ,
1222+ "abcdef" . char_indices( ) . rev( ) . collect:: <Vec <_>>( )
1223+ ) ;
1224+
1225+ let mut a = Rope :: new ( ) ;
1226+ a. add ( "こんにちは" ) ;
1227+ assert_eq ! (
1228+ a. char_indices( ) . rev( ) . collect:: <Vec <_>>( ) ,
1229+ "こんにちは" . char_indices( ) . rev( ) . collect:: <Vec <_>>( )
1230+ ) ;
1231+ a. add ( "世界" ) ;
1232+ assert_eq ! (
1233+ a. char_indices( ) . rev( ) . collect:: <Vec <_>>( ) ,
1234+ "こんにちは世界" . char_indices( ) . rev( ) . collect:: <Vec <_>>( )
1235+ ) ;
1236+ }
1237+
11711238 #[ test]
11721239 fn lines1 ( ) {
11731240 let rope = Rope :: from ( "abc" ) ;
0 commit comments