dsn: replace structure with new renamed structure2

This commit is contained in:
Mikolaj Wielgus 2024-06-16 14:05:49 +02:00
parent 4ec9467649
commit 8c2ad87bf0
6 changed files with 298 additions and 615 deletions

View File

@ -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
} }
} }

View File

@ -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());
} }

View File

@ -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;

View File

@ -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;

View File

@ -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]; } else {
// but if the file is malformed we may get an odd number of floats tokenizer.return_token(token);
let y = *pair.get(1).ok_or(Error::custom( break;
"expected paired x y coordinates, list ended at x", }
))?; }
Ok(array)
Ok(Point { x, y })
})
.collect::<Result<Vec<Point>, D::Error>>()?;
if vec.len() > 1 {
Err(Error::custom("expected a single pair of coordinates"))
} else {
Ok(vec.pop())
} }
} }
// 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>,
} }

View File

@ -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>,
}