use crate::WriteRequest;
use off64::u64;
use off64::usz;
use std::collections::BTreeMap;
pub fn merge_overlapping_writes<D: AsRef<[u8]> + Send + 'static>(
writes: impl IntoIterator<Item = WriteRequest<D>>,
) -> BTreeMap<u64, (u64, Vec<u8>)> {
let mut intervals: BTreeMap<u64, (u64, Vec<u8>)> = BTreeMap::new();
for w in writes {
let data = w.data.as_ref();
let offset = w.offset;
let end = offset + u64!(data.len());
let overlapping_keys: Vec<u64> = intervals
.range(..end)
.filter(|(_, &(old_end, _))| old_end > offset)
.map(|(&start, _)| start)
.collect();
let mut to_insert = Vec::new();
for key in overlapping_keys {
let (old_end, old_data) = intervals.remove(&key).unwrap();
if key < offset {
let preserved_len = usz!(offset - key);
to_insert.push((key, offset, old_data[..preserved_len].to_vec()));
}
if old_end > end {
let skip_len = usz!(end - key);
to_insert.push((end, old_end, old_data[skip_len..].to_vec()));
}
}
to_insert.push((offset, end, data.to_vec()));
for (start, end, data) in to_insert {
intervals.insert(start, (end, data));
}
}
intervals
}
#[cfg(test)]
mod tests {
use super::*;
fn wr(offset: u64, data: Vec<u8>) -> WriteRequest<Vec<u8>> {
WriteRequest::new(offset, data)
}
fn assert_intervals(intervals: &BTreeMap<u64, (u64, Vec<u8>)>, expected: &[(u64, u64, Vec<u8>)]) {
let actual: Vec<_> = intervals
.iter()
.map(|(&start, &(end, ref data))| (start, end, data.clone()))
.collect();
assert_eq!(
actual, expected,
"\nActual intervals: {:?}\nExpected intervals: {:?}",
actual, expected
);
}
#[test]
fn test_merge_no_writes() {
let writes: Vec<WriteRequest<Vec<u8>>> = vec![];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[]);
}
#[test]
fn test_merge_single_write() {
let writes = vec![wr(10, vec![1, 2, 3, 4])];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(10, 14, vec![1, 2, 3, 4])]);
}
#[test]
fn test_merge_non_overlapping_sequential() {
let writes = vec![wr(0, vec![1, 2]), wr(2, vec![3, 4]), wr(4, vec![5, 6])];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 2, vec![1, 2]),
(2, 4, vec![3, 4]),
(4, 6, vec![5, 6]),
]);
}
#[test]
fn test_merge_non_overlapping_gaps() {
let writes = vec![wr(0, vec![1, 2]), wr(10, vec![3, 4]), wr(20, vec![5, 6])];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 2, vec![1, 2]),
(10, 12, vec![3, 4]),
(20, 22, vec![5, 6]),
]);
}
#[test]
fn test_merge_complete_overlap_later_wins() {
let writes = vec![
wr(0, vec![1, 2, 3, 4]),
wr(0, vec![5, 6, 7, 8]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(0, 4, vec![5, 6, 7, 8])]);
}
#[test]
fn test_merge_partial_overlap_at_end() {
let writes = vec![
wr(0, vec![1, 2, 3, 4]), wr(2, vec![5, 6]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(0, 2, vec![1, 2]), (2, 4, vec![5, 6])]);
}
#[test]
fn test_merge_partial_overlap_at_start() {
let writes = vec![
wr(2, vec![1, 2, 3, 4]), wr(0, vec![5, 6]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(0, 2, vec![5, 6]), (2, 6, vec![1, 2, 3, 4])]);
}
#[test]
fn test_merge_write_inside_another() {
let writes = vec![
wr(0, vec![1, 2, 3, 4, 5, 6]), wr(2, vec![7, 8]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 2, vec![1, 2]),
(2, 4, vec![7, 8]),
(4, 6, vec![5, 6]),
]);
}
#[test]
fn test_merge_write_spans_multiple() {
let writes = vec![
wr(0, vec![1, 2]),
wr(2, vec![3, 4]),
wr(4, vec![5, 6]),
wr(1, vec![7, 8, 9, 10, 11]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(0, 1, vec![1]), (1, 6, vec![7, 8, 9, 10, 11])]);
}
#[test]
fn test_merge_multiple_overlaps_later_wins() {
let writes = vec![
wr(0, vec![1, 2, 3, 4]),
wr(1, vec![5, 6]), wr(2, vec![7, 8]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 1, vec![1]),
(1, 2, vec![5]),
(2, 4, vec![7, 8]),
]);
}
#[test]
fn test_merge_identical_offsets_later_wins() {
let writes = vec![
wr(5, vec![1, 2, 3]),
wr(5, vec![4, 5, 6]),
wr(5, vec![7, 8, 9]),
];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(5, 8, vec![7, 8, 9])]);
}
#[test]
fn test_merge_complex_overlapping_sequence() {
let writes = vec![
wr(0, vec![1, 2, 3, 4, 5]), wr(3, vec![6, 7, 8, 9]), wr(1, vec![10, 11]), wr(6, vec![12, 13, 14]), wr(2, vec![15]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 1, vec![1]),
(1, 2, vec![10]),
(2, 3, vec![15]),
(3, 6, vec![6, 7, 8]),
(6, 9, vec![12, 13, 14]),
]);
}
#[test]
fn test_merge_zero_length_not_supported() {
let writes = vec![
wr(5, vec![1, 2, 3]),
wr(10, vec![]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(5, 8, vec![1, 2, 3]), (10, 10, vec![])]);
}
#[test]
fn test_merge_out_of_order_offsets() {
let writes = vec![wr(20, vec![5, 6]), wr(0, vec![1, 2]), wr(10, vec![3, 4])];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 2, vec![1, 2]),
(10, 12, vec![3, 4]),
(20, 22, vec![5, 6]),
]);
}
#[test]
fn test_merge_adjacent_not_merged() {
let writes = vec![
wr(0, vec![1, 2]),
wr(2, vec![3, 4]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(0, 2, vec![1, 2]), (2, 4, vec![3, 4])]);
}
#[test]
fn test_merge_large_span_over_many_small() {
let writes = vec![
wr(0, vec![1]),
wr(2, vec![2]),
wr(4, vec![3]),
wr(6, vec![4]),
wr(8, vec![5]),
wr(1, vec![10, 11, 12, 13, 14, 15, 16, 17]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 1, vec![1]),
(1, 9, vec![10, 11, 12, 13, 14, 15, 16, 17]),
]);
}
#[test]
fn test_merge_write_extends_left() {
let writes = vec![
wr(10, vec![1, 2, 3, 4]),
wr(5, vec![5, 6, 7, 8, 9, 10]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(5, 11, vec![5, 6, 7, 8, 9, 10]),
(11, 14, vec![2, 3, 4]),
]);
}
#[test]
fn test_merge_write_extends_right() {
let writes = vec![
wr(5, vec![1, 2, 3, 4]),
wr(7, vec![5, 6, 7, 8, 9]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(5, 7, vec![1, 2]), (7, 12, vec![5, 6, 7, 8, 9])]);
}
#[test]
fn test_merge_alternating_overlaps() {
let writes = vec![
wr(0, vec![1, 2, 3]),
wr(2, vec![4, 5, 6]),
wr(4, vec![7, 8, 9]),
wr(6, vec![10, 11, 12]),
];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 2, vec![1, 2]),
(2, 4, vec![4, 5]),
(4, 6, vec![7, 8]),
(6, 9, vec![10, 11, 12]),
]);
}
#[test]
fn test_merge_same_byte_overwritten_multiple_times() {
let writes = vec![
wr(5, vec![1]),
wr(5, vec![2]),
wr(5, vec![3]),
wr(5, vec![4]),
wr(5, vec![5]),
];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[(5, 6, vec![5])]);
}
#[test]
fn test_merge_preserves_data_correctly() {
let writes = vec![
wr(0, vec![10, 20, 30, 40, 50, 60, 70, 80]), wr(2, vec![99, 88]), ];
let merged = merge_overlapping_writes(writes);
assert_intervals(&merged, &[
(0, 2, vec![10, 20]),
(2, 4, vec![99, 88]),
(4, 8, vec![50, 60, 70, 80]),
]);
}
}