Skip to content

Commit ed2419c

Browse files
authored
more rusty (#42)
1 parent 3aee889 commit ed2419c

2 files changed

Lines changed: 43 additions & 35 deletions

File tree

utils/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
quickcheck = "1.0.3"
9+
10+
[dev-dependencies]
11+
quickcheck = "1.0.3"

utils/src/lib.rs

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,56 @@
11
use std::iter;
22

3-
const HEADER_SIZE: usize = 16;
3+
const GAP: usize = 16;
44

55
pub fn get_diff<'a>(
66
new_page: &'a [u8],
77
old_page: &'a [u8],
88
) -> impl Iterator<Item = (usize, &'a [u8])> + 'a {
9-
let l = new_page.len();
10-
let o = old_page.len();
11-
12-
let mut offset = 0;
13-
let mut offset_end = 0;
14-
15-
old_page
9+
let iter = old_page
1610
.iter()
1711
.chain(iter::repeat::<&u8>(&0))
1812
.zip(new_page)
19-
.enumerate()
20-
.filter_map(move |(i, values)| {
21-
if values.0 == values.1 {
22-
// if this value matches and the previous one did not, we know we just passed the end of one or more
23-
// values that didn't match. In that case, we note the position by setting `offset_end` to `i`
24-
if i != 0 && ((i < o && new_page[i - 1] != old_page[i - 1]) || i >= o && new_page[i - 1] != 0) {
25-
offset_end = i;
26-
}
27-
// if we're HEADER_SIZE past the last section that needs changing, or at the end, we need to return the last blob of changes
28-
if offset != offset_end && (offset_end + HEADER_SIZE == i || (i == (l - 1) && offset_end + HEADER_SIZE > i))
29-
{
30-
return Some((offset, &new_page[offset..offset_end]));
31-
}
32-
} else {
33-
// if this value doesn't match but the previous one did, we know we're at the beginning of one or more
34-
// values that don't match. we note the position by updating `offset` to `i`.
35-
if i == 0 || ((i < o && new_page[i - 1] == old_page[i - 1]) || i >= o && new_page[i-1] == 0) {
36-
if offset_end == 0 || offset_end + HEADER_SIZE < i {
37-
offset = i;
13+
.map(|(&old, &new)| (old, new))
14+
.enumerate();
15+
16+
Diff {
17+
iter,
18+
gap: GAP,
19+
range: None,
20+
}
21+
.map(|(start, end)| (start, &new_page[start..=end]))
22+
}
23+
24+
pub struct Diff<I> {
25+
iter: I,
26+
gap: usize,
27+
range: Option<(usize, usize)>,
28+
}
29+
30+
impl<I> Iterator for Diff<I>
31+
where
32+
I: Iterator<Item = (usize, (u8, u8))>,
33+
{
34+
type Item = (usize, usize);
35+
fn next(&mut self) -> Option<Self::Item> {
36+
while let Some(item) = self.iter.next() {
37+
match item {
38+
(i, (old, new)) if old != new => {
39+
self.range = match self.range {
40+
None => Some((i, i)),
41+
Some((start, _)) => Some((start, i)),
3842
}
3943
}
40-
// normally, we add the values that need to be changed as soon as we see a matching value again, but
41-
// when we're on the last value that doesn't match, we need to have special handing to include it.
42-
if i == (l - 1) {
43-
return Some((offset, &new_page[offset..=i]));
44-
}
44+
(i, _) => match self.range {
45+
Some((_, end)) if end + self.gap < i => {
46+
return self.range.take();
47+
}
48+
_ => {}
49+
},
4550
}
46-
None
47-
})
51+
}
52+
self.range.take()
53+
}
4854
}
4955

5056
#[cfg(test)]

0 commit comments

Comments
 (0)