dsn: refactor the parser/serializer to allow enums

This cleans up and defines new types in structure.rs as well.
This commit is contained in:
Tomasz Cichoń 2024-03-08 05:06:00 +01:00
parent 8a56a16528
commit 6bbbc368c6
5 changed files with 304 additions and 342 deletions

View File

@ -246,6 +246,8 @@ fn main() -> Result<(), anyhow::Error> {
((4, 3), 15.0), ((4, 3), 15.0),
]), ]),
}));*/ }));*/
//let design = DsnDesign::load_from_file("tests/data/prerouted_lm317_breakout/prerouted_lm317_breakout.dsn")?;
let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?; let design = DsnDesign::load_from_file("tests/data/test/test.dsn")?;
//dbg!(&design); //dbg!(&design);
let layout = design.make_layout(); let layout = design.make_layout();

View File

@ -1,6 +1,6 @@
use std::fmt; use std::fmt;
use serde::de::{self, DeserializeSeed, SeqAccess, Visitor}; use serde::de::{self, DeserializeSeed, SeqAccess, EnumAccess, VariantAccess, Visitor};
use serde::Deserialize; use serde::Deserialize;
use thiserror::Error; use thiserror::Error;
@ -20,10 +20,12 @@ pub enum DsnDeError {
SpaceInQuoted, SpaceInQuoted,
#[error("expected unquoted string")] #[error("expected unquoted string")]
ExpectedUnquoted, ExpectedUnquoted,
#[error("expected opening parenthesis")] #[error("expected opening parenthesis for {0}")]
ExpectedOpeningParen, ExpectedOpeningParen(&'static str),
#[error("expected closing parenthesis")] #[error("expected closing parenthesis for {0}")]
ExpectedClosingParen, ExpectedClosingParen(&'static str),
#[error("expected a keyword")]
ExpectedKeyword,
#[error("wrong keyword: expected {0}, got {1}")] #[error("wrong keyword: expected {0}, got {1}")]
WrongKeyword(&'static str, String), WrongKeyword(&'static str, String),
} }
@ -54,8 +56,8 @@ pub struct Deserializer<'de> {
space_in_quoted_tokens: bool, space_in_quoted_tokens: bool,
reconfig_incoming: Option<ReconfigIncoming>, reconfig_incoming: Option<ReconfigIncoming>,
vec_type: Option<&'static str>,
next_option_empty_hint: bool, next_option_empty_hint: bool,
last_deserialized_type: Option<&'static str>,
} }
#[derive(PartialEq, Debug, Copy, Clone)] #[derive(PartialEq, Debug, Copy, Clone)]
@ -74,20 +76,20 @@ impl<'de> Deserializer<'de> {
space_in_quoted_tokens: false, space_in_quoted_tokens: false,
reconfig_incoming: None, reconfig_incoming: None,
vec_type: None,
next_option_empty_hint: false, next_option_empty_hint: false,
last_deserialized_type: None,
} }
} }
fn next_name_lookahead(&self) -> Option<String> { fn keyword_lookahead(&self) -> Option<String> {
let mut iter = self.input.chars(); let mut iter = self.input.chars();
if iter.next() != Some('(') { if let Some('(') = iter.next() {
None Some(iter
} else { .take_while(|c| c != &' ' && c != &'\r' && c != &'\n')
Some( .collect::<String>()
iter.take_while(|c| c != &' ' && c != &'\r' && c != &'\n')
.collect::<String>(),
) )
} else {
None
} }
} }
@ -97,7 +99,7 @@ impl<'de> Deserializer<'de> {
fn next(&mut self) -> Result<char> { fn next(&mut self) -> Result<char> {
let chr = self.peek()?; let chr = self.peek()?;
self.input = &self.input[1..]; self.input = &self.input[chr.len_utf8()..];
if chr == '\n' { if chr == '\n' {
self.context.line += 1; self.context.line += 1;
self.context.column = 0; self.context.column = 0;
@ -115,11 +117,11 @@ impl<'de> Deserializer<'de> {
self.next().unwrap(); self.next().unwrap();
} }
} }
return;
} }
fn parse_bool(&mut self) -> Result<bool> { fn parse_bool(&mut self) -> Result<bool> {
match &self.parse_identifier() { self.skip_ws();
match &self.parse_unquoted() {
Ok(string) => match string.as_str() { Ok(string) => match string.as_str() {
"on" => Ok(true), "on" => Ok(true),
"off" => Ok(false), "off" => Ok(false),
@ -129,11 +131,13 @@ impl<'de> Deserializer<'de> {
} }
} }
fn parse_identifier(&mut self) -> Result<String> { fn parse_keyword(&mut self) -> Result<String> {
self.skip_ws();
self.parse_unquoted() self.parse_unquoted()
} }
fn parse_string(&mut self) -> Result<String> { fn parse_string(&mut self) -> Result<String> {
self.skip_ws();
let chr = self.peek()?; let chr = self.peek()?;
if self.string_quote == Some(chr) { if self.string_quote == Some(chr) {
self.parse_quoted() self.parse_quoted()
@ -184,7 +188,7 @@ impl<'de> Deserializer<'de> {
} }
} }
/*pub fn from_str<'a, T>(input: &'a str) -> Result<T> pub fn from_str<'a, T>(input: &'a str) -> Result<T>
where where
T: Deserialize<'a>, T: Deserialize<'a>,
{ {
@ -195,7 +199,7 @@ where
dbg!(deserializer.input); dbg!(deserializer.input);
}*/ }*/
Ok(t) Ok(t)
}*/ }
impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = DsnDeError; type Error = DsnDeError;
@ -211,17 +215,17 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = self.parse_bool()?;
self.skip_ws(); self.skip_ws();
let value = self.parse_bool()?;
// if the struct deserializer set a variable saying the incoming value should reconfigure a specific variable in the parser // If the struct deserializer set a variable saying the incoming value
// we do so and clear the flag // should reconfigure a specific variable in the parser we do so and
// clear the flag.
if self.reconfig_incoming == Some(ReconfigIncoming::SpaceAllowed) { if self.reconfig_incoming == Some(ReconfigIncoming::SpaceAllowed) {
self.space_in_quoted_tokens = value; self.space_in_quoted_tokens = value;
self.reconfig_incoming = None; self.reconfig_incoming = None;
} }
self.last_deserialized_type = Some("");
visitor.visit_bool(value) visitor.visit_bool(value)
} }
@ -241,10 +245,9 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = self.parse_unquoted()?;
self.skip_ws(); self.skip_ws();
let value = self.parse_unquoted()?;
self.last_deserialized_type = Some("");
visitor.visit_i32(value.parse().unwrap()) visitor.visit_i32(value.parse().unwrap())
} }
fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_i64<V>(self, _visitor: V) -> Result<V::Value>
@ -269,26 +272,27 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = self.parse_unquoted()?;
self.skip_ws(); self.skip_ws();
let value = self.parse_unquoted()?;
self.last_deserialized_type = Some("");
visitor.visit_u32(value.parse().unwrap()) visitor.visit_u32(value.parse().unwrap())
} }
fn deserialize_u64<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
todo!(); self.skip_ws();
let value = self.parse_unquoted()?;
visitor.visit_u64(value.parse().unwrap())
} }
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value> fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let value = self.parse_unquoted()?;
self.skip_ws(); self.skip_ws();
let value = self.parse_unquoted()?;
self.last_deserialized_type = Some("");
visitor.visit_f32(value.parse().unwrap()) visitor.visit_f32(value.parse().unwrap())
} }
fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_f64<V>(self, _visitor: V) -> Result<V::Value>
@ -301,17 +305,17 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let chr = self.next()?;
self.skip_ws(); self.skip_ws();
let chr = self.next()?;
// if the struct deserializer set a variable saying the incoming value should reconfigure a specific variable in the parser // If the struct deserializer set a variable saying the incoming value
// we do so and clear the flag // should reconfigure a specific variable in the parser we do so and
// clear the flag.
if self.reconfig_incoming == Some(ReconfigIncoming::StringQuote) { if self.reconfig_incoming == Some(ReconfigIncoming::StringQuote) {
self.string_quote = Some(chr); self.string_quote = Some(chr);
self.reconfig_incoming = None; self.reconfig_incoming = None;
} }
self.last_deserialized_type = Some("");
visitor.visit_char(chr) visitor.visit_char(chr)
} }
@ -326,11 +330,10 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
let string = self.parse_string()?;
self.skip_ws(); self.skip_ws();
let value = self.parse_string()?;
self.last_deserialized_type = Some(""); visitor.visit_string(value)
visitor.visit_string(string)
} }
fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value>
@ -365,75 +368,29 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
todo!(); todo!();
} }
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value> fn deserialize_unit_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
if self.next()? != '(' { todo!();
return Err(DsnDeError::ExpectedOpeningParen);
}
self.skip_ws();
let parsed_keyword = self.parse_identifier()?;
if parsed_keyword != name {
return Err(DsnDeError::WrongKeyword(name, parsed_keyword));
}
self.skip_ws();
if self.next()? != ')' {
return Err(DsnDeError::ExpectedClosingParen);
}
self.skip_ws();
self.last_deserialized_type = Some(name);
visitor.visit_unit()
} }
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value> fn deserialize_newtype_struct<V>(self, _name: &'static str, _visitor: V) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
if self.next()? != '(' { todo!();
return Err(DsnDeError::ExpectedOpeningParen);
}
self.skip_ws();
let parsed_keyword = self.parse_identifier()?;
if parsed_keyword != name {
return Err(DsnDeError::WrongKeyword(name, parsed_keyword));
}
self.skip_ws();
// if what we're deserializing is a directive to update parser configuration
// set a variable so the deserializer for the following value can update the relevant config
// (the variable is reset to None by the bool/char deserializer when it updates the config)
self.reconfig_incoming = match name {
"string_quote" => Some(ReconfigIncoming::StringQuote),
"space_in_quoted_tokens" => Some(ReconfigIncoming::SpaceAllowed),
_ => None,
};
let value = visitor.visit_seq(NewtypeStructFields::new(self))?;
if self.next()? != ')' {
return Err(DsnDeError::ExpectedClosingParen);
}
self.skip_ws();
self.last_deserialized_type = Some(name);
Ok(value)
} }
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value> fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
self.last_deserialized_type = None; let elem_type = self.vec_type.expect(
visitor.visit_seq(ArrayIndices::new(self)) "fields of type Vec<_> need to have names suffixed with _vec"
);
visitor.visit_seq(ArrayIndices::new(self, elem_type))
} }
fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value> fn deserialize_tuple<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
@ -464,55 +421,46 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
fn deserialize_struct<V>( fn deserialize_struct<V>(
self, self,
name: &'static str, _name: &'static str,
fields: &'static [&'static str], fields: &'static [&'static str],
visitor: V, visitor: V,
) -> Result<V::Value> ) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
if self.next()? != '(' { visitor.visit_seq(StructFields::new(self, fields))
return Err(DsnDeError::ExpectedOpeningParen);
}
self.skip_ws();
let parsed_keyword = self.parse_identifier()?;
if parsed_keyword != name {
return Err(DsnDeError::WrongKeyword(name, parsed_keyword));
}
self.skip_ws();
let value = visitor.visit_seq(StructFields::new(self, fields))?;
if self.next()? != ')' {
return Err(DsnDeError::ExpectedClosingParen);
}
self.skip_ws();
// a hint for the array deserializer
self.last_deserialized_type = Some(name);
Ok(value)
} }
fn deserialize_enum<V>( fn deserialize_enum<V>(
self, self,
_name: &'static str, name: &'static str,
_variants: &'static [&'static str], _variants: &'static [&'static str],
_visitor: V, visitor: V,
) -> Result<V::Value> ) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
todo!(); self.skip_ws();
if self.next()? != '(' {
return Err(DsnDeError::ExpectedOpeningParen("an enum variant"));
}
let value = visitor.visit_enum(Enum::new(self))?;
self.skip_ws();
if self.next()? != ')' {
return Err(DsnDeError::ExpectedClosingParen(name));
}
Ok(value)
} }
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value> fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
where where
V: Visitor<'de>, V: Visitor<'de>,
{ {
visitor.visit_string(self.parse_string()?) self.skip_ws();
visitor.visit_string(self.parse_string().map_err(|err| DsnDeError::ExpectedKeyword)?)
} }
fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_ignored_any<V>(self, _visitor: V) -> Result<V::Value>
@ -523,38 +471,69 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
} }
} }
struct NewtypeStructFields<'a, 'de: 'a> { struct Enum<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>, de: &'a mut Deserializer<'de>,
} }
impl<'a, 'de> NewtypeStructFields<'a, 'de> { impl<'a, 'de> Enum<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self { fn new(de: &'a mut Deserializer<'de>) -> Self {
Self { de } Enum { de }
} }
} }
impl<'de, 'a> SeqAccess<'de> for NewtypeStructFields<'a, 'de> { impl<'de, 'a> EnumAccess<'de> for Enum<'a, 'de> {
type Error = DsnDeError;
type Variant = Self;
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
where
V: DeserializeSeed<'de>,
{
seed.deserialize(&mut *self.de).map(|value| (value, self))
}
}
impl<'de, 'a> VariantAccess<'de> for Enum<'a, 'de> {
type Error = DsnDeError; type Error = DsnDeError;
fn next_element_seed<S>(&mut self, seed: S) -> Result<Option<S::Value>> fn unit_variant(self) -> Result<()> {
where todo!();
S: DeserializeSeed<'de>,
{
if self.de.peek()? == ')' {
return Ok(None);
} }
seed.deserialize(&mut *self.de).map(Some) fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
where
T: DeserializeSeed<'de>,
{
seed.deserialize(self.de)
}
fn tuple_variant<V>(self, _len: usize, _visitor: V) -> Result<V::Value>
where
V: Visitor<'de>,
{
todo!();
}
fn struct_variant<V>(
self,
_fields: &'static [&'static str],
_visitor: V,
) -> Result<V::Value>
where
V: Visitor<'de>,
{
todo!();
} }
} }
struct ArrayIndices<'a, 'de: 'a> { struct ArrayIndices<'a, 'de: 'a> {
de: &'a mut Deserializer<'de>, de: &'a mut Deserializer<'de>,
elem_type: &'static str,
} }
impl<'a, 'de> ArrayIndices<'a, 'de> { impl<'a, 'de> ArrayIndices<'a, 'de> {
fn new(de: &'a mut Deserializer<'de>) -> Self { fn new(de: &'a mut Deserializer<'de>, elem_type: &'static str) -> Self {
Self { de } Self { de, elem_type }
} }
} }
@ -565,22 +544,35 @@ impl<'de, 'a> SeqAccess<'de> for ArrayIndices<'a, 'de> {
where where
S: DeserializeSeed<'de>, S: DeserializeSeed<'de>,
{ {
self.de.skip_ws();
if self.de.peek()? == ')' { if self.de.peek()? == ')' {
return Ok(None); return Ok(None);
} }
if let Some(prev) = self.de.last_deserialized_type { if self.de.peek()? != '(' {
if let Some(lookahead) = self.de.next_name_lookahead() { // anonymous field
if prev != lookahead {
// the next struct is of different type from the array contents
// that means the array implicitly ended
// and we're looking at a field following the array instead
return Ok(None);
}
}
}
seed.deserialize(&mut *self.de).map(Some) seed.deserialize(&mut *self.de).map(Some)
} else {
let lookahead = self.de.keyword_lookahead().ok_or(
DsnDeError::ExpectedOpeningParen(self.elem_type)
)?;
if lookahead == self.elem_type {
// cannot fail, consuming the lookahead
self.de.next().unwrap();
self.de.parse_keyword().unwrap();
let value = seed.deserialize(&mut *self.de)?;
self.de.skip_ws();
if self.de.next()? != ')' {
Err(DsnDeError::ExpectedClosingParen(self.elem_type))
} else {
Ok(Some(value))
}
} else {
Ok(None)
}
}
} }
} }
@ -607,43 +599,49 @@ impl<'de, 'a> SeqAccess<'de> for StructFields<'a, 'de> {
where where
S: DeserializeSeed<'de>, S: DeserializeSeed<'de>,
{ {
if self.de.peek()? == ')' { let field_name = self.fields[self.current_field];
if self.current_field < self.fields.len() {
// We're short a field (or multiple), self.de.skip_ws();
// but the trailing field(s) might be optional and implicitly absent.
// In that case we prepare a hint for deserialize_option to emit None: let ret = if field_name.ends_with("_vec") {
self.de.next_option_empty_hint = true; self.de.vec_type = field_name.strip_suffix("_vec");
// and we tell serde to deserialize a field that may or may not be there: let value = seed.deserialize(&mut *self.de).map(Some);
self.current_field += 1; self.de.vec_type = None;
return seed.deserialize(&mut *self.de).map(Some);
// If it was a non-optional that was missing for real, value
// then even though our bet here was wrong (and we just lied to serde)
// the deserializer we handed off to will see the same closing paren
// (that we reacted to just now) and still return a sensible error.
} else { } else {
return Ok(None); if self.de.peek()? != '(' {
} // anonymous field, cannot be optional
self.de.next_option_empty_hint = true;
let value = seed.deserialize(&mut *self.de).map(Some);
self.de.next_option_empty_hint = false;
value
} else {
self.de.next()?; // consume the '('
let parsed_keyword = self.de.parse_keyword()?;
if parsed_keyword == field_name {
if field_name == "string_quote" {
self.de.reconfig_incoming = Some(ReconfigIncoming::StringQuote);
} else if field_name == "space_in_quoted_tokens" {
self.de.reconfig_incoming = Some(ReconfigIncoming::SpaceAllowed);
} }
// check if the next field is "named" let value = seed.deserialize(&mut *self.de)?;
// (saved as `(fieldname value)`)
if let Some(lookahead) = self.de.next_name_lookahead() { self.de.skip_ws();
if lookahead != self.fields[self.current_field] { if self.de.next()? != ')' {
if lookahead + "s" != self.fields[self.current_field] { Err(DsnDeError::ExpectedClosingParen(field_name))
self.de.next_option_empty_hint = true;
} else { } else {
self.de.next_option_empty_hint = false; Ok(Some(value))
} }
} else { } else {
self.de.next_option_empty_hint = false; Err(DsnDeError::WrongKeyword(field_name, parsed_keyword))
} }
} else {
// optional fields must be "named"
// if we see something else assume empty option
self.de.next_option_empty_hint = true;
} }
};
self.current_field += 1; self.current_field += 1;
seed.deserialize(&mut *self.de).map(Some) ret
} }
} }

View File

@ -11,7 +11,7 @@ use crate::{
use super::{ use super::{
de::{Deserializer, DsnContext, DsnDeError}, de::{Deserializer, DsnContext, DsnDeError},
rules::Rules, rules::Rules,
structure::Pcb, structure::{DsnFile, Pcb, Shape},
}; };
#[derive(Error, Debug)] #[derive(Error, Debug)]
@ -34,8 +34,8 @@ impl DsnDesign {
let contents = std::fs::read_to_string(filename).unwrap(); // TODO: remove unwrap. let contents = std::fs::read_to_string(filename).unwrap(); // TODO: remove unwrap.
//let pcb = from_str::<Pcb>(&contents).map_err(|err| DsnError())?; //let pcb = from_str::<Pcb>(&contents).map_err(|err| DsnError())?;
let mut deserializer = Deserializer::from_str(&contents); let mut deserializer = Deserializer::from_str(&contents);
let pcb = Pcb::deserialize(&mut deserializer) let pcb = DsnFile::deserialize(&mut deserializer)
.map_err(|err| DsnError(deserializer.context, err))?; .map_err(|err| DsnError(deserializer.context, err))?.pcb;
let rules = Rules::from_pcb(&pcb); let rules = Rules::from_pcb(&pcb);
@ -46,50 +46,51 @@ impl DsnDesign {
let mut layout = Layout::new(&self.rules); let mut layout = Layout::new(&self.rules);
// mapping of pin id -> net id prepared for adding pins // mapping of pin id -> net id prepared for adding pins
let pin_nets = if let Some(nets) = self.pcb.network.nets.as_ref() { let pin_nets = HashMap::<String, i64>::from_iter(
HashMap::<String, i64>::from_iter( self.pcb.network.net_vec
nets.iter() .iter()
.map(|net| { .map(|net| {
// resolve the id so we don't work with strings // resolve the id so we don't work with strings
let net_id = self.rules.net_ids.get(&net.name).unwrap(); let net_id = self.rules.net_ids.get(&net.name).unwrap();
// take the list of pins // take the list of pins
// and for each pin id output (pin id, net id) // and for each pin id output (pin id, net id)
net.pins.ids.iter().map(|id| (id.clone(), *net_id)) net.pins.names.iter().map(|id| (id.clone(), *net_id))
}) })
// flatten the nested iters into a single stream of tuples // flatten the nested iters into a single stream of tuples
.flatten(), .flatten(),
) );
} else {
HashMap::<String, i64>::new()
};
// add pins from components // add pins from components
//self.pcb.placement.components.iter().map(|component| { 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
.images .image_vec
.iter() .iter()
.find(|image| image.name == component.name) .find(|image| image.name == component.name)
.unwrap(); .unwrap();
for pin in &image.pins { for pin in &image.pin_vec {
let pin_name = format!("{}-{}", place.name, pin.id); let pin_name = format!("{}-{}", place.name, pin.id);
let net_id = pin_nets.get(&pin_name).unwrap(); let net_id = pin_nets.get(&pin_name).unwrap();
let padstack = &self let padstack = &self
.pcb .pcb
.library .library
.padstacks .padstack_vec
.iter() .iter()
.find(|padstack| padstack.name == pin.name) .find(|padstack| padstack.name == pin.name)
.unwrap(); .unwrap();
// no layer support yet, pick the first one // no layer support yet, pick the first one
let circle = &padstack.shapes[0].0; let circle = match &padstack.shape_vec[0] {
Shape::Circle(circle) => circle,
Shape::Rect(_) => todo!(),
Shape::Path(_) => todo!(),
Shape::Polygon(_) => todo!(),
};
let circle = Circle { let circle = Circle {
pos: (place.x as f64 / 100.0, -place.y as f64 / 100.0).into(), pos: (place.x as f64 / 100.0, -place.y as f64 / 100.0).into(),
r: circle.diameter as f64 / 200.0, r: circle.diameter as f64 / 200.0,
@ -104,28 +105,32 @@ impl DsnDesign {
} }
} }
} }
//})
// add vias to layout and save indices of dots in the order they appear in the file // add vias to layout and save indices of dots in the order they appear in the file
let _dot_indices: Vec<_> = self let _dot_indices: Vec<_> = self
.pcb .pcb
.wiring .wiring
.vias .via_vec
.iter() .iter()
.map(|via| { .map(|via| {
let net_id = self.rules.net_ids.get(&via.net.0).unwrap(); let net_id = self.rules.net_ids.get(&via.net).unwrap();
// find the padstack referenced by this via placement // find the padstack referenced by this via placement
let padstack = &self let padstack = &self
.pcb .pcb
.library .library
.padstacks .padstack_vec
.iter() .iter()
.find(|padstack| padstack.name == via.name) .find(|padstack| padstack.name == via.name)
.unwrap(); .unwrap();
// no layer support yet, pick the first one // no layer support yet, pick the first one
let circle = &padstack.shapes[0].0; let circle = match &padstack.shape_vec[0] {
Shape::Circle(circle) => circle,
Shape::Rect(_) => todo!(),
Shape::Path(_) => todo!(),
Shape::Polygon(_) => todo!(),
};
let circle = Circle { let circle = Circle {
pos: (via.x as f64 / 100.0, -via.y as f64 / 100.0).into(), pos: (via.x as f64 / 100.0, -via.y as f64 / 100.0).into(),
r: circle.diameter as f64 / 200.0, r: circle.diameter as f64 / 200.0,
@ -140,8 +145,8 @@ impl DsnDesign {
}) })
.collect(); .collect();
for wire in self.pcb.wiring.wires.iter() { for wire in self.pcb.wiring.wire_vec.iter() {
let net_id = self.rules.net_ids.get(&wire.net.0).unwrap(); let net_id = self.rules.net_ids.get(&wire.net).unwrap();
// add the first coordinate in the wire path as a dot and save its index // add the first coordinate in the wire path as a dot and save its index
let mut prev_index = layout let mut prev_index = layout
@ -149,8 +154,8 @@ impl DsnDesign {
net: *net_id as i64, net: *net_id as i64,
circle: Circle { circle: Circle {
pos: ( pos: (
wire.path.coords[0].x as f64 / 100.0, wire.path.coord_vec[0].x as f64 / 100.0,
-wire.path.coords[0].y as f64 / 100.0, -wire.path.coord_vec[0].y as f64 / 100.0,
) )
.into(), .into(),
r: wire.path.width as f64 / 200.0, r: wire.path.width as f64 / 200.0,
@ -159,7 +164,7 @@ impl DsnDesign {
.unwrap(); .unwrap();
// iterate through path coords starting from the second // iterate through path coords starting from the second
for coord in wire.path.coords.iter().skip(1) { for coord in wire.path.coord_vec.iter().skip(1) {
let index = layout let index = layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: *net_id as i64, net: *net_id as i64,

View File

@ -13,8 +13,8 @@ pub struct Rule {
impl Rule { impl Rule {
fn from_dsn(rule: &super::structure::Rule) -> Self { fn from_dsn(rule: &super::structure::Rule) -> Self {
Self { Self {
width: rule.width.0 as f64 / 100.0, width: rule.width as f64 / 100.0,
clearance: rule.clearances[0].value as f64 / 100.0, // picks the generic clearance only for now clearance: rule.clearance_vec[0].value as f64 / 100.0, // picks the generic clearance only for now
} }
} }
} }
@ -36,9 +36,9 @@ impl Rules {
// 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_ids = HashMap::from_iter( let net_ids = HashMap::from_iter(
pcb.network pcb.network
.classes .class_vec
.iter() .iter()
.flat_map(|class| &class.nets) .flat_map(|class| &class.net_vec)
.enumerate() .enumerate()
.map(|(id, net)| (net.clone(), id as i64)), .map(|(id, net)| (net.clone(), id as i64)),
); );
@ -46,10 +46,10 @@ impl Rules {
let mut net_id_classes = HashMap::new(); let mut net_id_classes = HashMap::new();
let class_rules = HashMap::from_iter( let class_rules = HashMap::from_iter(
pcb.network pcb.network
.classes .class_vec
.iter() .iter()
.inspect(|class| { .inspect(|class| {
for net in &class.nets { for net in &class.net_vec {
let net_id = net_ids.get(net).unwrap(); let net_id = net_ids.get(net).unwrap();
net_id_classes.insert(*net_id, class.name.clone()); net_id_classes.insert(*net_id, class.name.clone());
} }

View File

@ -1,12 +1,16 @@
use serde::{de::Error, Deserialize, Deserializer}; use serde::{de::Error, Deserialize, Deserializer};
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "pcb")] pub struct DsnFile {
pub pcb: Pcb,
}
#[derive(Deserialize, Debug)]
pub struct Pcb { pub struct Pcb {
pub name: String, pub name: String,
pub parser: Parser, pub parser: Parser,
pub resolution: Resolution, pub resolution: Resolution,
pub unit: Option<Unit>, pub unit: String,
pub structure: Structure, pub structure: Structure,
pub placement: Placement, pub placement: Placement,
pub library: Library, pub library: Library,
@ -15,183 +19,141 @@ pub struct Pcb {
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "parser")]
pub struct Parser { pub struct Parser {
pub string_quote: Option<StringQuote>, pub string_quote: Option<char>,
pub space_in_quoted_tokens: SpaceAllowed, pub space_in_quoted_tokens: Option<bool>,
pub host_cad: Option<HostCad>, pub host_cad: Option<String>,
pub host_version: Option<HostVersion>, pub host_version: Option<String>,
} }
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[serde(rename = "string_quote")]
pub struct StringQuote(pub char);
#[derive(Deserialize, Debug, Clone, Copy, PartialEq)]
#[serde(rename = "space_in_quoted_tokens")]
pub struct SpaceAllowed(pub bool);
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "host_cad")]
pub struct HostCad(pub String);
#[derive(Deserialize, Debug)]
#[serde(rename = "host_version")]
pub struct HostVersion(pub String);
#[derive(Deserialize, Debug)]
#[serde(rename = "resolution")]
pub struct Resolution { pub struct Resolution {
pub unit: String, pub unit: String,
pub value: u32, pub value: u32,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "unit")]
pub struct Unit(pub String);
#[derive(Deserialize, Debug)]
#[serde(rename = "structure")]
pub struct Structure { pub struct Structure {
pub layers: Vec<Layer>, pub layer_vec: Vec<Layer>,
pub boundary: Boundary, pub boundary: Boundary,
pub plane: Vec<Plane>, pub plane_vec: Vec<Plane>,
pub vias: Vias, pub via: ViaNames,
pub rule: Rule, pub rule: Rule,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "layer")]
pub struct Layer { pub struct Layer {
pub name: String, pub name: String,
pub r#type: Type, pub r#type: String,
pub property: Property, pub property: Property,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "property")] pub struct Property {
pub struct Property(Index); pub index: usize,
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "index")] pub struct Boundary {
pub struct Index(pub u32); pub path: Path,
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "boundary")]
pub struct Boundary(pub Path);
#[derive(Deserialize, Debug)]
#[serde(rename = "plane")]
pub struct Plane { pub struct Plane {
net: String, pub net: String,
shape: Polygon, pub polygon: Polygon,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "via")] pub struct ViaNames {
pub struct Vias { pub name_vec: Vec<String>,
vias: Vec<String>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "placement")]
pub struct Placement { pub struct Placement {
pub components: Vec<Component>, pub component_vec: Vec<Component>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "component")]
pub struct Component { pub struct Component {
pub name: String, pub name: String,
pub places: Vec<Place>, pub place_vec: Vec<Place>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "place")]
pub struct Place { pub struct Place {
pub name: String, pub name: String,
pub x: f32, pub x: f32,
pub y: f32, pub y: f32,
pub side: String, pub side: String,
pub rotation: f32, pub rotation: f32,
pub PN: Option<PN>, pub PN: Option<String>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "PN")]
pub struct PN {
pub name: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename = "library")]
pub struct Library { pub struct Library {
pub images: Vec<Image>, pub image_vec: Vec<Image>,
pub padstacks: Vec<Padstack>, pub padstack_vec: Vec<Padstack>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "image")]
pub struct Image { pub struct Image {
pub name: String, pub name: String,
pub outlines: Vec<Outline>, pub outline_vec: Vec<Outline>,
pub pins: Vec<Pin>, pub pin_vec: Vec<Pin>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "outline")]
pub struct Outline { pub struct Outline {
pub path: Path, pub path: Path,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "pin")]
pub struct Pin { pub struct Pin {
pub name: String, pub name: String,
pub rotate: Option<Rotate>, pub rotate: Option<f32>,
pub id: String, pub id: String,
pub x: f32, pub x: f32,
pub y: f32, pub y: f32,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "rotate")]
pub struct Rotate { pub struct Rotate {
pub angle: f32, pub angle: f32,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "padstack")]
pub struct Padstack { pub struct Padstack {
pub name: String, pub name: String,
pub shapes: Vec<Shape>, pub shape_vec: Vec<Shape>,
pub attach: Attach, pub attach: bool,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "shape")] pub enum Shape {
pub struct Shape(pub Circle); #[serde(rename = "circle")]
Circle(Circle),
#[serde(rename = "rect")]
Rect(Rect),
#[serde(rename = "path")]
Path(Path),
#[serde(rename = "polygon")]
Polygon(Polygon),
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "circle")]
pub struct Circle { pub struct Circle {
pub layer: String, pub layer: String,
pub diameter: u32, pub diameter: u32,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "attach")]
pub struct Attach(pub bool);
#[derive(Deserialize, Debug)]
#[serde(rename = "network")]
pub struct Network { pub struct Network {
pub nets: Option<Vec<NetPinAssignments>>, pub net_vec: Vec<NetPinAssignments>,
pub classes: Vec<Class>, pub class_vec: Vec<Class>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "net")]
// 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 {
pub name: String, pub name: String,
@ -199,57 +161,53 @@ pub struct NetPinAssignments {
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "pins")]
pub struct Pins { pub struct Pins {
pub ids: Vec<String>, pub names: Vec<String>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "class")]
pub struct Class { pub struct Class {
pub name: String, pub name: String,
pub nets: Vec<String>, pub net_vec: Vec<String>,
pub circuit: Circuit, pub circuit: Circuit,
pub rule: Rule, pub rule: Rule,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "circuit")] pub struct Circuit {
pub struct Circuit(pub UseVia); pub use_via: UseVia,
}
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "use_via")]
pub struct UseVia { pub struct UseVia {
pub name: String, pub name: String,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "wiring")]
pub struct Wiring { pub struct Wiring {
pub wires: Vec<Wire>, pub wire_vec: Vec<Wire>,
pub vias: Vec<Via>, pub via_vec: Vec<Via>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "wire")]
pub struct Wire { pub struct Wire {
pub path: Path, pub path: Path,
pub net: Net, pub net: String,
pub r#type: Type, pub r#type: String,
} }
// structs that appear in multiple places // structs that appear in multiple places
#[derive(Deserialize, Debug)] // This type isn't deserialized as is. Instead, Vec<Point> is converted from
#[serde(rename = "type")] // what's effectively Vec<f32> (with even length) in the file.
pub struct Type(pub String); // Use #[serde(deserialize_with = "de_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 Vec<Point>.
fn de_points<'de, D>(deserializer: D) -> Result<Vec<Point>, D::Error> fn de_points<'de, D>(deserializer: D) -> Result<Vec<Point>, D::Error>
where where
D: Deserializer<'de>, D: Deserializer<'de>,
@ -257,7 +215,10 @@ where
Vec::<f32>::deserialize(deserializer)? Vec::<f32>::deserialize(deserializer)?
.chunks(2) .chunks(2)
.map(|pair| { .map(|pair| {
// 0th index is guaranteed to exist by `.chunks()`
// (it ends iteration instead of emitting an empty Vec)
let x = pair[0]; 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( let y = *pair.get(1).ok_or(Error::custom(
"expected paired x y coordinates, list ended at x", "expected paired x y coordinates, list ended at x",
))?; ))?;
@ -268,51 +229,47 @@ where
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "polygon")]
pub struct Polygon { pub struct Polygon {
pub layer: String, pub layer: String,
pub width: f32, pub width: f32,
#[serde(deserialize_with = "de_points")] #[serde(deserialize_with = "de_points")]
pub coords: Vec<Point>, pub coord_vec: Vec<Point>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "path")]
pub struct Path { pub struct Path {
pub layer: String, pub layer: String,
pub width: f32, pub width: f32,
#[serde(deserialize_with = "de_points")] #[serde(deserialize_with = "de_points")]
pub coords: Vec<Point>, pub coord_vec: Vec<Point>,
}
#[derive(Deserialize, Debug)]
pub struct Rect {
pub layer: String,
pub x1: f32,
pub y1: f32,
pub x2: f32,
pub y2: f32,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "via")]
pub struct Via { pub struct Via {
pub name: String, pub name: String,
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
pub net: Net, pub net: String,
pub r#type: Type, pub r#type: String,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "rule")]
pub struct Rule { pub struct Rule {
pub width: Width, pub width: f32,
pub clearances: Vec<Clearance>, pub clearance_vec: Vec<Clearance>,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
#[serde(rename = "net")]
pub struct Net(pub String);
#[derive(Deserialize, Debug)]
#[serde(rename = "width")]
pub struct Width(pub f32);
#[derive(Deserialize, Debug)]
#[serde(rename = "clearance")]
pub struct Clearance { pub struct Clearance {
pub value: f32, pub value: f32,
pub r#type: Option<Type>, pub r#type: Option<String>,
} }