use anyhow::{Context, Result};
use parx_rs::ParxReader;
use std::time::{Duration, UNIX_EPOCH};
use super::storage;
pub async fn run(input: &str) -> Result<()> {
let parx_bytes = storage::read_all(input)
.await
.context("Failed to read PARX file")?;
let reader = ParxReader::open(&parx_bytes).context("Failed to parse PARX file")?;
let manifest = reader.manifest();
let header = reader.header();
println!("PARX File: {}", input);
println!();
println!("Header:");
println!(
" Version: {}.{}",
header.version_major, header.version_minor
);
println!(" Flags: {:#06x}", header.flags);
if header.is_footer_compressed() {
if let Some(algo) = header.compression_algorithm() {
println!(" - Footer compressed ({})", algo);
}
}
println!();
println!("Manifest:");
println!(" Version: {}", manifest.version);
println!();
println!("Source Binding:");
if !manifest.source_uri.is_empty() {
println!(" URI: {}", manifest.source_uri);
}
println!(" Size: {} bytes", manifest.source_size);
println!(
" Footer hash: {}",
hex_string(&manifest.source_footer_checksum)
);
println!();
println!("Footer Payload:");
println!(" Offset: {}", manifest.footer_offset);
println!(" Length: {} bytes", manifest.footer_length);
if reader.is_compressed() {
println!(
" Uncompressed size: {} bytes",
manifest.footer_uncompressed_size
);
let ratio = if manifest.footer_uncompressed_size > 0 {
(manifest.footer_length as f64 / manifest.footer_uncompressed_size as f64) * 100.0
} else {
100.0
};
println!(" Compression ratio: {:.1}%", ratio);
}
println!(" Checksum: {}", hex_string(&manifest.footer_checksum));
println!();
println!("Build Metadata:");
if manifest.created_at_ms > 0 {
let created = UNIX_EPOCH + Duration::from_millis(manifest.created_at_ms);
if let Ok(datetime) = created.duration_since(UNIX_EPOCH) {
let secs = datetime.as_secs();
println!(" Created: {} (unix timestamp)", secs);
}
}
Ok(())
}
fn hex_string(bytes: &[u8]) -> String {
if bytes.is_empty() {
return "(empty)".to_string();
}
bytes.iter().map(|b| format!("{:02x}", b)).collect()
}