Skip to main content

symbol_corpus_roundtrip/
symbol_corpus_roundtrip.rs

1use std::fs;
2use std::path::{Path, PathBuf};
3
4use kiutils_kicad::SymbolLibFile;
5
6fn usage() -> String {
7    "usage: symbol_corpus_roundtrip <input_dir> <output_dir>".to_string()
8}
9
10fn collect_symbol_files(dir: &Path, files: &mut Vec<PathBuf>) -> Result<(), String> {
11    let entries = fs::read_dir(dir).map_err(|e| format!("read_dir {}: {e}", dir.display()))?;
12    for entry in entries {
13        let entry = entry.map_err(|e| format!("read_dir entry {}: {e}", dir.display()))?;
14        let path = entry.path();
15        if path.is_dir() {
16            collect_symbol_files(&path, files)?;
17        } else if path.extension().and_then(|s| s.to_str()) == Some("kicad_sym") {
18            files.push(path);
19        }
20    }
21    Ok(())
22}
23
24fn main() -> Result<(), String> {
25    let mut args = std::env::args().skip(1);
26    let input_dir = args.next().map(PathBuf::from).ok_or_else(usage)?;
27    let output_dir = args.next().map(PathBuf::from).ok_or_else(usage)?;
28
29    let mut files = Vec::new();
30    collect_symbol_files(&input_dir, &mut files)?;
31    files.sort();
32
33    if files.is_empty() {
34        return Err(format!(
35            "no .kicad_sym files found under {}",
36            input_dir.display()
37        ));
38    }
39
40    let mut ok = 0usize;
41    let mut failed = 0usize;
42
43    for path in files {
44        let rel = path
45            .strip_prefix(&input_dir)
46            .map_err(|e| format!("strip_prefix {}: {e}", path.display()))?;
47        let out_path = output_dir.join(rel);
48        if let Some(parent) = out_path.parent() {
49            fs::create_dir_all(parent)
50                .map_err(|e| format!("create_dir_all {}: {e}", parent.display()))?;
51        }
52
53        let result = (|| -> Result<(), String> {
54            let doc = SymbolLibFile::read(&path).map_err(|e| format!("read: {e}"))?;
55            doc.write(&out_path).map_err(|e| format!("write: {e}"))?;
56            let _ = SymbolLibFile::read(&out_path).map_err(|e| format!("reread: {e}"))?;
57            Ok(())
58        })();
59
60        match result {
61            Ok(()) => {
62                ok += 1;
63                println!("ok: {}", path.display());
64            }
65            Err(err) => {
66                failed += 1;
67                eprintln!("fail: {} -> {}", path.display(), err);
68            }
69        }
70    }
71
72    println!("summary: ok={ok} failed={failed}");
73    if failed > 0 {
74        return Err(format!("{failed} files failed"));
75    }
76    Ok(())
77}