symbol_corpus_roundtrip/
symbol_corpus_roundtrip.rs1use 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}