Skip to content

Commit d0c2d45

Browse files
committed
perf: add size_hint for rope CharIndices
1 parent 739d6a7 commit d0c2d45

File tree

1 file changed

+49
-3
lines changed

1 file changed

+49
-3
lines changed

src/rope.rs

+49-3
Original file line numberDiff line numberDiff line change
@@ -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

555555
enum 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,39 @@ impl Iterator for CharIndices<'_, '_> {
777777
}
778778
}
779779
}
780+
781+
#[inline(always)]
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+
(0, None)
791+
// if *chunk_index >= chunks.len() {
792+
// if char_indices.is_empty() {
793+
// return (0, Some(0));
794+
// }
795+
// return (char_indices.len(), Some(char_indices.len()));
796+
// }
797+
//
798+
// let Some(total) = chunks.last().map(|(s, l)| *l + s.len()) else {
799+
// return (0, Some(0));
800+
// };
801+
//
802+
// let (_, prev) = chunks[*chunk_index];
803+
// // SAFETY: The previous length is guaranteed be less than or equal to the latter one.
804+
// let remaining = total - prev;
805+
//
806+
// (
807+
// (remaining + 3) / 4 + char_indices.len(),
808+
// Some(remaining + char_indices.len()),
809+
// )
810+
}
811+
}
812+
}
780813
}
781814

782815
impl Default for Rope<'_> {
@@ -1226,25 +1259,38 @@ mod tests {
12261259

12271260
#[test]
12281261
fn char_indices() {
1262+
// The algorithm is the same as the one used in `std::str::CharIndices::size_hint`.
1263+
macro_rules! lo {
1264+
($expr:expr) => {
1265+
($expr + 3) / 4
1266+
};
1267+
}
1268+
12291269
let mut a = Rope::new();
12301270
a.add("abc");
12311271
a.add("def");
12321272
assert_eq!(
12331273
a.char_indices().collect::<Vec<_>>(),
12341274
"abcdef".char_indices().collect::<Vec<_>>()
12351275
);
1276+
let len = "abcdef".char_indices().size_hint().1.unwrap();
1277+
assert_eq!(a.char_indices().size_hint(), (lo!(len), Some(len)));
12361278

12371279
let mut a = Rope::new();
12381280
a.add("こんにちは");
12391281
assert_eq!(
12401282
a.char_indices().collect::<Vec<_>>(),
12411283
"こんにちは".char_indices().collect::<Vec<_>>()
12421284
);
1285+
let len = "こんにちは".char_indices().size_hint().1.unwrap();
1286+
assert_eq!(a.char_indices().size_hint(), (lo!(len), Some(len)));
12431287
a.add("世界");
12441288
assert_eq!(
12451289
a.char_indices().collect::<Vec<_>>(),
12461290
"こんにちは世界".char_indices().collect::<Vec<_>>()
12471291
);
1292+
let len = "こんにちは世界".char_indices().size_hint().1.unwrap();
1293+
assert_eq!(a.char_indices().size_hint(), (lo!(len), Some(len)));
12481294
}
12491295

12501296
#[test]

0 commit comments

Comments
 (0)