use std::collections::HashMap;
use crate::features::storage::sstable::Entry;
#[derive(Debug)]
pub enum MergeError {
EmptyInput,
}
pub type Result<T> = std::result::Result<T, MergeError>;
pub fn merge_latest_by_key(runs_newest_first: &[Vec<Entry>]) -> Result<Vec<Entry>> {
if runs_newest_first.is_empty() {
return Err(MergeError::EmptyInput);
}
let mut seen: HashMap<u64, Entry> = HashMap::new();
for run in runs_newest_first {
for entry in run {
seen.entry(entry.key).or_insert_with(|| entry.clone());
}
}
let mut merged: Vec<Entry> = seen.into_values().collect();
merged.sort_by(|a, b| (a.key, a.version).cmp(&(b.key, b.version)));
Ok(merged)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::features::storage::sstable::EntryKind;
#[test]
fn merge_prefers_newest_run() {
let older = vec![
Entry {
key: 1,
version: 1,
kind: EntryKind::EdgeDelta,
value: b"old-1".to_vec(),
},
Entry {
key: 2,
version: 1,
kind: EntryKind::EdgeDelta,
value: b"old-2".to_vec(),
},
];
let newer = vec![
Entry {
key: 2,
version: 2,
kind: EntryKind::FullNode,
value: b"new-2".to_vec(),
},
Entry {
key: 3,
version: 1,
kind: EntryKind::VectorDelta,
value: b"new-3".to_vec(),
},
];
let merged = merge_latest_by_key(&[newer.clone(), older]).unwrap();
assert_eq!(merged.len(), 3);
assert!(merged.iter().any(|e| e.key == 1 && e.value == b"old-1"));
assert!(merged.iter().any(|e| e.key == 2 && e.value == b"new-2"));
assert!(merged.iter().any(|e| e.key == 3 && e.value == b"new-3"));
}
}