#![allow(dead_code)]
mod diagnostic;
#[cfg(test)]
mod tests;
pub use diagnostic::JsonDiagnostic;
use std::path::Path;
use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
#[serde(tag = "type")]
pub enum CircuitElement {
#[serde(rename = "source_component")]
Component(Component),
#[serde(rename = "source_net")]
Net(Net),
#[serde(rename = "source_port")]
Port(Port),
#[serde(rename = "source_pad")]
Pad(Pad),
#[serde(rename = "source_trace")]
Trace(Trace),
#[serde(other)]
Unknown,
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Component {
#[serde(alias = "source_component_id", alias = "sourceComponentId")]
pub component_id: Option<String>,
#[serde(alias = "ftype")]
pub kind: Option<String>,
#[serde(default)]
pub name: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Net {
#[serde(alias = "source_net_id", alias = "sourceNetId", alias = "netId")]
pub net_id: Option<String>,
#[serde(alias = "netName")]
pub name: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Port {
#[serde(alias = "source_port_id", alias = "sourcePortId")]
pub port_id: Option<String>,
#[serde(alias = "portName")]
pub name: Option<String>,
#[serde(alias = "source_net_id", alias = "sourceNetId", alias = "netId")]
pub net_id: Option<String>,
#[serde(default, alias = "source_component_id", alias = "sourceComponentId")]
pub source_component_id: Option<String>,
#[serde(default, alias = "pin_number", alias = "pinNumber")]
pub pin_number: Option<u32>,
#[serde(default, alias = "port_hints", alias = "portHints")]
pub port_hints: Option<Vec<String>>,
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Pad {
#[serde(alias = "source_pad_id", alias = "sourcePadId")]
pub pad_id: Option<String>,
#[serde(alias = "source_net_id", alias = "sourceNetId", alias = "netId")]
pub net_id: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Default)]
pub struct Trace {
#[serde(alias = "source_trace_id", alias = "sourceTraceId")]
pub trace_id: Option<String>,
#[serde(
default,
alias = "connectedSourcePortIds",
alias = "connected_port_ids",
alias = "connectedPortIds"
)]
pub connected_source_port_ids: Vec<String>,
#[serde(
default,
alias = "connectedSourceNetIds",
alias = "connected_net_ids",
alias = "connectedNetIds"
)]
pub connected_source_net_ids: Vec<String>,
#[serde(default, alias = "display_name", alias = "displayName")]
pub name: Option<String>,
#[serde(default, alias = "subcircuit_connectivity_map_key")]
pub connectivity_key: Option<String>,
}
#[derive(Debug, Clone)]
pub struct Circuit {
pub elements: Vec<CircuitElement>,
}
impl Circuit {
pub fn components(&self) -> impl Iterator<Item = &Component> {
self.elements.iter().filter_map(|e| match e {
CircuitElement::Component(c) => Some(c),
_ => None,
})
}
pub fn nets(&self) -> impl Iterator<Item = &Net> {
self.elements.iter().filter_map(|e| match e {
CircuitElement::Net(n) => Some(n),
_ => None,
})
}
pub fn ports(&self) -> impl Iterator<Item = &Port> {
self.elements.iter().filter_map(|e| match e {
CircuitElement::Port(p) => Some(p),
_ => None,
})
}
pub fn pads(&self) -> impl Iterator<Item = &Pad> {
self.elements.iter().filter_map(|e| match e {
CircuitElement::Pad(p) => Some(p),
_ => None,
})
}
pub fn traces(&self) -> impl Iterator<Item = &Trace> {
self.elements.iter().filter_map(|e| match e {
CircuitElement::Trace(t) => Some(t),
_ => None,
})
}
}
pub fn parse(source: &str, path: &Path) -> Result<Circuit, JsonDiagnostic> {
let elements: Vec<CircuitElement> =
serde_json::from_str(source).map_err(|err| JsonDiagnostic::new(err, source, path))?;
Ok(Circuit { elements })
}