@@ -509,7 +509,7 @@ impl<'a> Rope<'a> {
509
509
Lines {
510
510
iter : match & self . repr {
511
511
Repr :: Light ( s) => LinesEnum :: Light ( s) ,
512
- Repr :: Full ( data) => LinesEnum :: Complex {
512
+ Repr :: Full ( data) => LinesEnum :: Full {
513
513
iter : data,
514
514
in_chunk_byte_idx : 0 ,
515
515
chunk_idx : 0 ,
@@ -554,7 +554,7 @@ impl Hash for Rope<'_> {
554
554
555
555
enum LinesEnum < ' a , ' b > {
556
556
Light ( & ' b str ) ,
557
- Complex {
557
+ Full {
558
558
iter : & ' a Vec < ( & ' b str , usize ) > ,
559
559
in_chunk_byte_idx : usize ,
560
560
chunk_idx : usize ,
@@ -605,7 +605,7 @@ impl<'a> Iterator for Lines<'_, 'a> {
605
605
}
606
606
Lines {
607
607
iter :
608
- LinesEnum :: Complex {
608
+ LinesEnum :: Full {
609
609
iter : chunks,
610
610
ref mut in_chunk_byte_idx,
611
611
ref mut chunk_idx,
@@ -777,6 +777,38 @@ impl Iterator for CharIndices<'_, '_> {
777
777
}
778
778
}
779
779
}
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
+ }
780
812
}
781
813
782
814
impl Default for Rope < ' _ > {
@@ -1226,25 +1258,38 @@ mod tests {
1226
1258
1227
1259
#[ test]
1228
1260
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
+
1229
1268
let mut a = Rope :: new ( ) ;
1230
1269
a. add ( "abc" ) ;
1231
1270
a. add ( "def" ) ;
1232
1271
assert_eq ! (
1233
1272
a. char_indices( ) . collect:: <Vec <_>>( ) ,
1234
1273
"abcdef" . char_indices( ) . collect:: <Vec <_>>( )
1235
1274
) ;
1275
+ let len = "abcdef" . char_indices ( ) . size_hint ( ) . 1 . unwrap ( ) ;
1276
+ assert_eq ! ( a. char_indices( ) . size_hint( ) , ( lo!( len) , Some ( len) ) ) ;
1236
1277
1237
1278
let mut a = Rope :: new ( ) ;
1238
1279
a. add ( "こんにちは" ) ;
1239
1280
assert_eq ! (
1240
1281
a. char_indices( ) . collect:: <Vec <_>>( ) ,
1241
1282
"こんにちは" . char_indices( ) . collect:: <Vec <_>>( )
1242
1283
) ;
1284
+ let len = "こんにちは" . char_indices ( ) . size_hint ( ) . 1 . unwrap ( ) ;
1285
+ assert_eq ! ( a. char_indices( ) . size_hint( ) , ( lo!( len) , Some ( len) ) ) ;
1243
1286
a. add ( "世界" ) ;
1244
1287
assert_eq ! (
1245
1288
a. char_indices( ) . collect:: <Vec <_>>( ) ,
1246
1289
"こんにちは世界" . char_indices( ) . collect:: <Vec <_>>( )
1247
1290
) ;
1291
+ let len = "こんにちは世界" . char_indices ( ) . size_hint ( ) . 1 . unwrap ( ) ;
1292
+ assert_eq ! ( a. char_indices( ) . size_hint( ) , ( lo!( len) , Some ( len) ) ) ;
1248
1293
}
1249
1294
1250
1295
#[ test]
0 commit comments