use std::fs;
use std::path::Path;
use std::process::ExitCode;
use dsfb_gpu_debug_core::serialize::{write_key, write_str, write_u64};
use dsfb_gpu_debug_core::verdict::FinalVerdict;
use super::{parse_flags, require_flag, usage_error};
pub fn parse_and_run(args: &[String]) -> ExitCode {
let flags = match parse_flags(args) {
Ok(f) => f,
Err(message) => return usage_error(&message),
};
let cpu_path = match require_flag(&flags, "cpu") {
Ok(s) => s.to_string(),
Err(message) => return usage_error(&message),
};
let gpu_path = match require_flag(&flags, "gpu") {
Ok(s) => s.to_string(),
Err(message) => return usage_error(&message),
};
let out_path = match require_flag(&flags, "out") {
Ok(s) => s.to_string(),
Err(message) => return usage_error(&message),
};
let cpu_bytes = match fs::read(&cpu_path) {
Ok(b) => b,
Err(error) => {
eprintln!("dsfb-gpu-debug: failed to read {cpu_path}: {error}");
return ExitCode::from(5);
}
};
let gpu_bytes = match fs::read(&gpu_path) {
Ok(b) => b,
Err(error) => {
eprintln!("dsfb-gpu-debug: failed to read {gpu_path}: {error}");
return ExitCode::from(5);
}
};
let verdict = if cpu_bytes == gpu_bytes {
FinalVerdict::ReplayAdmissible
} else {
FinalVerdict::NumericMismatch
};
let report = write_comparison_report(
&cpu_path,
&gpu_path,
verdict,
cpu_bytes.len(),
gpu_bytes.len(),
);
if let Some(parent) = Path::new(&out_path).parent() {
if !parent.as_os_str().is_empty() {
if let Err(error) = fs::create_dir_all(parent) {
eprintln!(
"dsfb-gpu-debug: could not create {}: {error}",
parent.display()
);
return ExitCode::from(5);
}
}
}
if let Err(error) = fs::write(&out_path, &report) {
eprintln!("dsfb-gpu-debug: failed to write {out_path}: {error}");
return ExitCode::from(5);
}
eprintln!(
"dsfb-gpu-debug: comparison verdict={} (cpu={} bytes, gpu={} bytes)",
verdict.name(),
cpu_bytes.len(),
gpu_bytes.len()
);
ExitCode::from(verdict.exit_code())
}
fn write_comparison_report(
cpu_path: &str,
gpu_path: &str,
verdict: FinalVerdict,
cpu_len: usize,
gpu_len: usize,
) -> Vec<u8> {
let mut buf: Vec<u8> = Vec::new();
buf.push(b'{');
write_key(&mut buf, "cpu_bytes");
write_u64(&mut buf, cpu_len as u64);
buf.push(b',');
write_key(&mut buf, "cpu_path");
write_str(&mut buf, cpu_path);
buf.push(b',');
write_key(&mut buf, "gpu_bytes");
write_u64(&mut buf, gpu_len as u64);
buf.push(b',');
write_key(&mut buf, "gpu_path");
write_str(&mut buf, gpu_path);
buf.push(b',');
write_key(&mut buf, "verdict");
write_str(&mut buf, verdict.name());
buf.push(b'}');
buf
}