Skip to content

Commit f10038d

Browse files
committed
perf: ReplaceSourceRopeIterator
1 parent 34505cb commit f10038d

File tree

1 file changed

+87
-141
lines changed

1 file changed

+87
-141
lines changed

src/replace_source.rs

Lines changed: 87 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -924,15 +924,14 @@ pub struct ReplaceSourceRopeIterator<'a> {
924924
current_chunk: Option<&'a str>,
925925
current_chunk_start: usize,
926926
current_chunk_pos: usize,
927-
state: IteratorState,
928927
}
929928

930929
impl<'a> ReplaceSourceRopeIterator<'a> {
931930
fn new(
932931
inner_chunks: Box<dyn Iterator<Item = &'a str> + 'a>,
933932
replacements: &'a [Replacement],
934933
) -> Self {
935-
let mut iter = Self {
934+
Self {
936935
inner_chunks,
937936
replacements,
938937
pos: 0,
@@ -942,166 +941,113 @@ impl<'a> ReplaceSourceRopeIterator<'a> {
942941
current_chunk: None,
943942
current_chunk_start: 0,
944943
current_chunk_pos: 0,
945-
state: IteratorState::ProcessingChunk,
946-
};
947-
948-
iter.load_next_chunk();
949-
iter
950-
}
951-
952-
fn load_next_chunk(&mut self) {
953-
self.current_chunk = self.inner_chunks.next();
954-
self.current_chunk_pos = 0;
955-
if self.current_chunk.is_some() {
956-
self.current_chunk_start = self.pos;
957-
} else {
958-
self.state = IteratorState::FinalReplacements;
959944
}
960945
}
946+
}
961947

962-
fn skip_replaced_content(&mut self) -> bool {
963-
if let Some(replacement_end) = self.replacement_end {
964-
if replacement_end > self.pos {
965-
let chunk_end =
966-
self.current_chunk_start + self.current_chunk.unwrap().len();
948+
impl<'a> Iterator for ReplaceSourceRopeIterator<'a> {
949+
type Item = &'a str;
967950

968-
// Skip the entire chunk
969-
if replacement_end >= chunk_end {
970-
self.pos = chunk_end;
971-
self.load_next_chunk();
972-
return true;
951+
fn next(&mut self) -> Option<Self::Item> {
952+
loop {
953+
// 加载下一个chunk(如果需要)
954+
if self.current_chunk.is_none() {
955+
self.current_chunk = self.inner_chunks.next();
956+
self.current_chunk_pos = 0;
957+
if let Some(chunk) = self.current_chunk {
958+
self.current_chunk_start = self.pos;
959+
} else {
960+
// 没有更多chunk,处理剩余的替换
961+
return if self.replacement_idx < self.replacements.len() {
962+
let content = &self.replacements[self.replacement_idx].content;
963+
self.replacement_idx += 1;
964+
Some(content)
965+
} else {
966+
None
967+
};
973968
}
974-
975-
// Partially skip the chunk
976-
let skip_len = replacement_end - self.pos;
977-
self.current_chunk_pos += skip_len;
978-
self.pos += skip_len;
979969
}
980-
}
981-
false
982-
}
983-
984-
fn process_current_chunk(&mut self) -> Option<&'a str> {
985-
let chunk = self.current_chunk?;
986-
let chunk_end = self.current_chunk_start + chunk.len();
987-
988-
// Check if there are replacements in the current chunk
989-
while let Some(next_repl_pos) =
990-
self.next_replacement.filter(|&pos| pos < chunk_end)
991-
{
992-
if next_repl_pos > self.pos {
993-
// Return content before replacement
994-
let offset = next_repl_pos - self.pos;
995-
let result =
996-
&chunk[self.current_chunk_pos..self.current_chunk_pos + offset];
997-
self.current_chunk_pos += offset;
998-
self.pos = next_repl_pos;
999-
return Some(result);
1000-
}
1001-
1002-
// Prepare to return replacement content
1003-
self.state = IteratorState::EmittingReplacement;
1004-
return None;
1005-
}
1006-
1007-
// Return remaining content of the chunk
1008-
if self.current_chunk_pos < chunk.len() {
1009-
let result = &chunk[self.current_chunk_pos..];
1010-
self.pos = chunk_end;
1011-
self.load_next_chunk();
1012-
Some(result)
1013-
} else {
1014-
self.load_next_chunk();
1015-
None
1016-
}
1017-
}
1018-
1019-
fn emit_replacement(&mut self) -> Option<&'a str> {
1020-
let replacement = &self.replacements[self.replacement_idx];
1021-
let content = &replacement.content;
1022-
1023-
// Update replacement state
1024-
self.replacement_end = Some(
1025-
self
1026-
.replacement_end
1027-
.map_or(replacement.end as usize, |end| {
1028-
end.max(replacement.end as usize)
1029-
}),
1030-
);
1031970

1032-
self.replacement_idx += 1;
1033-
self.next_replacement = self
1034-
.replacements
1035-
.get(self.replacement_idx)
1036-
.map(|r| r.start as usize);
971+
let chunk = self.current_chunk.unwrap();
972+
let chunk_end = self.current_chunk_start + chunk.len();
1037973

1038-
// Check if we need to skip replaced content
1039-
if let Some(replacement_end) = self.replacement_end {
1040-
if replacement_end > self.pos {
1041-
self.pos = replacement_end;
1042-
1043-
// If current chunk needs to be skipped, reload it
1044-
if let Some(chunk) = self.current_chunk {
1045-
let chunk_end = self.current_chunk_start + chunk.len();
974+
// 跳过被替换的内容
975+
if let Some(replacement_end) = self.replacement_end {
976+
if replacement_end > self.pos {
1046977
if replacement_end >= chunk_end {
1047-
self.load_next_chunk();
978+
// 跳过整个chunk
979+
self.pos = chunk_end;
980+
self.current_chunk = None;
981+
continue;
1048982
} else {
1049-
self.current_chunk_pos = replacement_end - self.current_chunk_start;
983+
// 部分跳过chunk
984+
let skip_len = replacement_end - self.pos;
985+
self.current_chunk_pos += skip_len;
986+
self.pos += skip_len;
1050987
}
1051988
}
1052989
}
1053-
}
1054-
1055-
self.state = IteratorState::ProcessingChunk;
1056-
Some(content)
1057-
}
1058-
1059-
fn emit_final_replacements(&mut self) -> Option<&'a str> {
1060-
if self.replacement_idx < self.replacements.len() {
1061-
let content = &self.replacements[self.replacement_idx].content;
1062-
self.replacement_idx += 1;
1063-
Some(content)
1064-
} else {
1065-
self.state = IteratorState::Done;
1066-
None
1067-
}
1068-
}
1069-
}
1070-
1071-
impl<'a> Iterator for ReplaceSourceRopeIterator<'a> {
1072-
type Item = &'a str;
1073-
1074-
fn next(&mut self) -> Option<Self::Item> {
1075-
loop {
1076-
match self.state {
1077-
IteratorState::ProcessingChunk => {
1078-
if self.skip_replaced_content() {
1079-
continue;
1080-
}
1081-
1082-
if let Some(result) = self.process_current_chunk() {
1083-
return Some(result);
1084-
}
1085990

1086-
if self.current_chunk.is_none() {
1087-
self.state = IteratorState::FinalReplacements;
1088-
}
991+
// 检查当前chunk中是否有替换
992+
if let Some(next_repl_pos) =
993+
self.next_replacement.filter(|&pos| pos < chunk_end)
994+
{
995+
if next_repl_pos > self.pos {
996+
// 返回替换前的内容
997+
let offset = next_repl_pos - self.pos;
998+
let result =
999+
&chunk[self.current_chunk_pos..self.current_chunk_pos + offset];
1000+
self.current_chunk_pos += offset;
1001+
self.pos = next_repl_pos;
1002+
return Some(result);
10891003
}
10901004

1091-
IteratorState::EmittingReplacement => {
1092-
if let Some(result) = self.emit_replacement() {
1093-
return Some(result);
1094-
}
1095-
}
1005+
// 处理替换
1006+
let replacement = &self.replacements[self.replacement_idx];
1007+
let content = &replacement.content;
1008+
1009+
// 更新替换结束位置
1010+
self.replacement_end = Some(
1011+
self
1012+
.replacement_end
1013+
.map_or(replacement.end as usize, |end| {
1014+
end.max(replacement.end as usize)
1015+
}),
1016+
);
10961017

1097-
IteratorState::FinalReplacements => {
1098-
if let Some(result) = self.emit_final_replacements() {
1099-
return Some(result);
1018+
// 移动到下一个替换
1019+
self.replacement_idx += 1;
1020+
self.next_replacement = self
1021+
.replacements
1022+
.get(self.replacement_idx)
1023+
.map(|r| r.start as usize);
1024+
1025+
// 更新位置(跳过被替换的内容)
1026+
if let Some(replacement_end) = self.replacement_end {
1027+
if replacement_end > self.pos {
1028+
self.pos = replacement_end;
1029+
// 如果当前chunk需要被跳过,重置它
1030+
if replacement_end >= chunk_end {
1031+
self.current_chunk = None;
1032+
} else {
1033+
self.current_chunk_pos =
1034+
replacement_end - self.current_chunk_start;
1035+
}
11001036
}
11011037
}
11021038

1103-
IteratorState::Done => return None,
1039+
return Some(content);
11041040
}
1041+
1042+
// 返回chunk的剩余内容
1043+
if self.current_chunk_pos < chunk.len() {
1044+
let result = &chunk[self.current_chunk_pos..];
1045+
self.pos = chunk_end;
1046+
self.current_chunk = None;
1047+
return Some(result);
1048+
}
1049+
1050+
self.current_chunk = None;
11051051
}
11061052
}
11071053
}

0 commit comments

Comments
 (0)