use anyhow::{Context, Result};
use parx_rs::ParxReader;
use super::storage;
pub async fn run(input: &str, with_source: bool) -> Result<()> {
println!("Verifying: {}", input);
let parx_bytes = storage::read_all(input)
.await
.context("Failed to read PARX file")?;
let reader = ParxReader::open(&parx_bytes).context("PARX file validation failed")?;
println!(" Header magic: OK");
println!(" Trailer magic: OK");
println!(" Manifest CRC32C: OK");
println!(" Footer CRC32C: OK");
if reader.is_compressed() {
if let Some(algo) = reader.compression_algorithm() {
println!(" Decompression ({}): OK", algo);
}
}
if with_source {
let manifest = reader.manifest();
if manifest.source_uri.is_empty() {
println!();
println!("Warning: No source URI in manifest, cannot verify against source");
} else {
println!();
println!("Verifying against source: {}", manifest.source_uri);
let source_meta = storage::head(&manifest.source_uri)
.await
.context("Failed to get source file metadata")?;
if reader.validate_source_size(source_meta.size as u64) {
println!(" Source size: OK ({} bytes)", source_meta.size);
} else {
println!(
" Source size: MISMATCH (expected {}, got {})",
manifest.source_size, source_meta.size
);
anyhow::bail!("Source file size mismatch - PARX file is stale");
}
let (source_footer, _) = storage::extract_parquet_footer(&manifest.source_uri)
.await
.context("Failed to extract source Parquet footer")?;
if reader.validate_source_footer(&source_footer) {
println!(" Source footer hash: OK");
} else {
println!(" Source footer hash: MISMATCH");
anyhow::bail!("Source footer hash mismatch - PARX file is stale");
}
}
}
println!();
println!("Verification passed.");
Ok(())
}