@@ -509,7 +509,7 @@ impl<'a> Rope<'a> {
509509 Lines {
510510 iter : match & self . repr {
511511 Repr :: Light ( s) => LinesEnum :: Light ( s) ,
512- Repr :: Full ( data) => LinesEnum :: Complex {
512+ Repr :: Full ( data) => LinesEnum :: Full {
513513 iter : data,
514514 in_chunk_byte_idx : 0 ,
515515 chunk_idx : 0 ,
@@ -554,7 +554,7 @@ impl Hash for Rope<'_> {
554554
555555enum LinesEnum < ' a , ' b > {
556556 Light ( & ' b str ) ,
557- Complex {
557+ Full {
558558 iter : & ' a Vec < ( & ' b str , usize ) > ,
559559 in_chunk_byte_idx : usize ,
560560 chunk_idx : usize ,
@@ -605,7 +605,7 @@ impl<'a> Iterator for Lines<'_, 'a> {
605605 }
606606 Lines {
607607 iter :
608- LinesEnum :: Complex {
608+ LinesEnum :: Full {
609609 iter : chunks,
610610 ref mut in_chunk_byte_idx,
611611 ref mut chunk_idx,
@@ -777,6 +777,38 @@ impl Iterator for CharIndices<'_, '_> {
777777 }
778778 }
779779 }
780+
781+ #[ inline]
782+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
783+ match & self . iter {
784+ CharIndicesEnum :: Light { iter } => ( 0 , None ) ,
785+ CharIndicesEnum :: Full {
786+ chunks,
787+ char_indices,
788+ chunk_index,
789+ } => {
790+ if * chunk_index >= chunks. len ( ) {
791+ if char_indices. is_empty ( ) {
792+ return ( 0 , Some ( 0 ) ) ;
793+ }
794+ return ( char_indices. len ( ) , Some ( char_indices. len ( ) ) ) ;
795+ }
796+
797+ let Some ( total) = chunks. last ( ) . map ( |( s, l) | * l + s. len ( ) ) else {
798+ return ( 0 , Some ( 0 ) ) ;
799+ } ;
800+
801+ let ( _, prev) = chunks[ * chunk_index] ;
802+ // SAFETY: The previous length is guaranteed be less than or equal to the latter one.
803+ let remaining = total - prev;
804+
805+ (
806+ ( remaining + 3 ) / 4 + char_indices. len ( ) ,
807+ Some ( remaining + char_indices. len ( ) ) ,
808+ )
809+ }
810+ }
811+ }
780812}
781813
782814impl Default for Rope < ' _ > {
@@ -1226,25 +1258,38 @@ mod tests {
12261258
12271259 #[ test]
12281260 fn char_indices ( ) {
1261+ // The algorithm is the same as the one used in `std::str::CharIndices::size_hint`.
1262+ macro_rules! lo {
1263+ ( $expr: expr) => {
1264+ ( $expr + 3 ) / 4
1265+ } ;
1266+ }
1267+
12291268 let mut a = Rope :: new ( ) ;
12301269 a. add ( "abc" ) ;
12311270 a. add ( "def" ) ;
12321271 assert_eq ! (
12331272 a. char_indices( ) . collect:: <Vec <_>>( ) ,
12341273 "abcdef" . char_indices( ) . collect:: <Vec <_>>( )
12351274 ) ;
1275+ let len = "abcdef" . char_indices ( ) . size_hint ( ) . 1 . unwrap ( ) ;
1276+ assert_eq ! ( a. char_indices( ) . size_hint( ) , ( lo!( len) , Some ( len) ) ) ;
12361277
12371278 let mut a = Rope :: new ( ) ;
12381279 a. add ( "こんにちは" ) ;
12391280 assert_eq ! (
12401281 a. char_indices( ) . collect:: <Vec <_>>( ) ,
12411282 "こんにちは" . char_indices( ) . collect:: <Vec <_>>( )
12421283 ) ;
1284+ let len = "こんにちは" . char_indices ( ) . size_hint ( ) . 1 . unwrap ( ) ;
1285+ assert_eq ! ( a. char_indices( ) . size_hint( ) , ( lo!( len) , Some ( len) ) ) ;
12431286 a. add ( "世界" ) ;
12441287 assert_eq ! (
12451288 a. char_indices( ) . collect:: <Vec <_>>( ) ,
12461289 "こんにちは世界" . char_indices( ) . collect:: <Vec <_>>( )
12471290 ) ;
1291+ let len = "こんにちは世界" . char_indices ( ) . size_hint ( ) . 1 . unwrap ( ) ;
1292+ assert_eq ! ( a. char_indices( ) . size_hint( ) , ( lo!( len) , Some ( len) ) ) ;
12481293 }
12491294
12501295 #[ test]
0 commit comments