pub mod reference_zic;
pub mod report;
pub mod semantic;
pub mod zdump;
use std::path::{Path, PathBuf};
use crate::error::{Error, Result};
use crate::fs::output_tree;
use crate::model::Database;
use crate::tzif;
use report::{ComparisonKind, ZoneComparison};
#[derive(Debug, Clone)]
pub enum CompareMode {
Structural,
Zdump { program: String, lo: i32, hi: i32 },
}
pub fn compare_zone(
db: &Database,
inputs: &[PathBuf],
zone: &str,
reference_zic: &str,
work_dir: &Path,
mode: &CompareMode,
) -> Result<ZoneComparison> {
let ours_bytes = crate::compile_zone_to_bytes(db, zone)?;
let ref_root = work_dir.join("ref");
std::fs::create_dir_all(&ref_root).map_err(|e| Error::io(&ref_root, e))?;
reference_zic::compile_with_reference(reference_zic, inputs, &ref_root)?;
let ref_path = reference_zic::compiled_path(&ref_root, zone);
let theirs_bytes = std::fs::read(&ref_path).map_err(|e| Error::io(&ref_path, e))?;
let byte_identical = ours_bytes == theirs_bytes;
match mode {
CompareMode::Structural => {
let ours = tzif::parse(&ours_bytes)?;
let theirs = tzif::parse(&theirs_bytes)?;
Ok(ZoneComparison {
zone: zone.to_string(),
kind: ComparisonKind::DecodedTzif,
differences: semantic::diff(&ours, &theirs),
byte_identical,
})
}
CompareMode::Zdump { program, lo, hi } => {
let ours_root = work_dir.join("ours");
let ours_path =
output_tree::write_zone_file(&ours_root, zone, &ours_bytes, true, false)?;
let ours_lines = zdump::run(program, &ours_path, *lo, *hi)?;
let theirs_lines = zdump::run(program, &ref_path, *lo, *hi)?;
Ok(ZoneComparison {
zone: zone.to_string(),
kind: ComparisonKind::ZdumpBehaviour { lo: *lo, hi: *hi },
differences: zdump::diff(&ours_lines, &theirs_lines),
byte_identical,
})
}
}
}