use std::collections::BTreeMap; /// For each chunk with a non-uniform delta, look at the bytes a uniform stride /// would swallow past the next record's start. Under "padding" they should be /// uniform or zero; under "variable-length" they are data and should not be. fn main() { let data = std::path::PathBuf::from(std::env::var("HOME").unwrap()).join("Documents/gc-extracted"); let mut hist: BTreeMap, usize> = BTreeMap::new(); let mut total = 0usize; let mut zero = 0usize; for lv in 0..6usize { let Ok(core) = std::fs::read(data.join(format!("level{lv}/core_data.bin"))) else { continue; }; for c in gc_formats::chunks::parse_all_chunks(&core).unwrap() { let s = c.chunk.stride; let o = &c.chunk.offsets; for w in o.windows(2) { let (a, b) = (w[0] as usize, w[1] as usize); if b - a >= s { continue; } let gap = s - (b - a); // bytes the uniform slice over-reads // the disputed bytes are the last `gap` of the uniform slice let lo = c.chunk.offset + a + (b - a); let Some(tail) = core.get(lo..lo + gap) else { continue; }; let mut t = tail.to_vec(); t.sort_unstable(); if t.iter().all(|&x| x == t[0]) { zero += 1; } *hist.entry(tail.to_vec()).or_default() += 1; total += 1; } } } println!( "{total} over-reads examined; {zero} are a single repeated byte ({:.1}%)", 100.0 * zero as f64 / total.max(1) as f64 ); println!("\nmost common disputed byte sequences:"); let mut v: Vec<_> = hist.into_iter().collect(); v.sort_by_key(|(_, n)| std::cmp::Reverse(*n)); for (b, n) in v.iter().take(15) { println!( " x{n:<5} {}", b.iter() .map(|x| format!("{x:02x}")) .collect::>() .join(" ") ); } println!("\ndistinct disputed sequences: {}", v.len()); }