///|
pub(all) enum RecordDiffKind {
Added
Removed
Changed
} derive(Debug, Eq)
///|
pub(all) struct RecordDiff {
kind : RecordDiffKind
key : String
left : VcfRecord?
right : VcfRecord?
} derive(Debug, Eq)
///|
pub fn diff_documents(
left : VcfDocument,
right : VcfDocument,
) -> Array[RecordDiff] {
let diffs : Array[RecordDiff] = []
for record in left.records {
let key = record_key(record)
match find_record(right.records, key) {
None =>
diffs.push({
kind: RecordDiffKind::Removed,
key,
left: Some(record),
right: None,
})
Some(other) if other != record =>
diffs.push({
kind: RecordDiffKind::Changed,
key,
left: Some(record),
right: Some(other),
})
Some(_) => ()
}
if find_record(right.records, key) is None {
match find_locus(right.records, record_locus_key(record)) {
Some(other) => {
ignore(diffs.pop())
diffs.push({
kind: RecordDiffKind::Changed,
key,
left: Some(record),
right: Some(other),
})
}
None => ()
}
}
}
for record in right.records {
let key = record_key(record)
if find_record(left.records, key) is None &&
find_locus(left.records, record_locus_key(record)) is None {
diffs.push({
kind: RecordDiffKind::Added,
key,
left: None,
right: Some(record),
})
}
}
diffs
}
///|
fn record_locus_key(record : VcfRecord) -> String {
"\{record.chrom}:\{record.pos}:\{record.ref_allele}"
}
///|
pub fn record_key(record : VcfRecord) -> String {
let alts = record.alt_alleles.join(",")
"\{record.chrom}:\{record.pos}:\{record.ref_allele}>\{alts}"
}
///|
fn find_record(records : Array[VcfRecord], key : String) -> VcfRecord? {
for record in records {
if record_key(record) == key {
return Some(record)
}
}
None
}
///|
fn find_locus(records : Array[VcfRecord], key : String) -> VcfRecord? {
for record in records {
if record_locus_key(record) == key {
return Some(record)
}
}
None
}