app
Adom Chip Fetcher
Public Made by Adomby adom
Your whole parts library — manufacturer-grade chip CAD (symbol, footprint, 3D) one tap from your EDA tool.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
//! Supply-chain (BOM) identifiers for the adom-lbr v1.6.0 contract.
//!
//! Whenever chip-fetcher shells `adom-lbr generate`/`export` it MUST pass the
//! supply-chain IDs it already looked up — `--mfr`, `--mpn`, `--mouser`,
//! `--digikey`, `--lcsc` — so adom-lbr writes MF/MPN/MOUSER/DIGIKEY/LCSC into
//! the library device <technology>, which Fusion 360 / Altium / OrCAD surface in
//! the BOM. Omitting one is only OK when that distributor genuinely has no match
//! (adom-lbr just notes it). We read everything we know from `stock.json` (the
//! Mouser snapshot), falling back to `info.json` and `<mpn>-symbol.extracted.json`.
use serde_json::Value;
use std::path::Path;
fn read_json(dir: &Path, name: &str) -> Value {
std::fs::read_to_string(dir.join(name))
.ok()
.and_then(|s| serde_json::from_str(&s).ok())
.unwrap_or(Value::Null)
}
/// Follow a path of keys to a non-empty string.
fn s(v: &Value, path: &[&str]) -> Option<String> {
let mut cur = v;
for k in path {
cur = cur.get(k)?;
}
cur.as_str().filter(|x| !x.is_empty()).map(|x| x.to_string())
}
/// The adom-lbr BOM flags for a part, in order. Always includes `--mpn` (the
/// orderable MPN); `--mfr` and `--mouser` when known; `--digikey`/`--lcsc` only
/// when a real distributor part number is on record (omitted otherwise, which
/// adom-lbr accepts as "not stocked there").
pub fn flags(dir: &Path, mpn: &str) -> Vec<String> {
let stock = read_json(dir, "stock.json");
let info = read_json(dir, "info.json");
let sym = read_json(dir, &format!("{mpn}-symbol.extracted.json"));
// Manufacturer: Mouser snapshot → info.json → extracted symbol.
let mfr = s(&stock, &["mouser", "manufacturer"])
.or_else(|| s(&info, &["manufacturer"]))
.or_else(|| s(&sym, &["manufacturer"]));
// Orderable MPN: Mouser's exact MPN → info.json → the part name itself.
let part_mpn = s(&stock, &["mouser", "mpn"])
.or_else(|| s(&info, &["mpn"]))
.unwrap_or_else(|| mpn.to_string());
let mouser = s(&stock, &["mouser", "mouser_pn"]);
// DigiKey / LCSC only when an explicit order code is recorded (stock.json is
// Mouser-centric; these are usually absent → correctly omitted).
let digikey = s(&stock, &["digikey", "digikey_pn"]).or_else(|| s(&stock, &["digikey_pn"]));
let lcsc = s(&stock, &["lcsc", "lcsc_pn"]).or_else(|| s(&stock, &["lcsc_pn"]));
let mut f = Vec::new();
if let Some(m) = mfr {
f.push("--mfr".into());
f.push(m);
}
f.push("--mpn".into());
f.push(part_mpn);
if let Some(m) = mouser {
f.push("--mouser".into());
f.push(m);
}
if let Some(d) = digikey {
f.push("--digikey".into());
f.push(d);
}
if let Some(l) = lcsc {
f.push("--lcsc".into());
f.push(l);
}
f
}