diff --git a/src/dsn/de.rs b/src/dsn/de.rs index c4a0217..6194b24 100644 --- a/src/dsn/de.rs +++ b/src/dsn/de.rs @@ -608,7 +608,8 @@ impl<'de, 'a> SeqAccess<'de> for StructFields<'a, 'de> { } } - // TODO explain this part of empty option detection + // check if the next field is "named" + // (saved as `(fieldname value)`) if let Some(lookahead) = self.de.next_name_lookahead() { if lookahead != self.fields[self.current_field] { if lookahead + "s" != self.fields[self.current_field] { @@ -620,7 +621,9 @@ impl<'de, 'a> SeqAccess<'de> for StructFields<'a, 'de> { self.de.next_option_empty_hint = false; } } else { - self.de.next_option_empty_hint = false; + // optional fields must be "named" + // if we see something else assume empty option + self.de.next_option_empty_hint = true; } self.current_field += 1; diff --git a/src/dsn/structure.rs b/src/dsn/structure.rs index a679ac8..05a52ce 100644 --- a/src/dsn/structure.rs +++ b/src/dsn/structure.rs @@ -1,4 +1,4 @@ -use serde::Deserialize; +use serde::{Deserialize, Deserializer, de::Error}; #[derive(Deserialize, Debug)] #[serde(rename = "pcb")] @@ -55,6 +55,7 @@ pub struct Unit(pub String); pub struct Structure { pub layers: Vec, pub boundary: Boundary, + pub plane: Option, pub vias: Vias, pub rule: Rule, } @@ -79,6 +80,13 @@ pub struct Index(pub u32); #[serde(rename = "boundary")] pub struct Boundary(pub Path); +#[derive(Deserialize, Debug)] +#[serde(rename = "plane")] +pub struct Plane { + net: String, + shape: Polygon, +} + #[derive(Deserialize, Debug)] #[serde(rename = "via")] pub struct Vias { @@ -140,11 +148,18 @@ pub struct Outline { #[serde(rename = "pin")] pub struct Pin { pub name: String, + pub rotate: Option, pub id: String, pub x: f32, pub y: f32, } +#[derive(Deserialize, Debug)] +#[serde(rename = "rotate")] +pub struct Rotate { + pub angle: f32, +} + #[derive(Deserialize, Debug)] #[serde(rename = "padstack")] pub struct Padstack { @@ -229,47 +244,44 @@ pub struct Wire { #[serde(rename = "type")] pub struct Type(pub String); -#[derive(Deserialize, Debug)] -#[serde(rename = "unit")] +#[derive(Debug)] pub struct Point { pub x: f32, pub y: f32, } +fn de_points<'de, D>(deserializer: D) -> Result, D::Error> + where D: Deserializer<'de> +{ + Vec::::deserialize(deserializer)? + .chunks(2) + .map(|pair| { + let x = pair[0]; + 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>>() +} + #[derive(Deserialize, Debug)] -#[serde(from = "FlatPath")] -pub struct Path { +#[serde(rename = "polygon")] +pub struct Polygon { pub layer: String, pub width: f32, + #[serde(deserialize_with = "de_points")] pub coords: Vec, } #[derive(Deserialize, Debug)] #[serde(rename = "path")] -struct FlatPath { +pub struct Path { pub layer: String, pub width: f32, - pub coords: Vec, -} - -impl From for Path { - fn from(flat: FlatPath) -> Path { - Path { - layer: flat.layer, - width: flat.width, - coords: flat - .coords - .chunks(2) - .map(|pair| Point { - x: pair[0], - // it's possible to return an error instead of panicking if this From were TryFrom, - // but I don't think serde will let us grab and inspect it elsewhere - // so annotating this with line/column information later might be difficult? - y: *pair.get(1).expect("unpaired coordinate in path"), - }) - .collect(), - } - } + #[serde(deserialize_with = "de_points")] + pub coords: Vec, } #[derive(Deserialize, Debug)]