mirror of https://codeberg.org/topola/topola.git
dsn: replace structure with new renamed structure2
This commit is contained in:
parent
4ec9467649
commit
8c2ad87bf0
|
|
@ -34,17 +34,17 @@ impl DsnDesign {
|
||||||
let reader = std::io::BufReader::new(file);
|
let reader = std::io::BufReader::new(file);
|
||||||
let mut list_reader = super::read::ListTokenizer::new(reader);
|
let mut list_reader = super::read::ListTokenizer::new(reader);
|
||||||
|
|
||||||
let dsn = list_reader.read_value::<super::structure2::DsnFile>();
|
let dsn = list_reader.read_value::<super::structure::DsnFile>();
|
||||||
|
|
||||||
// TODO: make_board() still uses the old version of structure.rs
|
// TODO: make_board() still uses the old version of structure.rs
|
||||||
// so we can't pass the data to topola for real
|
// so we can't pass the data to topola for real
|
||||||
|
|
||||||
if let Ok(dsn) = dsn {
|
if let Ok(dsn) = dsn {
|
||||||
use super::structure2::*;
|
use super::structure::*;
|
||||||
|
|
||||||
// (this entire if let block does not belong here)
|
// (this entire if let block does not belong here)
|
||||||
|
|
||||||
let ses_name = filename.replace(".dsn", ".ses");
|
/*let ses_name = filename.replace(".dsn", ".ses");
|
||||||
let file2 = std::fs::File::create(ses_name).unwrap();
|
let file2 = std::fs::File::create(ses_name).unwrap();
|
||||||
let writer = std::io::BufWriter::new(file2);
|
let writer = std::io::BufWriter::new(file2);
|
||||||
let mut list_writer = super::write::ListWriter::new(writer);
|
let mut list_writer = super::write::ListWriter::new(writer);
|
||||||
|
|
@ -103,38 +103,43 @@ impl DsnDesign {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};*/
|
||||||
|
|
||||||
println!("{:?}", list_writer.write_value(&ses));
|
//println!("{:?}", list_writer.write_value(&ses));
|
||||||
|
|
||||||
|
Ok(Self { pcb: dsn.pcb })
|
||||||
} else {
|
} else {
|
||||||
dbg!(dsn);
|
dbg!(dsn);
|
||||||
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
let contents = std::fs::read_to_string(filename)?;
|
|
||||||
|
|
||||||
Self::load_from_string(contents)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_from_string(contents: String) -> Result<Self, LoadingError> {
|
pub fn load_from_string(contents: String) -> Result<Self, LoadingError> {
|
||||||
let pcb = de::from_str::<DsnFile>(&contents)
|
/*let dsn = de::from_str::<DsnFile>(&contents)
|
||||||
.map_err(|err| LoadingError::Syntax(err))?
|
.map_err(|err| LoadingError::Syntax(err))?
|
||||||
.pcb;
|
.pcb;
|
||||||
|
|
||||||
Ok(Self { pcb })
|
Ok(Self { pcb })*/
|
||||||
|
let mut list_reader = super::read::ListTokenizer::new(contents.as_bytes());
|
||||||
|
let dsn = list_reader.read_value::<super::structure::DsnFile>();
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
pcb: dsn.unwrap().pcb,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_board(&self) -> Board<DsnMesadata> {
|
pub fn make_board(&self) -> Board<DsnMesadata> {
|
||||||
let mesadata = DsnMesadata::from_pcb(&self.pcb);
|
let mesadata = DsnMesadata::from_pcb(&self.pcb);
|
||||||
let mut board = Board::new(Layout::new(Drawing::new(
|
let mut board = Board::new(Layout::new(Drawing::new(
|
||||||
mesadata,
|
mesadata,
|
||||||
self.pcb.structure.layer_vec.len(),
|
self.pcb.structure.layers.len(),
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// mapping of pin -> net prepared for adding pins
|
// mapping of pin -> net prepared for adding pins
|
||||||
let pin_nets = HashMap::<String, usize>::from_iter(
|
let pin_nets = HashMap::<String, usize>::from_iter(
|
||||||
self.pcb
|
self.pcb
|
||||||
.network
|
.network
|
||||||
.net_vec
|
.nets
|
||||||
.iter()
|
.iter()
|
||||||
.map(|net_pin_assignments| {
|
.map(|net_pin_assignments| {
|
||||||
// resolve the id so we don't work with strings
|
// resolve the id so we don't work with strings
|
||||||
|
|
@ -158,34 +163,34 @@ impl DsnDesign {
|
||||||
);
|
);
|
||||||
|
|
||||||
// add pins from components
|
// add pins from components
|
||||||
for component in &self.pcb.placement.component_vec {
|
for component in &self.pcb.placement.components {
|
||||||
for place in &component.place_vec {
|
for place in &component.places {
|
||||||
let image = self
|
let image = self
|
||||||
.pcb
|
.pcb
|
||||||
.library
|
.library
|
||||||
.image_vec
|
.images
|
||||||
.iter()
|
.iter()
|
||||||
.find(|image| image.name == component.name)
|
.find(|image| image.name == component.name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for pin in &image.pin_vec {
|
for pin in &image.pins {
|
||||||
let pinname = format!("{}-{}", place.name, pin.id);
|
let pinname = format!("{}-{}", place.name, pin.id);
|
||||||
let net = pin_nets.get(&pinname).unwrap();
|
let net = pin_nets.get(&pinname).unwrap();
|
||||||
|
|
||||||
let padstack = &self
|
let padstack = &self
|
||||||
.pcb
|
.pcb
|
||||||
.library
|
.library
|
||||||
.padstack_vec
|
.padstacks
|
||||||
.iter()
|
.iter()
|
||||||
.find(|padstack| padstack.name == pin.name)
|
.find(|padstack| padstack.name == pin.name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for shape in padstack.shape_vec.iter() {
|
for shape in padstack.shapes.iter() {
|
||||||
match shape {
|
match shape {
|
||||||
Shape::Circle(circle) => {
|
Shape::Circle(circle) => {
|
||||||
let layer = Self::layer(
|
let layer = Self::layer(
|
||||||
&mut board,
|
&mut board,
|
||||||
&self.pcb.structure.layer_vec,
|
&self.pcb.structure.layers,
|
||||||
&circle.layer,
|
&circle.layer,
|
||||||
place.side == "front",
|
place.side == "front",
|
||||||
);
|
);
|
||||||
|
|
@ -204,7 +209,7 @@ impl DsnDesign {
|
||||||
Shape::Rect(rect) => {
|
Shape::Rect(rect) => {
|
||||||
let layer = Self::layer(
|
let layer = Self::layer(
|
||||||
&mut board,
|
&mut board,
|
||||||
&self.pcb.structure.layer_vec,
|
&self.pcb.structure.layers,
|
||||||
&rect.layer,
|
&rect.layer,
|
||||||
place.side == "front",
|
place.side == "front",
|
||||||
);
|
);
|
||||||
|
|
@ -226,7 +231,7 @@ impl DsnDesign {
|
||||||
Shape::Path(path) => {
|
Shape::Path(path) => {
|
||||||
let layer = Self::layer(
|
let layer = Self::layer(
|
||||||
&mut board,
|
&mut board,
|
||||||
&self.pcb.structure.layer_vec,
|
&self.pcb.structure.layers,
|
||||||
&path.layer,
|
&path.layer,
|
||||||
place.side == "front",
|
place.side == "front",
|
||||||
);
|
);
|
||||||
|
|
@ -236,7 +241,7 @@ impl DsnDesign {
|
||||||
place.rotation as f64,
|
place.rotation as f64,
|
||||||
(pin.x as f64, pin.y as f64).into(),
|
(pin.x as f64, pin.y as f64).into(),
|
||||||
pin.rotate.unwrap_or(0.0) as f64,
|
pin.rotate.unwrap_or(0.0) as f64,
|
||||||
&path.coord_vec,
|
&path.coords,
|
||||||
path.width as f64,
|
path.width as f64,
|
||||||
layer as usize,
|
layer as usize,
|
||||||
*net,
|
*net,
|
||||||
|
|
@ -246,7 +251,7 @@ impl DsnDesign {
|
||||||
Shape::Polygon(polygon) => {
|
Shape::Polygon(polygon) => {
|
||||||
let layer = Self::layer(
|
let layer = Self::layer(
|
||||||
&mut board,
|
&mut board,
|
||||||
&self.pcb.structure.layer_vec,
|
&self.pcb.structure.layers,
|
||||||
&polygon.layer,
|
&polygon.layer,
|
||||||
place.side == "front",
|
place.side == "front",
|
||||||
);
|
);
|
||||||
|
|
@ -256,7 +261,7 @@ impl DsnDesign {
|
||||||
place.rotation as f64,
|
place.rotation as f64,
|
||||||
(pin.x as f64, pin.y as f64).into(),
|
(pin.x as f64, pin.y as f64).into(),
|
||||||
pin.rotate.unwrap_or(0.0) as f64,
|
pin.rotate.unwrap_or(0.0) as f64,
|
||||||
&polygon.coord_vec,
|
&polygon.coords,
|
||||||
polygon.width as f64,
|
polygon.width as f64,
|
||||||
layer as usize,
|
layer as usize,
|
||||||
*net,
|
*net,
|
||||||
|
|
@ -269,7 +274,7 @@ impl DsnDesign {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for via in &self.pcb.wiring.via_vec {
|
for via in &self.pcb.wiring.vias {
|
||||||
let net = board
|
let net = board
|
||||||
.layout()
|
.layout()
|
||||||
.drawing()
|
.drawing()
|
||||||
|
|
@ -281,17 +286,17 @@ impl DsnDesign {
|
||||||
let padstack = &self
|
let padstack = &self
|
||||||
.pcb
|
.pcb
|
||||||
.library
|
.library
|
||||||
.padstack_vec
|
.padstacks
|
||||||
.iter()
|
.iter()
|
||||||
.find(|padstack| padstack.name == via.name)
|
.find(|padstack| padstack.name == via.name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for shape in &padstack.shape_vec {
|
for shape in &padstack.shapes {
|
||||||
match shape {
|
match shape {
|
||||||
Shape::Circle(circle) => {
|
Shape::Circle(circle) => {
|
||||||
let layer = Self::layer(
|
let layer = Self::layer(
|
||||||
&mut board,
|
&mut board,
|
||||||
&self.pcb.structure.layer_vec,
|
&self.pcb.structure.layers,
|
||||||
&circle.layer,
|
&circle.layer,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
@ -308,12 +313,8 @@ impl DsnDesign {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Shape::Rect(rect) => {
|
Shape::Rect(rect) => {
|
||||||
let layer = Self::layer(
|
let layer =
|
||||||
&mut board,
|
Self::layer(&mut board, &self.pcb.structure.layers, &rect.layer, true);
|
||||||
&self.pcb.structure.layer_vec,
|
|
||||||
&rect.layer,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
Self::add_rect(
|
Self::add_rect(
|
||||||
&mut board,
|
&mut board,
|
||||||
(0.0, 0.0).into(),
|
(0.0, 0.0).into(),
|
||||||
|
|
@ -330,19 +331,15 @@ impl DsnDesign {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Shape::Path(path) => {
|
Shape::Path(path) => {
|
||||||
let layer = Self::layer(
|
let layer =
|
||||||
&mut board,
|
Self::layer(&mut board, &self.pcb.structure.layers, &path.layer, true);
|
||||||
&self.pcb.structure.layer_vec,
|
|
||||||
&path.layer,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
Self::add_path(
|
Self::add_path(
|
||||||
&mut board,
|
&mut board,
|
||||||
(0.0, 0.0).into(),
|
(0.0, 0.0).into(),
|
||||||
0.0,
|
0.0,
|
||||||
(0.0, 0.0).into(),
|
(0.0, 0.0).into(),
|
||||||
0.0,
|
0.0,
|
||||||
&path.coord_vec,
|
&path.coords,
|
||||||
path.width as f64,
|
path.width as f64,
|
||||||
layer as usize,
|
layer as usize,
|
||||||
net,
|
net,
|
||||||
|
|
@ -352,7 +349,7 @@ impl DsnDesign {
|
||||||
Shape::Polygon(polygon) => {
|
Shape::Polygon(polygon) => {
|
||||||
let layer = Self::layer(
|
let layer = Self::layer(
|
||||||
&mut board,
|
&mut board,
|
||||||
&self.pcb.structure.layer_vec,
|
&self.pcb.structure.layers,
|
||||||
&polygon.layer,
|
&polygon.layer,
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
@ -362,7 +359,7 @@ impl DsnDesign {
|
||||||
0.0,
|
0.0,
|
||||||
(0.0, 0.0).into(),
|
(0.0, 0.0).into(),
|
||||||
0.0,
|
0.0,
|
||||||
&polygon.coord_vec,
|
&polygon.coords,
|
||||||
polygon.width as f64,
|
polygon.width as f64,
|
||||||
layer as usize,
|
layer as usize,
|
||||||
net,
|
net,
|
||||||
|
|
@ -373,7 +370,7 @@ impl DsnDesign {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for wire in self.pcb.wiring.wire_vec.iter() {
|
for wire in self.pcb.wiring.wires.iter() {
|
||||||
let layer = board
|
let layer = board
|
||||||
.layout()
|
.layout()
|
||||||
.drawing()
|
.drawing()
|
||||||
|
|
@ -393,7 +390,7 @@ impl DsnDesign {
|
||||||
0.0,
|
0.0,
|
||||||
(0.0, 0.0).into(),
|
(0.0, 0.0).into(),
|
||||||
0.0,
|
0.0,
|
||||||
&wire.path.coord_vec,
|
&wire.path.coords,
|
||||||
wire.path.width as f64,
|
wire.path.width as f64,
|
||||||
layer,
|
layer,
|
||||||
net,
|
net,
|
||||||
|
|
@ -426,7 +423,7 @@ impl DsnDesign {
|
||||||
|
|
||||||
fn layer(
|
fn layer(
|
||||||
board: &Board<DsnMesadata>,
|
board: &Board<DsnMesadata>,
|
||||||
layer_vec: &Vec<Layer>,
|
layers: &Vec<Layer>,
|
||||||
layername: &str,
|
layername: &str,
|
||||||
front: bool,
|
front: bool,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
|
|
@ -440,7 +437,7 @@ impl DsnDesign {
|
||||||
if front {
|
if front {
|
||||||
image_layer as usize
|
image_layer as usize
|
||||||
} else {
|
} else {
|
||||||
layer_vec.len() - image_layer as usize - 1
|
layers.len() - image_layer as usize - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ impl DsnRule {
|
||||||
fn from_dsn(rule: &super::structure::Rule) -> Self {
|
fn from_dsn(rule: &super::structure::Rule) -> Self {
|
||||||
Self {
|
Self {
|
||||||
width: rule.width as f64,
|
width: rule.width as f64,
|
||||||
clearance: rule.clearance_vec[0].value as f64, // picks the generic clearance only for now
|
clearance: rule.clearances[0].value as f64, // picks the generic clearance only for now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -43,7 +43,7 @@ impl DsnMesadata {
|
||||||
pub fn from_pcb(pcb: &Pcb) -> Self {
|
pub fn from_pcb(pcb: &Pcb) -> Self {
|
||||||
let layer_layername = BiHashMap::from_iter(
|
let layer_layername = BiHashMap::from_iter(
|
||||||
pcb.structure
|
pcb.structure
|
||||||
.layer_vec
|
.layers
|
||||||
.iter()
|
.iter()
|
||||||
.map(|layer| (layer.property.index, layer.name.clone())),
|
.map(|layer| (layer.property.index, layer.name.clone())),
|
||||||
);
|
);
|
||||||
|
|
@ -51,9 +51,9 @@ impl DsnMesadata {
|
||||||
// keeping this as a separate iter pass because it might be moved into a different struct later?
|
// keeping this as a separate iter pass because it might be moved into a different struct later?
|
||||||
let net_netname = BiHashMap::from_iter(
|
let net_netname = BiHashMap::from_iter(
|
||||||
pcb.network
|
pcb.network
|
||||||
.class_vec
|
.classes
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|class| &class.net_vec)
|
.flat_map(|class| &class.nets)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(net, netname)| (net, netname.clone())),
|
.map(|(net, netname)| (net, netname.clone())),
|
||||||
);
|
);
|
||||||
|
|
@ -61,10 +61,10 @@ impl DsnMesadata {
|
||||||
let mut net_netclass = HashMap::new();
|
let mut net_netclass = HashMap::new();
|
||||||
let class_rules = HashMap::from_iter(
|
let class_rules = HashMap::from_iter(
|
||||||
pcb.network
|
pcb.network
|
||||||
.class_vec
|
.classes
|
||||||
.iter()
|
.iter()
|
||||||
.inspect(|class| {
|
.inspect(|class| {
|
||||||
for netname in &class.net_vec {
|
for netname in &class.nets {
|
||||||
let net = net_netname.get_by_right(netname).unwrap();
|
let net = net_netname.get_by_right(netname).unwrap();
|
||||||
net_netclass.insert(*net, class.name.clone());
|
net_netclass.insert(*net, class.name.clone());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,4 @@ pub mod design;
|
||||||
pub mod mesadata;
|
pub mod mesadata;
|
||||||
mod read;
|
mod read;
|
||||||
mod structure;
|
mod structure;
|
||||||
mod structure2;
|
|
||||||
mod write;
|
mod write;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::common::ListToken;
|
use super::common::ListToken;
|
||||||
use super::structure2::Parser;
|
use super::structure::Parser;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use utf8_chars::BufReadCharsExt;
|
use utf8_chars::BufReadCharsExt;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,57 @@
|
||||||
use serde::{de::Error, Deserialize, Deserializer};
|
use super::common::ListToken;
|
||||||
|
use super::read::ReadDsn;
|
||||||
|
use super::read::{ListTokenizer, ParseError};
|
||||||
|
use super::write::ListWriter;
|
||||||
|
use super::write::WriteDsn;
|
||||||
|
use dsn_derive::ReadDsn;
|
||||||
|
use dsn_derive::WriteDsn;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
pub struct Dummy {}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
pub struct SesFile {
|
||||||
|
pub session: Session,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
pub struct Session {
|
||||||
|
#[anon]
|
||||||
|
pub id: String,
|
||||||
|
pub routes: Routes,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
pub struct Routes {
|
||||||
|
pub resolution: Resolution,
|
||||||
|
pub library_out: Library,
|
||||||
|
pub network_out: NetworkOut,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
pub struct NetworkOut {
|
||||||
|
#[vec("net")]
|
||||||
|
pub net: Vec<NetOut>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
pub struct NetOut {
|
||||||
|
#[anon]
|
||||||
|
pub name: String,
|
||||||
|
#[vec("wire")]
|
||||||
|
pub wire: Vec<Wire>,
|
||||||
|
#[vec("via")]
|
||||||
|
pub via: Vec<Via>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct DsnFile {
|
pub struct DsnFile {
|
||||||
pub pcb: Pcb,
|
pub pcb: Pcb,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Pcb {
|
pub struct Pcb {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub parser: Parser,
|
pub parser: Parser,
|
||||||
pub resolution: Resolution,
|
pub resolution: Resolution,
|
||||||
|
|
@ -18,7 +63,7 @@ pub struct Pcb {
|
||||||
pub wiring: Wiring,
|
pub wiring: Wiring,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(WriteDsn, Debug)]
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
pub string_quote: Option<char>,
|
pub string_quote: Option<char>,
|
||||||
pub space_in_quoted_tokens: Option<bool>,
|
pub space_in_quoted_tokens: Option<bool>,
|
||||||
|
|
@ -26,288 +71,366 @@ pub struct Parser {
|
||||||
pub host_version: Option<String>,
|
pub host_version: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Resolution {
|
pub struct Resolution {
|
||||||
|
#[anon]
|
||||||
pub unit: String,
|
pub unit: String,
|
||||||
pub value: u32,
|
#[anon]
|
||||||
|
pub value: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Structure {
|
pub struct Structure {
|
||||||
pub layer_vec: Vec<Layer>,
|
#[vec("layer")]
|
||||||
|
pub layers: Vec<Layer>,
|
||||||
pub boundary: Boundary,
|
pub boundary: Boundary,
|
||||||
pub plane_vec: Vec<Plane>,
|
#[vec("plane")]
|
||||||
|
pub planes: Vec<Plane>,
|
||||||
pub via: ViaNames,
|
pub via: ViaNames,
|
||||||
pub rule: Rule,
|
pub rule: Rule,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Layer {
|
pub struct Layer {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
pub property: Property,
|
pub property: Property,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Property {
|
pub struct Property {
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Boundary {
|
pub struct Boundary {
|
||||||
pub path: Path,
|
pub path: Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Plane {
|
pub struct Plane {
|
||||||
|
#[anon]
|
||||||
pub net: String,
|
pub net: String,
|
||||||
pub polygon: Polygon,
|
pub polygon: Polygon,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct ViaNames {
|
pub struct ViaNames {
|
||||||
pub name_vec: Vec<String>,
|
#[anon_vec]
|
||||||
|
pub names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Placement {
|
pub struct Placement {
|
||||||
pub component_vec: Vec<Component>,
|
#[vec("component")]
|
||||||
|
pub components: Vec<Component>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Component {
|
pub struct Component {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub place_vec: Vec<Place>,
|
#[vec("place")]
|
||||||
|
pub places: Vec<Place>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
pub struct Place {
|
pub struct Place {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
#[anon]
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
|
#[anon]
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
|
#[anon]
|
||||||
pub side: String,
|
pub side: String,
|
||||||
|
#[anon]
|
||||||
pub rotation: f32,
|
pub rotation: f32,
|
||||||
pub PN: Option<String>,
|
pub PN: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Library {
|
pub struct Library {
|
||||||
pub image_vec: Vec<Image>,
|
#[vec("image")]
|
||||||
pub padstack_vec: Vec<Padstack>,
|
pub images: Vec<Image>,
|
||||||
|
#[vec("padstack")]
|
||||||
|
pub padstacks: Vec<Padstack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub outline_vec: Vec<Outline>,
|
#[vec("outline")]
|
||||||
pub pin_vec: Vec<Pin>,
|
pub outlines: Vec<Outline>,
|
||||||
pub keepout_vec: Vec<Keepout>,
|
#[vec("pin")]
|
||||||
|
pub pins: Vec<Pin>,
|
||||||
|
#[vec("keepout")]
|
||||||
|
pub keepouts: Vec<Keepout>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Outline {
|
pub struct Outline {
|
||||||
pub path: Path,
|
pub path: Path,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Pin {
|
pub struct Pin {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub rotate: Option<f32>,
|
pub rotate: Option<f32>,
|
||||||
|
#[anon]
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
#[anon]
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
|
#[anon]
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Keepout {
|
|
||||||
pub idk: String,
|
|
||||||
pub shape_anonymous: Shape,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct Rotate {
|
pub struct Rotate {
|
||||||
pub angle: f32,
|
pub angle: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
|
pub struct Keepout {
|
||||||
|
#[anon]
|
||||||
|
pub idk: String,
|
||||||
|
#[anon]
|
||||||
|
pub shape: Shape,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Padstack {
|
pub struct Padstack {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub shape_vec: Vec<Shape>,
|
#[vec("shape")]
|
||||||
|
pub shapes: Vec<Shape>,
|
||||||
pub attach: bool,
|
pub attach: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
// TODO: derive for enums if more than this single one is needed
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Shape {
|
pub enum Shape {
|
||||||
#[serde(rename = "circle")]
|
|
||||||
Circle(Circle),
|
Circle(Circle),
|
||||||
#[serde(rename = "rect")]
|
|
||||||
Rect(Rect),
|
Rect(Rect),
|
||||||
#[serde(rename = "path")]
|
|
||||||
Path(Path),
|
Path(Path),
|
||||||
#[serde(rename = "polygon")]
|
|
||||||
Polygon(Polygon),
|
Polygon(Polygon),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
impl<R: std::io::BufRead> ReadDsn<R> for Shape {
|
||||||
|
fn read_dsn(tokenizer: &mut ListTokenizer<R>) -> Result<Self, ParseError> {
|
||||||
|
let name = tokenizer.consume_token()?.expect_any_start()?;
|
||||||
|
let value = match name.as_str() {
|
||||||
|
"circle" => Ok(Shape::Circle(tokenizer.read_value()?)),
|
||||||
|
"rect" => Ok(Shape::Rect(tokenizer.read_value()?)),
|
||||||
|
"path" => Ok(Shape::Path(tokenizer.read_value()?)),
|
||||||
|
"polygon" => Ok(Shape::Polygon(tokenizer.read_value()?)),
|
||||||
|
_ => Err(ParseError::Expected("a different keyword")),
|
||||||
|
};
|
||||||
|
tokenizer.consume_token()?.expect_end()?;
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: std::io::Write> WriteDsn<W> for Shape {
|
||||||
|
fn write_dsn(&self, writer: &mut ListWriter<W>) -> Result<(), std::io::Error> {
|
||||||
|
match self {
|
||||||
|
Self::Circle(inner) => writer.write_named("circle", inner),
|
||||||
|
Self::Rect(inner) => writer.write_named("rect", inner),
|
||||||
|
Self::Path(inner) => writer.write_named("path", inner),
|
||||||
|
Self::Polygon(inner) => writer.write_named("polygon", inner),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Circle {
|
pub struct Circle {
|
||||||
|
#[anon]
|
||||||
pub layer: String,
|
pub layer: String,
|
||||||
|
#[anon]
|
||||||
pub diameter: u32,
|
pub diameter: u32,
|
||||||
#[serde(deserialize_with = "de_point_optional")]
|
#[anon]
|
||||||
pub offset: Option<Point>,
|
pub offset: Option<Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Network {
|
pub struct Network {
|
||||||
pub net_vec: Vec<NetPinAssignments>,
|
#[vec("net")]
|
||||||
pub class_vec: Vec<Class>,
|
pub nets: Vec<NetPinAssignments>,
|
||||||
|
#[vec("class")]
|
||||||
|
pub classes: Vec<Class>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
// dsn names this "net", but it's a structure unrelated to "net" in wiring or elsewhere
|
// dsn names this "net", but it's a structure unrelated to "net" in wiring or elsewhere
|
||||||
pub struct NetPinAssignments {
|
pub struct NetPinAssignments {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub pins: Pins,
|
pub pins: Pins,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Pins {
|
pub struct Pins {
|
||||||
|
#[anon_vec]
|
||||||
pub names: Vec<String>,
|
pub names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub net_vec: Vec<String>,
|
#[anon_vec]
|
||||||
|
pub nets: Vec<String>,
|
||||||
pub circuit: Circuit,
|
pub circuit: Circuit,
|
||||||
pub rule: Rule,
|
pub rule: Rule,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Circuit {
|
pub struct Circuit {
|
||||||
pub use_via: UseVia,
|
pub use_via: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct UseVia {
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct Wiring {
|
pub struct Wiring {
|
||||||
pub wire_vec: Vec<Wire>,
|
#[vec("wire")]
|
||||||
pub via_vec: Vec<Via>,
|
pub wires: Vec<Wire>,
|
||||||
|
#[vec("via")]
|
||||||
|
pub vias: Vec<Via>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Wire {
|
pub struct Wire {
|
||||||
pub path: Path,
|
pub path: Path,
|
||||||
pub net: String,
|
pub net: String,
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// structs that appear in multiple places
|
////////////////////////////////////////////
|
||||||
|
// structs that appear in multiple places //
|
||||||
// This type isn't deserialized as is. Instead, Vec<Point> is converted from
|
////////////////////////////////////////////
|
||||||
// what's effectively Vec<f32> (with even length) in the file.
|
|
||||||
// Use #[serde(deserialize_with = "de_points")] for Vec<Point>
|
|
||||||
// and #[serde(deserialize_with = "de_point_optional")] for a single Point.
|
|
||||||
|
|
||||||
|
// This type isn't meant to be deserialized as is (single points are
|
||||||
|
// more conveniently represented as fields on the enclosing struct)
|
||||||
|
// It exists to give a way to read arrays of coordinates
|
||||||
|
// (and enforce that such an array actually contains a whole number of points)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Point {
|
pub struct Point {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to deserialize Option<Point>
|
// Custom impl for the case described above
|
||||||
fn de_point_optional<'de, D>(deserializer: D) -> Result<Option<Point>, D::Error>
|
impl<R: std::io::BufRead> ReadDsn<R> for Vec<Point> {
|
||||||
where
|
fn read_dsn(tokenizer: &mut ListTokenizer<R>) -> Result<Self, ParseError> {
|
||||||
D: Deserializer<'de>,
|
let mut array = Vec::<Point>::new();
|
||||||
{
|
loop {
|
||||||
let mut vec: Vec<Point> = Vec::<f32>::deserialize(deserializer)?
|
let token = tokenizer.consume_token()?;
|
||||||
.chunks(2)
|
if let ListToken::Leaf { value: ref x } = token {
|
||||||
.map(|pair| {
|
let x = x.parse::<f32>().unwrap();
|
||||||
// 0th index is guaranteed to exist by `.chunks()`
|
let y = tokenizer.read_value::<f32>()?;
|
||||||
// (it ends iteration instead of emitting an empty Vec)
|
array.push(Point { x, y });
|
||||||
let x = pair[0];
|
|
||||||
// but if the file is malformed we may get an odd number of floats
|
|
||||||
let y = *pair.get(1).ok_or(Error::custom(
|
|
||||||
"expected paired x y coordinates, list ended at x",
|
|
||||||
))?;
|
|
||||||
|
|
||||||
Ok(Point { x, y })
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<Point>, D::Error>>()?;
|
|
||||||
|
|
||||||
if vec.len() > 1 {
|
|
||||||
Err(Error::custom("expected a single pair of coordinates"))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(vec.pop())
|
tokenizer.return_token(token);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(array)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to deserialize Vec<Point>.
|
impl<R: std::io::BufRead> ReadDsn<R> for Option<Point> {
|
||||||
fn de_points<'de, D>(deserializer: D) -> Result<Vec<Point>, D::Error>
|
fn read_dsn(tokenizer: &mut ListTokenizer<R>) -> Result<Self, ParseError> {
|
||||||
where
|
let token = tokenizer.consume_token()?;
|
||||||
D: Deserializer<'de>,
|
if let ListToken::Leaf { value: ref x } = token {
|
||||||
{
|
let x = x.parse::<f32>().unwrap();
|
||||||
Vec::<f32>::deserialize(deserializer)?
|
let y = tokenizer.read_value::<f32>()?;
|
||||||
.chunks(2)
|
Ok(Some(Point { x, y }))
|
||||||
.map(|pair| {
|
} else {
|
||||||
// 0th index is guaranteed to exist by `.chunks()`
|
tokenizer.return_token(token);
|
||||||
// (it ends iteration instead of emitting an empty Vec)
|
Ok(None)
|
||||||
let x = pair[0];
|
}
|
||||||
// but if the file is malformed we may get an odd number of floats
|
}
|
||||||
let y = *pair.get(1).ok_or(Error::custom(
|
|
||||||
"expected paired x y coordinates, list ended at x",
|
|
||||||
))?;
|
|
||||||
|
|
||||||
Ok(Point { x, y })
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<Point>, D::Error>>()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
impl<W: std::io::Write> WriteDsn<W> for Vec<Point> {
|
||||||
|
fn write_dsn(&self, writer: &mut ListWriter<W>) -> Result<(), std::io::Error> {
|
||||||
|
for elem in self {
|
||||||
|
writer.write_value(&elem.x)?;
|
||||||
|
writer.write_value(&elem.y)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: std::io::Write> WriteDsn<W> for Option<Point> {
|
||||||
|
fn write_dsn(&self, writer: &mut ListWriter<W>) -> Result<(), std::io::Error> {
|
||||||
|
if let Some(value) = self {
|
||||||
|
writer.write_value(&value.x)?;
|
||||||
|
writer.write_value(&value.y)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Polygon {
|
pub struct Polygon {
|
||||||
|
#[anon]
|
||||||
pub layer: String,
|
pub layer: String,
|
||||||
|
#[anon]
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
#[serde(deserialize_with = "de_points")]
|
#[anon]
|
||||||
pub coord_vec: Vec<Point>,
|
pub coords: Vec<Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Path {
|
pub struct Path {
|
||||||
|
#[anon]
|
||||||
pub layer: String,
|
pub layer: String,
|
||||||
|
#[anon]
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
#[serde(deserialize_with = "de_points")]
|
#[anon]
|
||||||
pub coord_vec: Vec<Point>,
|
pub coords: Vec<Point>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
|
#[anon]
|
||||||
pub layer: String,
|
pub layer: String,
|
||||||
|
#[anon]
|
||||||
pub x1: f32,
|
pub x1: f32,
|
||||||
|
#[anon]
|
||||||
pub y1: f32,
|
pub y1: f32,
|
||||||
|
#[anon]
|
||||||
pub x2: f32,
|
pub x2: f32,
|
||||||
|
#[anon]
|
||||||
pub y2: f32,
|
pub y2: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Via {
|
pub struct Via {
|
||||||
|
#[anon]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
#[anon]
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
|
#[anon]
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
pub net: String,
|
pub net: String,
|
||||||
pub r#type: String,
|
pub r#type: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Rule {
|
pub struct Rule {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
pub clearance_vec: Vec<Clearance>,
|
#[vec("clearance")]
|
||||||
|
pub clearances: Vec<Clearance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(ReadDsn, WriteDsn, Debug)]
|
||||||
pub struct Clearance {
|
pub struct Clearance {
|
||||||
|
#[anon]
|
||||||
pub value: f32,
|
pub value: f32,
|
||||||
pub r#type: Option<String>,
|
pub r#type: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,436 +0,0 @@
|
||||||
use super::common::ListToken;
|
|
||||||
use super::read::ReadDsn;
|
|
||||||
use super::read::{ListTokenizer, ParseError};
|
|
||||||
use super::write::ListWriter;
|
|
||||||
use super::write::WriteDsn;
|
|
||||||
use dsn_derive::ReadDsn;
|
|
||||||
use dsn_derive::WriteDsn;
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Dummy {}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct SesFile {
|
|
||||||
pub session: Session,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Session {
|
|
||||||
#[anon]
|
|
||||||
pub id: String,
|
|
||||||
pub routes: Routes,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Routes {
|
|
||||||
pub resolution: Resolution,
|
|
||||||
pub library_out: Library,
|
|
||||||
pub network_out: NetworkOut,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct NetworkOut {
|
|
||||||
#[vec("net")]
|
|
||||||
pub net: Vec<NetOut>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct NetOut {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
#[vec("wire")]
|
|
||||||
pub wire: Vec<Wire>,
|
|
||||||
#[vec("via")]
|
|
||||||
pub via: Vec<Via>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct DsnFile {
|
|
||||||
pub pcb: Pcb,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Pcb {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
pub parser: Parser,
|
|
||||||
pub resolution: Resolution,
|
|
||||||
pub unit: String,
|
|
||||||
pub structure: Structure,
|
|
||||||
pub placement: Placement,
|
|
||||||
pub library: Library,
|
|
||||||
pub network: Network,
|
|
||||||
pub wiring: Wiring,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(WriteDsn, Debug)]
|
|
||||||
pub struct Parser {
|
|
||||||
pub string_quote: Option<char>,
|
|
||||||
pub space_in_quoted_tokens: Option<bool>,
|
|
||||||
pub host_cad: Option<String>,
|
|
||||||
pub host_version: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Resolution {
|
|
||||||
#[anon]
|
|
||||||
pub unit: String,
|
|
||||||
#[anon]
|
|
||||||
pub value: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Structure {
|
|
||||||
#[vec("layer")]
|
|
||||||
pub layers: Vec<Layer>,
|
|
||||||
pub boundary: Boundary,
|
|
||||||
#[vec("plane")]
|
|
||||||
pub planes: Vec<Plane>,
|
|
||||||
pub via: ViaNames,
|
|
||||||
pub rule: Rule,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Layer {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
pub r#type: String,
|
|
||||||
pub property: Property,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Property {
|
|
||||||
pub index: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Boundary {
|
|
||||||
pub path: Path,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Plane {
|
|
||||||
#[anon]
|
|
||||||
pub net: String,
|
|
||||||
pub polygon: Polygon,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct ViaNames {
|
|
||||||
#[anon_vec]
|
|
||||||
pub names: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Placement {
|
|
||||||
#[vec("component")]
|
|
||||||
pub components: Vec<Component>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Component {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
#[vec("place")]
|
|
||||||
pub places: Vec<Place>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub struct Place {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
#[anon]
|
|
||||||
pub x: f32,
|
|
||||||
#[anon]
|
|
||||||
pub y: f32,
|
|
||||||
#[anon]
|
|
||||||
pub side: String,
|
|
||||||
#[anon]
|
|
||||||
pub rotation: f32,
|
|
||||||
pub PN: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Library {
|
|
||||||
#[vec("image")]
|
|
||||||
pub images: Vec<Image>,
|
|
||||||
#[vec("padstack")]
|
|
||||||
pub padstacks: Vec<Padstack>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Image {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
#[vec("outline")]
|
|
||||||
pub outlines: Vec<Outline>,
|
|
||||||
#[vec("pin")]
|
|
||||||
pub pins: Vec<Pin>,
|
|
||||||
#[vec("keepout")]
|
|
||||||
pub keepouts: Vec<Keepout>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Outline {
|
|
||||||
pub path: Path,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Pin {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
pub rotate: Option<f32>,
|
|
||||||
#[anon]
|
|
||||||
pub id: String,
|
|
||||||
#[anon]
|
|
||||||
pub x: f32,
|
|
||||||
#[anon]
|
|
||||||
pub y: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Rotate {
|
|
||||||
pub angle: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Keepout {
|
|
||||||
#[anon]
|
|
||||||
pub idk: String,
|
|
||||||
#[anon]
|
|
||||||
pub shape: Shape,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Padstack {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
#[vec("shape")]
|
|
||||||
pub shapes: Vec<Shape>,
|
|
||||||
pub attach: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: derive for enums if more than this single one is needed
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum Shape {
|
|
||||||
Circle(Circle),
|
|
||||||
Rect(Rect),
|
|
||||||
Path(Path),
|
|
||||||
Polygon(Polygon),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: std::io::BufRead> ReadDsn<R> for Shape {
|
|
||||||
fn read_dsn(tokenizer: &mut ListTokenizer<R>) -> Result<Self, ParseError> {
|
|
||||||
let name = tokenizer.consume_token()?.expect_any_start()?;
|
|
||||||
let value = match name.as_str() {
|
|
||||||
"circle" => Ok(Shape::Circle(tokenizer.read_value()?)),
|
|
||||||
"rect" => Ok(Shape::Rect(tokenizer.read_value()?)),
|
|
||||||
"path" => Ok(Shape::Path(tokenizer.read_value()?)),
|
|
||||||
"polygon" => Ok(Shape::Polygon(tokenizer.read_value()?)),
|
|
||||||
_ => Err(ParseError::Expected("a different keyword")),
|
|
||||||
};
|
|
||||||
tokenizer.consume_token()?.expect_end()?;
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: std::io::Write> WriteDsn<W> for Shape {
|
|
||||||
fn write_dsn(&self, writer: &mut ListWriter<W>) -> Result<(), std::io::Error> {
|
|
||||||
match self {
|
|
||||||
Self::Circle(inner) => writer.write_named("circle", inner),
|
|
||||||
Self::Rect(inner) => writer.write_named("rect", inner),
|
|
||||||
Self::Path(inner) => writer.write_named("path", inner),
|
|
||||||
Self::Polygon(inner) => writer.write_named("polygon", inner),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Circle {
|
|
||||||
#[anon]
|
|
||||||
pub layer: String,
|
|
||||||
#[anon]
|
|
||||||
pub diameter: u32,
|
|
||||||
#[anon]
|
|
||||||
pub offset: Option<Point>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Network {
|
|
||||||
#[vec("net")]
|
|
||||||
pub nets: Vec<NetPinAssignments>,
|
|
||||||
#[vec("class")]
|
|
||||||
pub classes: Vec<Class>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
// dsn names this "net", but it's a structure unrelated to "net" in wiring or elsewhere
|
|
||||||
pub struct NetPinAssignments {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
pub pins: Pins,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Pins {
|
|
||||||
#[anon_vec]
|
|
||||||
pub names: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Class {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
#[anon_vec]
|
|
||||||
pub nets: Vec<String>,
|
|
||||||
pub circuit: Circuit,
|
|
||||||
pub rule: Rule,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Circuit {
|
|
||||||
pub use_via: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Wiring {
|
|
||||||
#[vec("wire")]
|
|
||||||
pub wires: Vec<Wire>,
|
|
||||||
#[vec("via")]
|
|
||||||
pub vias: Vec<Via>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Wire {
|
|
||||||
pub path: Path,
|
|
||||||
pub net: String,
|
|
||||||
pub r#type: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////
|
|
||||||
// structs that appear in multiple places //
|
|
||||||
////////////////////////////////////////////
|
|
||||||
|
|
||||||
// This type isn't meant to be deserialized as is (single points are
|
|
||||||
// more conveniently represented as fields on the enclosing struct)
|
|
||||||
// It exists to give a way to read arrays of coordinates
|
|
||||||
// (and enforce that such an array actually contains a whole number of points)
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Point {
|
|
||||||
pub x: f32,
|
|
||||||
pub y: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom impl for the case described above
|
|
||||||
impl<R: std::io::BufRead> ReadDsn<R> for Vec<Point> {
|
|
||||||
fn read_dsn(tokenizer: &mut ListTokenizer<R>) -> Result<Self, ParseError> {
|
|
||||||
let mut array = Vec::<Point>::new();
|
|
||||||
loop {
|
|
||||||
let token = tokenizer.consume_token()?;
|
|
||||||
if let ListToken::Leaf { value: ref x } = token {
|
|
||||||
let x = x.parse::<f32>().unwrap();
|
|
||||||
let y = tokenizer.read_value::<f32>()?;
|
|
||||||
array.push(Point { x, y });
|
|
||||||
} else {
|
|
||||||
tokenizer.return_token(token);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(array)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: std::io::BufRead> ReadDsn<R> for Option<Point> {
|
|
||||||
fn read_dsn(tokenizer: &mut ListTokenizer<R>) -> Result<Self, ParseError> {
|
|
||||||
let token = tokenizer.consume_token()?;
|
|
||||||
if let ListToken::Leaf { value: ref x } = token {
|
|
||||||
let x = x.parse::<f32>().unwrap();
|
|
||||||
let y = tokenizer.read_value::<f32>()?;
|
|
||||||
Ok(Some(Point { x, y }))
|
|
||||||
} else {
|
|
||||||
tokenizer.return_token(token);
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: std::io::Write> WriteDsn<W> for Vec<Point> {
|
|
||||||
fn write_dsn(&self, writer: &mut ListWriter<W>) -> Result<(), std::io::Error> {
|
|
||||||
for elem in self {
|
|
||||||
writer.write_value(&elem.x)?;
|
|
||||||
writer.write_value(&elem.y)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: std::io::Write> WriteDsn<W> for Option<Point> {
|
|
||||||
fn write_dsn(&self, writer: &mut ListWriter<W>) -> Result<(), std::io::Error> {
|
|
||||||
if let Some(value) = self {
|
|
||||||
writer.write_value(&value.x)?;
|
|
||||||
writer.write_value(&value.y)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Polygon {
|
|
||||||
#[anon]
|
|
||||||
pub layer: String,
|
|
||||||
#[anon]
|
|
||||||
pub width: f32,
|
|
||||||
#[anon]
|
|
||||||
pub coords: Vec<Point>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Path {
|
|
||||||
#[anon]
|
|
||||||
pub layer: String,
|
|
||||||
#[anon]
|
|
||||||
pub width: f32,
|
|
||||||
#[anon]
|
|
||||||
pub coords: Vec<Point>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Rect {
|
|
||||||
#[anon]
|
|
||||||
pub layer: String,
|
|
||||||
#[anon]
|
|
||||||
pub x1: f32,
|
|
||||||
#[anon]
|
|
||||||
pub y1: f32,
|
|
||||||
#[anon]
|
|
||||||
pub x2: f32,
|
|
||||||
#[anon]
|
|
||||||
pub y2: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Via {
|
|
||||||
#[anon]
|
|
||||||
pub name: String,
|
|
||||||
#[anon]
|
|
||||||
pub x: i32,
|
|
||||||
#[anon]
|
|
||||||
pub y: i32,
|
|
||||||
pub net: String,
|
|
||||||
pub r#type: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Rule {
|
|
||||||
pub width: f32,
|
|
||||||
#[vec("clearance")]
|
|
||||||
pub clearances: Vec<Clearance>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ReadDsn, WriteDsn, Debug)]
|
|
||||||
pub struct Clearance {
|
|
||||||
#[anon]
|
|
||||||
pub value: f32,
|
|
||||||
pub r#type: Option<String>,
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue