From 8c2ad87bf075710d33afe3ae4e587f52ccff4205 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Sun, 16 Jun 2024 14:05:49 +0200 Subject: [PATCH] dsn: replace structure with new renamed structure2 --- src/dsn/design.rs | 93 +++++---- src/dsn/mesadata.rs | 12 +- src/dsn/mod.rs | 1 - src/dsn/read.rs | 2 +- src/dsn/structure.rs | 369 +++++++++++++++++++++++------------ src/dsn/structure2.rs | 436 ------------------------------------------ 6 files changed, 298 insertions(+), 615 deletions(-) delete mode 100644 src/dsn/structure2.rs diff --git a/src/dsn/design.rs b/src/dsn/design.rs index b7714da..c62d1f0 100644 --- a/src/dsn/design.rs +++ b/src/dsn/design.rs @@ -34,17 +34,17 @@ impl DsnDesign { let reader = std::io::BufReader::new(file); let mut list_reader = super::read::ListTokenizer::new(reader); - let dsn = list_reader.read_value::(); + let dsn = list_reader.read_value::(); // TODO: make_board() still uses the old version of structure.rs // so we can't pass the data to topola for real if let Ok(dsn) = dsn { - use super::structure2::*; + use super::structure::*; // (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 writer = std::io::BufWriter::new(file2); 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 { dbg!(dsn); + todo!(); } - - let contents = std::fs::read_to_string(filename)?; - - Self::load_from_string(contents) } pub fn load_from_string(contents: String) -> Result { - let pcb = de::from_str::(&contents) + /*let dsn = de::from_str::(&contents) .map_err(|err| LoadingError::Syntax(err))? .pcb; - Ok(Self { pcb }) + Ok(Self { pcb })*/ + let mut list_reader = super::read::ListTokenizer::new(contents.as_bytes()); + let dsn = list_reader.read_value::(); + + Ok(Self { + pcb: dsn.unwrap().pcb, + }) } pub fn make_board(&self) -> Board { let mesadata = DsnMesadata::from_pcb(&self.pcb); let mut board = Board::new(Layout::new(Drawing::new( mesadata, - self.pcb.structure.layer_vec.len(), + self.pcb.structure.layers.len(), ))); // mapping of pin -> net prepared for adding pins let pin_nets = HashMap::::from_iter( self.pcb .network - .net_vec + .nets .iter() .map(|net_pin_assignments| { // resolve the id so we don't work with strings @@ -158,34 +163,34 @@ impl DsnDesign { ); // add pins from components - for component in &self.pcb.placement.component_vec { - for place in &component.place_vec { + for component in &self.pcb.placement.components { + for place in &component.places { let image = self .pcb .library - .image_vec + .images .iter() .find(|image| image.name == component.name) .unwrap(); - for pin in &image.pin_vec { + for pin in &image.pins { let pinname = format!("{}-{}", place.name, pin.id); let net = pin_nets.get(&pinname).unwrap(); let padstack = &self .pcb .library - .padstack_vec + .padstacks .iter() .find(|padstack| padstack.name == pin.name) .unwrap(); - for shape in padstack.shape_vec.iter() { + for shape in padstack.shapes.iter() { match shape { Shape::Circle(circle) => { let layer = Self::layer( &mut board, - &self.pcb.structure.layer_vec, + &self.pcb.structure.layers, &circle.layer, place.side == "front", ); @@ -204,7 +209,7 @@ impl DsnDesign { Shape::Rect(rect) => { let layer = Self::layer( &mut board, - &self.pcb.structure.layer_vec, + &self.pcb.structure.layers, &rect.layer, place.side == "front", ); @@ -226,7 +231,7 @@ impl DsnDesign { Shape::Path(path) => { let layer = Self::layer( &mut board, - &self.pcb.structure.layer_vec, + &self.pcb.structure.layers, &path.layer, place.side == "front", ); @@ -236,7 +241,7 @@ impl DsnDesign { place.rotation as f64, (pin.x as f64, pin.y as f64).into(), pin.rotate.unwrap_or(0.0) as f64, - &path.coord_vec, + &path.coords, path.width as f64, layer as usize, *net, @@ -246,7 +251,7 @@ impl DsnDesign { Shape::Polygon(polygon) => { let layer = Self::layer( &mut board, - &self.pcb.structure.layer_vec, + &self.pcb.structure.layers, &polygon.layer, place.side == "front", ); @@ -256,7 +261,7 @@ impl DsnDesign { place.rotation as f64, (pin.x as f64, pin.y as f64).into(), pin.rotate.unwrap_or(0.0) as f64, - &polygon.coord_vec, + &polygon.coords, polygon.width as f64, layer as usize, *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 .layout() .drawing() @@ -281,17 +286,17 @@ impl DsnDesign { let padstack = &self .pcb .library - .padstack_vec + .padstacks .iter() .find(|padstack| padstack.name == via.name) .unwrap(); - for shape in &padstack.shape_vec { + for shape in &padstack.shapes { match shape { Shape::Circle(circle) => { let layer = Self::layer( &mut board, - &self.pcb.structure.layer_vec, + &self.pcb.structure.layers, &circle.layer, true, ); @@ -308,12 +313,8 @@ impl DsnDesign { ) } Shape::Rect(rect) => { - let layer = Self::layer( - &mut board, - &self.pcb.structure.layer_vec, - &rect.layer, - true, - ); + let layer = + Self::layer(&mut board, &self.pcb.structure.layers, &rect.layer, true); Self::add_rect( &mut board, (0.0, 0.0).into(), @@ -330,19 +331,15 @@ impl DsnDesign { ) } Shape::Path(path) => { - let layer = Self::layer( - &mut board, - &self.pcb.structure.layer_vec, - &path.layer, - true, - ); + let layer = + Self::layer(&mut board, &self.pcb.structure.layers, &path.layer, true); Self::add_path( &mut board, (0.0, 0.0).into(), 0.0, (0.0, 0.0).into(), 0.0, - &path.coord_vec, + &path.coords, path.width as f64, layer as usize, net, @@ -352,7 +349,7 @@ impl DsnDesign { Shape::Polygon(polygon) => { let layer = Self::layer( &mut board, - &self.pcb.structure.layer_vec, + &self.pcb.structure.layers, &polygon.layer, true, ); @@ -362,7 +359,7 @@ impl DsnDesign { 0.0, (0.0, 0.0).into(), 0.0, - &polygon.coord_vec, + &polygon.coords, polygon.width as f64, layer as usize, 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 .layout() .drawing() @@ -393,7 +390,7 @@ impl DsnDesign { 0.0, (0.0, 0.0).into(), 0.0, - &wire.path.coord_vec, + &wire.path.coords, wire.path.width as f64, layer, net, @@ -426,7 +423,7 @@ impl DsnDesign { fn layer( board: &Board, - layer_vec: &Vec, + layers: &Vec, layername: &str, front: bool, ) -> usize { @@ -440,7 +437,7 @@ impl DsnDesign { if front { image_layer as usize } else { - layer_vec.len() - image_layer as usize - 1 + layers.len() - image_layer as usize - 1 } } diff --git a/src/dsn/mesadata.rs b/src/dsn/mesadata.rs index e3390bd..e31e42e 100644 --- a/src/dsn/mesadata.rs +++ b/src/dsn/mesadata.rs @@ -18,7 +18,7 @@ impl DsnRule { fn from_dsn(rule: &super::structure::Rule) -> Self { Self { 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 { let layer_layername = BiHashMap::from_iter( pcb.structure - .layer_vec + .layers .iter() .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? let net_netname = BiHashMap::from_iter( pcb.network - .class_vec + .classes .iter() - .flat_map(|class| &class.net_vec) + .flat_map(|class| &class.nets) .enumerate() .map(|(net, netname)| (net, netname.clone())), ); @@ -61,10 +61,10 @@ impl DsnMesadata { let mut net_netclass = HashMap::new(); let class_rules = HashMap::from_iter( pcb.network - .class_vec + .classes .iter() .inspect(|class| { - for netname in &class.net_vec { + for netname in &class.nets { let net = net_netname.get_by_right(netname).unwrap(); net_netclass.insert(*net, class.name.clone()); } diff --git a/src/dsn/mod.rs b/src/dsn/mod.rs index a58be18..28b6830 100644 --- a/src/dsn/mod.rs +++ b/src/dsn/mod.rs @@ -4,5 +4,4 @@ pub mod design; pub mod mesadata; mod read; mod structure; -mod structure2; mod write; diff --git a/src/dsn/read.rs b/src/dsn/read.rs index f259de7..408e55c 100644 --- a/src/dsn/read.rs +++ b/src/dsn/read.rs @@ -1,5 +1,5 @@ use super::common::ListToken; -use super::structure2::Parser; +use super::structure::Parser; use thiserror::Error; use utf8_chars::BufReadCharsExt; diff --git a/src/dsn/structure.rs b/src/dsn/structure.rs index 6a53e8b..eccc704 100644 --- a/src/dsn/structure.rs +++ b/src/dsn/structure.rs @@ -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, +} + +#[derive(ReadDsn, WriteDsn, Debug)] +pub struct NetOut { + #[anon] + pub name: String, + #[vec("wire")] + pub wire: Vec, + #[vec("via")] + pub via: Vec, +} + +#[derive(ReadDsn, WriteDsn, Debug)] pub struct DsnFile { pub pcb: Pcb, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Pcb { + #[anon] pub name: String, pub parser: Parser, pub resolution: Resolution, @@ -18,7 +63,7 @@ pub struct Pcb { pub wiring: Wiring, } -#[derive(Deserialize, Debug)] +#[derive(WriteDsn, Debug)] pub struct Parser { pub string_quote: Option, pub space_in_quoted_tokens: Option, @@ -26,288 +71,366 @@ pub struct Parser { pub host_version: Option, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Resolution { + #[anon] pub unit: String, - pub value: u32, + #[anon] + pub value: f32, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Structure { - pub layer_vec: Vec, + #[vec("layer")] + pub layers: Vec, pub boundary: Boundary, - pub plane_vec: Vec, + #[vec("plane")] + pub planes: Vec, pub via: ViaNames, pub rule: Rule, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Layer { + #[anon] pub name: String, pub r#type: String, pub property: Property, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Property { pub index: usize, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Boundary { pub path: Path, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Plane { + #[anon] pub net: String, pub polygon: Polygon, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct ViaNames { - pub name_vec: Vec, + #[anon_vec] + pub names: Vec, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Placement { - pub component_vec: Vec, + #[vec("component")] + pub components: Vec, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Component { + #[anon] pub name: String, - pub place_vec: Vec, + #[vec("place")] + pub places: Vec, } -#[derive(Deserialize, Debug)] +#[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, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Library { - pub image_vec: Vec, - pub padstack_vec: Vec, + #[vec("image")] + pub images: Vec, + #[vec("padstack")] + pub padstacks: Vec, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Image { + #[anon] pub name: String, - pub outline_vec: Vec, - pub pin_vec: Vec, - pub keepout_vec: Vec, + #[vec("outline")] + pub outlines: Vec, + #[vec("pin")] + pub pins: Vec, + #[vec("keepout")] + pub keepouts: Vec, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Outline { pub path: Path, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Pin { + #[anon] pub name: String, pub rotate: Option, + #[anon] pub id: String, + #[anon] pub x: f32, + #[anon] pub y: f32, } -#[derive(Deserialize, Debug)] -pub struct Keepout { - pub idk: String, - pub shape_anonymous: Shape, -} - -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Rotate { 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 { + #[anon] pub name: String, - pub shape_vec: Vec, + #[vec("shape")] + pub shapes: Vec, pub attach: bool, } -#[derive(Deserialize, Debug)] +// TODO: derive for enums if more than this single one is needed +#[derive(Debug)] pub enum Shape { - #[serde(rename = "circle")] Circle(Circle), - #[serde(rename = "rect")] Rect(Rect), - #[serde(rename = "path")] Path(Path), - #[serde(rename = "polygon")] Polygon(Polygon), } -#[derive(Deserialize, Debug)] +impl ReadDsn for Shape { + fn read_dsn(tokenizer: &mut ListTokenizer) -> Result { + 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 WriteDsn for Shape { + fn write_dsn(&self, writer: &mut ListWriter) -> 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, - #[serde(deserialize_with = "de_point_optional")] + #[anon] pub offset: Option, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Network { - pub net_vec: Vec, - pub class_vec: Vec, + #[vec("net")] + pub nets: Vec, + #[vec("class")] + pub classes: Vec, } -#[derive(Deserialize, Debug)] +#[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(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Pins { + #[anon_vec] pub names: Vec, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Class { + #[anon] pub name: String, - pub net_vec: Vec, + #[anon_vec] + pub nets: Vec, pub circuit: Circuit, pub rule: Rule, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Circuit { - pub use_via: UseVia, + pub use_via: String, } -#[derive(Deserialize, Debug)] -pub struct UseVia { - pub name: String, -} - -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Wiring { - pub wire_vec: Vec, - pub via_vec: Vec, + #[vec("wire")] + pub wires: Vec, + #[vec("via")] + pub vias: Vec, } -#[derive(Deserialize, Debug)] +#[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 deserialized as is. Instead, Vec is converted from -// what's effectively Vec (with even length) in the file. -// Use #[serde(deserialize_with = "de_points")] for Vec -// and #[serde(deserialize_with = "de_point_optional")] for a single Point. +//////////////////////////////////////////// +// 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, } -// Used to deserialize Option -fn de_point_optional<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let mut vec: Vec = Vec::::deserialize(deserializer)? - .chunks(2) - .map(|pair| { - // 0th index is guaranteed to exist by `.chunks()` - // (it ends iteration instead of emitting an empty Vec) - 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::, D::Error>>()?; - - if vec.len() > 1 { - Err(Error::custom("expected a single pair of coordinates")) - } else { - Ok(vec.pop()) +// Custom impl for the case described above +impl ReadDsn for Vec { + fn read_dsn(tokenizer: &mut ListTokenizer) -> Result { + let mut array = Vec::::new(); + loop { + let token = tokenizer.consume_token()?; + if let ListToken::Leaf { value: ref x } = token { + let x = x.parse::().unwrap(); + let y = tokenizer.read_value::()?; + array.push(Point { x, y }); + } else { + tokenizer.return_token(token); + break; + } + } + Ok(array) } } -// Used to deserialize Vec. -fn de_points<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - Vec::::deserialize(deserializer)? - .chunks(2) - .map(|pair| { - // 0th index is guaranteed to exist by `.chunks()` - // (it ends iteration instead of emitting an empty Vec) - 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::, D::Error>>() +impl ReadDsn for Option { + fn read_dsn(tokenizer: &mut ListTokenizer) -> Result { + let token = tokenizer.consume_token()?; + if let ListToken::Leaf { value: ref x } = token { + let x = x.parse::().unwrap(); + let y = tokenizer.read_value::()?; + Ok(Some(Point { x, y })) + } else { + tokenizer.return_token(token); + Ok(None) + } + } } -#[derive(Deserialize, Debug)] +impl WriteDsn for Vec { + fn write_dsn(&self, writer: &mut ListWriter) -> Result<(), std::io::Error> { + for elem in self { + writer.write_value(&elem.x)?; + writer.write_value(&elem.y)?; + } + Ok(()) + } +} + +impl WriteDsn for Option { + fn write_dsn(&self, writer: &mut ListWriter) -> 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, - #[serde(deserialize_with = "de_points")] - pub coord_vec: Vec, + #[anon] + pub coords: Vec, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Path { + #[anon] pub layer: String, + #[anon] pub width: f32, - #[serde(deserialize_with = "de_points")] - pub coord_vec: Vec, + #[anon] + pub coords: Vec, } -#[derive(Deserialize, Debug)] +#[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(Deserialize, Debug)] +#[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(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Rule { pub width: f32, - pub clearance_vec: Vec, + #[vec("clearance")] + pub clearances: Vec, } -#[derive(Deserialize, Debug)] +#[derive(ReadDsn, WriteDsn, Debug)] pub struct Clearance { + #[anon] pub value: f32, pub r#type: Option, } diff --git a/src/dsn/structure2.rs b/src/dsn/structure2.rs deleted file mode 100644 index eccc704..0000000 --- a/src/dsn/structure2.rs +++ /dev/null @@ -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, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct NetOut { - #[anon] - pub name: String, - #[vec("wire")] - pub wire: Vec, - #[vec("via")] - pub via: Vec, -} - -#[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, - pub space_in_quoted_tokens: Option, - pub host_cad: Option, - pub host_version: Option, -} - -#[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, - pub boundary: Boundary, - #[vec("plane")] - pub planes: Vec, - 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, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Placement { - #[vec("component")] - pub components: Vec, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Component { - #[anon] - pub name: String, - #[vec("place")] - pub places: Vec, -} - -#[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, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Library { - #[vec("image")] - pub images: Vec, - #[vec("padstack")] - pub padstacks: Vec, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Image { - #[anon] - pub name: String, - #[vec("outline")] - pub outlines: Vec, - #[vec("pin")] - pub pins: Vec, - #[vec("keepout")] - pub keepouts: Vec, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Outline { - pub path: Path, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Pin { - #[anon] - pub name: String, - pub rotate: Option, - #[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, - 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 ReadDsn for Shape { - fn read_dsn(tokenizer: &mut ListTokenizer) -> Result { - 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 WriteDsn for Shape { - fn write_dsn(&self, writer: &mut ListWriter) -> 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, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Network { - #[vec("net")] - pub nets: Vec, - #[vec("class")] - pub classes: Vec, -} - -#[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, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Class { - #[anon] - pub name: String, - #[anon_vec] - pub nets: Vec, - 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, - #[vec("via")] - pub vias: Vec, -} - -#[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 ReadDsn for Vec { - fn read_dsn(tokenizer: &mut ListTokenizer) -> Result { - let mut array = Vec::::new(); - loop { - let token = tokenizer.consume_token()?; - if let ListToken::Leaf { value: ref x } = token { - let x = x.parse::().unwrap(); - let y = tokenizer.read_value::()?; - array.push(Point { x, y }); - } else { - tokenizer.return_token(token); - break; - } - } - Ok(array) - } -} - -impl ReadDsn for Option { - fn read_dsn(tokenizer: &mut ListTokenizer) -> Result { - let token = tokenizer.consume_token()?; - if let ListToken::Leaf { value: ref x } = token { - let x = x.parse::().unwrap(); - let y = tokenizer.read_value::()?; - Ok(Some(Point { x, y })) - } else { - tokenizer.return_token(token); - Ok(None) - } - } -} - -impl WriteDsn for Vec { - fn write_dsn(&self, writer: &mut ListWriter) -> Result<(), std::io::Error> { - for elem in self { - writer.write_value(&elem.x)?; - writer.write_value(&elem.y)?; - } - Ok(()) - } -} - -impl WriteDsn for Option { - fn write_dsn(&self, writer: &mut ListWriter) -> 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, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Path { - #[anon] - pub layer: String, - #[anon] - pub width: f32, - #[anon] - pub coords: Vec, -} - -#[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, -} - -#[derive(ReadDsn, WriteDsn, Debug)] -pub struct Clearance { - #[anon] - pub value: f32, - pub r#type: Option, -}