app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
← Commit history
rust/src/cli.rsdeleted−117@@ -1,117 +0,0 @@-//! kicad-cli runner. Every call is quiet (no console window), has a deadline, and returns-//! stdout, stderr and the parsed JSON report when one was requested.--use std::path::Path;-use std::process::Command;-use std::time::{Duration, Instant};--use serde_json::{json, Value};--/// Never let a console child blip a window onto the user's screen.-pub fn quiet(cmd: &mut Command) {- cmd.stdin(std::process::Stdio::null());- #[cfg(windows)]- {- use std::os::windows::process::CommandExt;- const CREATE_NO_WINDOW: u32 = 0x0800_0000;- cmd.creation_flags(CREATE_NO_WINDOW);- }-}--pub struct CliResult {- pub exit_code: i32,- pub stdout: String,- pub stderr: String,- pub elapsed_ms: u64,- pub timed_out: bool,-}--pub fn run(cli: &Path, args: &[&str], timeout: Duration) -> CliResult {- let mut cmd = Command::new(cli);- cmd.args(args);- quiet(&mut cmd);- cmd.stdout(std::process::Stdio::piped()).stderr(std::process::Stdio::piped());- let t0 = Instant::now();- let mut child = match cmd.spawn() {- Ok(c) => c,- Err(e) => {- return CliResult { exit_code: -1, stdout: String::new(), stderr: format!("spawn failed: {e}"), elapsed_ms: 0, timed_out: false }- }- };- // Poll with a deadline; kill on timeout so a hung kicad-cli never hangs a verb.- loop {- match child.try_wait() {- Ok(Some(_)) => break,- Ok(None) => {- if t0.elapsed() > timeout {- let _ = child.kill();- let _ = child.wait();- return CliResult { exit_code: -2, stdout: String::new(), stderr: "kicad-cli timed out".into(), elapsed_ms: t0.elapsed().as_millis() as u64, timed_out: true };- }- std::thread::sleep(Duration::from_millis(50));- }- Err(e) => {- return CliResult { exit_code: -1, stdout: String::new(), stderr: format!("wait failed: {e}"), elapsed_ms: t0.elapsed().as_millis() as u64, timed_out: false }- }- }- }- let out = child.wait_with_output().unwrap();- CliResult {- exit_code: out.status.code().unwrap_or(-1),- stdout: String::from_utf8_lossy(&out.stdout).to_string(),- stderr: String::from_utf8_lossy(&out.stderr).to_string(),- elapsed_ms: t0.elapsed().as_millis() as u64,- timed_out: false,- }-}--/// Summarise a kicad-cli drc/erc JSON report the way the Python bridge does:-/// counts by severity, unconnected items, and the first violations verbatim.-pub fn summarize_report(report: &Value) -> Value {- let mut errors = 0u64;- let mut warnings = 0u64;- let mut exclusions = 0u64;- let mut first: Vec<Value> = Vec::new();- let mut walk = |arr: &Value| {- if let Some(items) = arr.as_array() {- for v in items {- if v.get("excluded").and_then(Value::as_bool).unwrap_or(false) {- exclusions += 1;- continue;- }- match v.get("severity").and_then(Value::as_str) {- Some("error") => errors += 1,- Some("warning") => warnings += 1,- _ => {}- }- if first.len() < 25 {- first.push(json!({- "type": v.get("type"),- "severity": v.get("severity"),- "description": v.get("description"),- "items": v.get("items").and_then(Value::as_array).map(|a| a.iter().filter_map(|i| i.get("description").cloned()).collect::<Vec<_>>()),- }));- }- }- }- };- walk(report.get("violations").unwrap_or(&Value::Null));- let unconnected = report.get("unconnected_items").and_then(Value::as_array).map(|a| a.len()).unwrap_or(0);- walk(report.get("unconnected_items").unwrap_or(&Value::Null));- walk(report.get("schematic_parity").unwrap_or(&Value::Null));- if let Some(sheets) = report.get("sheets").and_then(Value::as_array) {- for s in sheets {- walk(s.get("violations").unwrap_or(&Value::Null));- }- }- json!({- "errors": errors,- "warnings": warnings,- "excluded": exclusions,- "unconnected": unconnected,- "clean": errors == 0 && unconnected == 0,- "first": first,- "kicadVersion": report.get("kicad_version"),- "source": report.get("source"),- })-}