weavatrix_edit/application/
stream.rs1use std::iter::FusedIterator;
2
3use super::PreparedEdit;
4
5#[derive(Clone, Debug)]
10pub struct EditChunks<'prepared> {
11 source: &'prepared str,
12 edits: &'prepared [PreparedEdit],
13 edit_index: usize,
14 cursor: usize,
15 finished: bool,
16}
17
18impl<'prepared> EditChunks<'prepared> {
19 pub(super) const fn new(source: &'prepared str, edits: &'prepared [PreparedEdit]) -> Self {
20 Self {
21 source,
22 edits,
23 edit_index: 0,
24 cursor: 0,
25 finished: false,
26 }
27 }
28}
29
30impl<'prepared> Iterator for EditChunks<'prepared> {
31 type Item = &'prepared str;
32
33 fn next(&mut self) -> Option<Self::Item> {
34 loop {
35 if let Some(edit) = self.edits.get(self.edit_index) {
36 if self.cursor < edit.start {
37 let unchanged = &self.source[self.cursor..edit.start];
38 self.cursor = edit.start;
39 return Some(unchanged);
40 }
41 self.edit_index += 1;
42 self.cursor = self.cursor.max(edit.end);
43 if !edit.after.is_empty() {
44 return Some(&edit.after);
45 }
46 continue;
47 }
48 if self.finished {
49 return None;
50 }
51 self.finished = true;
52 if self.cursor < self.source.len() {
53 return Some(&self.source[self.cursor..]);
54 }
55 }
56 }
57
58 fn size_hint(&self) -> (usize, Option<usize>) {
59 let edits_left = self.edits.len().saturating_sub(self.edit_index);
60 (
61 0,
62 edits_left
63 .checked_mul(2)
64 .and_then(|size| size.checked_add(1)),
65 )
66 }
67}
68
69impl FusedIterator for EditChunks<'_> {}