Skip to main content

inspect_issues/
inspect_issues.rs

1use halbu::{Save, Strictness};
2
3fn main() -> Result<(), Box<dyn std::error::Error>> {
4    // Start from a known good file.
5    let bytes = std::fs::read("assets/test/Joe.d2s")?;
6
7    // Strict mode fails fast on invalid data.
8    let strict = Save::parse(&bytes, Strictness::Strict)?;
9    println!(
10        "Strict parse OK: format={:?}, name={}",
11        strict.save.format(),
12        strict.save.character.name
13    );
14
15    // Validation is separate from parsing, so check the save on its own.
16    let validation = strict.save.validate();
17    println!("\nValidation issues: {}", validation.issues.len());
18    for (index, issue) in validation.issues.iter().enumerate() {
19        println!("#{index} [{:?}] {}", issue.code, issue.message);
20    }
21
22    // Break the payload on purpose so we can inspect non-fatal issues.
23    // - byte 0 breaks signature
24    // - truncation simulates a damaged or incomplete file
25    let mut damaged = bytes.clone();
26    damaged[0] = 0x00;
27    damaged.truncate(220);
28
29    // Lax mode keeps going and collects issues.
30    let lax = Save::parse(&damaged, Strictness::Lax)?;
31    println!("\nLax parse issues: {}", lax.issues.len());
32    for (index, issue) in lax.issues.iter().enumerate() {
33        println!(
34            "#{index} [{:?}/{:?}] section={:?} offset={:?} expected={:?} found={:?}\n  {}",
35            issue.severity,
36            issue.kind,
37            issue.section,
38            issue.offset,
39            issue.expected,
40            issue.found,
41            issue.message
42        );
43    }
44
45    // Strict mode should reject the damaged payload.
46    match Save::parse(&damaged, Strictness::Strict) {
47        Ok(_) => println!("\nUnexpected: strict parse accepted damaged payload."),
48        Err(error) => println!("\nStrict parse error: {error}"),
49    }
50
51    Ok(())
52}