use super::plan::{PartSource, PatchSourceKind, Region};
pub(crate) fn insert(regions: &mut Vec<Region>, incoming: Region) {
let start = incoming.target_offset;
let end = start.saturating_add(u64::from(incoming.length));
debug_assert!(end > start, "zero-length region must not be inserted");
let first = regions.partition_point(|r| region_end(r) <= start);
let last = regions.partition_point(|r| r.target_offset < end);
if first == last {
regions.insert(first, incoming);
return;
}
let head = {
let r = ®ions[first];
if r.target_offset < start {
let head_len = u32::try_from(start - r.target_offset)
.expect("head split fits in u32 because the original region.length did");
Some(truncate_right(r, head_len))
} else {
None
}
};
let tail = {
let r = ®ions[last - 1];
if region_end(r) > end {
let tail_skip = u32::try_from(end - r.target_offset)
.expect("tail split offset fits in u32 because the original region.length did");
Some(truncate_left(r, tail_skip))
} else {
None
}
};
match (head, tail) {
(None, None) => {
regions.splice(first..last, std::iter::once(incoming));
}
(Some(h), None) => {
regions.splice(first..last, [h, incoming]);
}
(None, Some(t)) => {
regions.splice(first..last, [incoming, t]);
}
(Some(h), Some(t)) => {
regions.splice(first..last, [h, incoming, t]);
}
}
}
#[inline]
fn region_end(r: &Region) -> u64 {
r.target_offset + u64::from(r.length)
}
fn truncate_right(r: &Region, new_len: u32) -> Region {
let source = match &r.source {
PartSource::Patch {
patch_idx,
offset,
kind,
decoded_skip,
} => {
let new_kind = match *kind {
PatchSourceKind::Raw { .. } => PatchSourceKind::Raw { len: new_len },
PatchSourceKind::Deflated {
compressed_len,
decompressed_len,
} => PatchSourceKind::Deflated {
compressed_len,
decompressed_len,
},
};
PartSource::Patch {
patch_idx: *patch_idx,
offset: *offset,
kind: new_kind,
decoded_skip: *decoded_skip,
}
}
other => other.clone(),
};
Region {
target_offset: r.target_offset,
length: new_len,
source,
expected: r.expected.clone(),
}
}
fn truncate_left(r: &Region, skip: u32) -> Region {
let source = match &r.source {
PartSource::Patch {
patch_idx,
offset,
kind,
decoded_skip,
} => match *kind {
PatchSourceKind::Raw { len } => PartSource::Patch {
patch_idx: *patch_idx,
offset: offset + u64::from(skip),
kind: PatchSourceKind::Raw {
len: len.saturating_sub(skip),
},
decoded_skip: *decoded_skip,
},
PatchSourceKind::Deflated {
compressed_len,
decompressed_len,
} => PartSource::Patch {
patch_idx: *patch_idx,
offset: *offset,
kind: PatchSourceKind::Deflated {
compressed_len,
decompressed_len,
},
decoded_skip: decoded_skip.saturating_add(u16::try_from(skip).unwrap_or(u16::MAX)),
},
},
other => other.clone(),
};
Region {
target_offset: r.target_offset + u64::from(skip),
length: r.length - skip,
source,
expected: r.expected.clone(),
}
}
#[cfg(test)]
mod tests {
use super::super::plan::{PartExpected, PartSource, PatchSourceKind, Region};
use super::*;
fn raw(offset: u64, len: u32, src_off: u64) -> Region {
Region {
target_offset: offset,
length: len,
source: PartSource::Patch {
patch_idx: 0,
offset: src_off,
kind: PatchSourceKind::Raw { len },
decoded_skip: 0,
},
expected: PartExpected::SizeOnly,
}
}
fn deflated(
offset: u64,
len: u32,
src_off: u64,
compressed_len: u32,
decompressed_len: u32,
) -> Region {
Region {
target_offset: offset,
length: len,
source: PartSource::Patch {
patch_idx: 0,
offset: src_off,
kind: PatchSourceKind::Deflated {
compressed_len,
decompressed_len,
},
decoded_skip: 0,
},
expected: PartExpected::SizeOnly,
}
}
fn zeros(offset: u64, len: u32) -> Region {
Region {
target_offset: offset,
length: len,
source: PartSource::Zeros,
expected: PartExpected::Zeros,
}
}
fn sorted_non_overlapping(regions: &[Region]) -> bool {
regions
.windows(2)
.all(|w| w[0].target_offset + u64::from(w[0].length) <= w[1].target_offset)
&& regions.iter().all(|r| r.length > 0)
}
#[test]
fn insert_into_empty_vec() {
let mut v = Vec::new();
insert(&mut v, raw(0, 100, 1000));
assert_eq!(v.len(), 1);
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[0].length, 100);
}
#[test]
fn append_disjoint_at_end() {
let mut v = vec![raw(0, 10, 1000)];
insert(&mut v, raw(20, 10, 2000));
assert_eq!(v.len(), 2);
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[1].target_offset, 20);
assert!(sorted_non_overlapping(&v));
}
#[test]
fn append_disjoint_at_start() {
let mut v = vec![raw(50, 10, 5000)];
insert(&mut v, raw(0, 10, 1000));
assert_eq!(v.len(), 2);
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[1].target_offset, 50);
assert!(sorted_non_overlapping(&v));
}
#[test]
fn touching_regions_are_disjoint() {
let mut v = vec![raw(0, 10, 1000)];
insert(&mut v, raw(10, 10, 2000));
assert_eq!(v.len(), 2);
assert!(sorted_non_overlapping(&v));
}
#[test]
fn exact_replace_one_region() {
let mut v = vec![raw(100, 50, 1000)];
insert(&mut v, zeros(100, 50));
assert_eq!(v.len(), 1);
assert_eq!(v[0].source, PartSource::Zeros);
assert_eq!(v[0].length, 50);
}
#[test]
fn overlap_left_truncates_existing_head_and_inserts_new() {
let mut v = vec![raw(50, 50, 1000)];
insert(&mut v, zeros(40, 30));
assert_eq!(v.len(), 2);
assert_eq!(v[0].target_offset, 40);
assert_eq!(v[0].length, 30);
assert_eq!(v[0].source, PartSource::Zeros);
assert_eq!(v[1].target_offset, 70);
assert_eq!(v[1].length, 30);
assert!(sorted_non_overlapping(&v));
}
#[test]
fn overlap_right_truncates_existing_tail_and_inserts_new() {
let mut v = vec![raw(50, 50, 1000)];
insert(&mut v, zeros(80, 40));
assert_eq!(v.len(), 2);
assert_eq!(v[0].target_offset, 50);
assert_eq!(v[0].length, 30);
assert_eq!(v[1].target_offset, 80);
assert_eq!(v[1].length, 40);
assert_eq!(v[1].source, PartSource::Zeros);
assert!(sorted_non_overlapping(&v));
}
#[test]
fn fully_contained_overwrite_splits_into_three() {
let mut v = vec![raw(0, 100, 1000)];
insert(&mut v, zeros(40, 20));
assert_eq!(v.len(), 3);
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[0].length, 40);
assert_eq!(v[1].target_offset, 40);
assert_eq!(v[1].length, 20);
assert_eq!(v[1].source, PartSource::Zeros);
assert_eq!(v[2].target_offset, 60);
assert_eq!(v[2].length, 40);
match &v[2].source {
PartSource::Patch {
offset,
kind,
decoded_skip,
..
} => {
assert_eq!(*offset, 1060);
assert_eq!(*kind, PatchSourceKind::Raw { len: 40 });
assert_eq!(*decoded_skip, 0, "Raw never uses decoded_skip");
}
other => panic!("expected Raw Patch tail, got {other:?}"),
}
match &v[0].source {
PartSource::Patch { offset, kind, .. } => {
assert_eq!(*offset, 1000);
assert_eq!(*kind, PatchSourceKind::Raw { len: 40 });
}
other => panic!("expected Raw Patch head, got {other:?}"),
}
assert!(sorted_non_overlapping(&v));
}
#[test]
fn fully_containing_overwrite_removes_contained() {
let mut v = vec![raw(40, 20, 5000)];
insert(&mut v, zeros(0, 100));
assert_eq!(v.len(), 1);
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[0].length, 100);
assert_eq!(v[0].source, PartSource::Zeros);
}
#[test]
fn fully_containing_overwrite_removes_multiple() {
let mut v = vec![raw(10, 10, 1000), raw(30, 10, 2000), raw(50, 10, 3000)];
insert(&mut v, zeros(0, 100));
assert_eq!(v.len(), 1);
assert_eq!(v[0].length, 100);
}
#[test]
fn truncate_right_raw_shrinks_kind_len() {
let mut v = vec![raw(0, 100, 1000)];
insert(&mut v, zeros(50, 50));
assert_eq!(v.len(), 2);
assert_eq!(v[0].length, 50);
match &v[0].source {
PartSource::Patch { offset, kind, .. } => {
assert_eq!(*offset, 1000);
assert_eq!(*kind, PatchSourceKind::Raw { len: 50 });
}
other => panic!("expected Raw Patch head, got {other:?}"),
}
}
#[test]
fn truncate_left_on_deflated_advances_decoded_skip_not_offset() {
let mut v = vec![deflated(0, 100, 2000, 50, 100)];
insert(&mut v, zeros(0, 30));
assert_eq!(v.len(), 2);
assert_eq!(v[1].target_offset, 30);
assert_eq!(v[1].length, 70);
match &v[1].source {
PartSource::Patch {
offset,
kind,
decoded_skip,
..
} => {
assert_eq!(*offset, 2000);
assert_eq!(
*kind,
PatchSourceKind::Deflated {
compressed_len: 50,
decompressed_len: 100,
}
);
assert_eq!(*decoded_skip, 30);
}
other => panic!("expected Deflated Patch tail, got {other:?}"),
}
}
#[test]
fn truncate_right_on_deflated_keeps_block_metadata() {
let mut v = vec![deflated(0, 100, 2000, 50, 100)];
insert(&mut v, zeros(50, 50));
assert_eq!(v.len(), 2);
assert_eq!(v[0].length, 50);
match &v[0].source {
PartSource::Patch {
offset,
kind,
decoded_skip,
..
} => {
assert_eq!(*offset, 2000);
assert_eq!(
*kind,
PatchSourceKind::Deflated {
compressed_len: 50,
decompressed_len: 100,
}
);
assert_eq!(*decoded_skip, 0);
}
other => panic!("expected Deflated Patch head, got {other:?}"),
}
}
#[test]
fn deflated_split_across_both_sides_preserves_block_metadata() {
let mut v = vec![deflated(0, 100, 2000, 50, 100)];
insert(&mut v, zeros(40, 20));
assert_eq!(v.len(), 3);
match &v[0].source {
PartSource::Patch {
kind, decoded_skip, ..
} => {
assert_eq!(
*kind,
PatchSourceKind::Deflated {
compressed_len: 50,
decompressed_len: 100,
}
);
assert_eq!(*decoded_skip, 0);
}
other => panic!("expected Deflated head, got {other:?}"),
}
match &v[2].source {
PartSource::Patch {
kind, decoded_skip, ..
} => {
assert_eq!(
*kind,
PatchSourceKind::Deflated {
compressed_len: 50,
decompressed_len: 100,
}
);
assert_eq!(*decoded_skip, 60);
}
other => panic!("expected Deflated tail, got {other:?}"),
}
}
fn empty_block(offset: u64, units: u32) -> Region {
Region {
target_offset: offset,
length: units * 128,
source: PartSource::EmptyBlock { units },
expected: PartExpected::EmptyBlock { units },
}
}
#[test]
fn single_byte_raw_fully_contained_splits_existing_into_three() {
let mut v = vec![raw(0, 100, 1000)];
insert(&mut v, raw(50, 1, 9_000));
assert_eq!(v.len(), 3, "1-byte overlay must split into 3 regions");
assert!(sorted_non_overlapping(&v));
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[0].length, 50);
assert_eq!(v[1].target_offset, 50);
assert_eq!(v[1].length, 1);
assert_eq!(v[2].target_offset, 51);
assert_eq!(v[2].length, 49);
match &v[2].source {
PartSource::Patch { offset, kind, .. } => {
assert_eq!(*offset, 1051);
assert_eq!(*kind, PatchSourceKind::Raw { len: 49 });
}
other => panic!("expected Raw Patch tail, got {other:?}"),
}
}
#[test]
fn single_byte_zeros_fully_contained_splits_existing_into_three() {
let mut v = vec![raw(0, 100, 1000)];
insert(&mut v, zeros(50, 1));
assert_eq!(v.len(), 3);
assert!(sorted_non_overlapping(&v));
assert_eq!(v[1].length, 1);
assert_eq!(v[1].source, PartSource::Zeros);
assert_eq!(v[2].target_offset, 51);
assert_eq!(v[2].length, 49);
}
#[test]
fn single_byte_empty_block_fully_contained_splits_existing_into_three() {
let mut v = vec![raw(0, 256, 1000)];
insert(&mut v, empty_block(100, 1)); assert_eq!(v.len(), 3);
assert!(sorted_non_overlapping(&v));
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[0].length, 100);
assert_eq!(v[1].target_offset, 100);
assert_eq!(v[1].length, 128);
assert!(matches!(v[1].source, PartSource::EmptyBlock { units: 1 }));
assert_eq!(v[2].target_offset, 228);
assert_eq!(v[2].length, 28);
}
#[test]
fn overlap_spans_multiple_with_truncation_on_both_sides() {
let mut v = vec![raw(0, 50, 1000), raw(60, 30, 2000), raw(100, 50, 3000)];
insert(&mut v, zeros(30, 90));
assert_eq!(v.len(), 3);
assert_eq!(v[0].target_offset, 0);
assert_eq!(v[0].length, 30);
assert_eq!(v[1].target_offset, 30);
assert_eq!(v[1].length, 90);
assert_eq!(v[1].source, PartSource::Zeros);
assert_eq!(v[2].target_offset, 120);
assert_eq!(v[2].length, 30);
match &v[2].source {
PartSource::Patch { offset, kind, .. } => {
assert_eq!(*offset, 3020);
assert_eq!(*kind, PatchSourceKind::Raw { len: 30 });
}
other => panic!("expected Raw Patch tail, got {other:?}"),
}
assert!(sorted_non_overlapping(&v));
}
}