gerber_types/
extended_codes.rs

1//! Extended code types.
2
3use std::io::Write;
4
5use crate::errors::GerberResult;
6use crate::traits::PartialGerberCode;
7
8// Unit
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Unit {
12    Inches,
13    Millimeters,
14}
15
16impl<W: Write> PartialGerberCode<W> for Unit {
17    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
18        match *self {
19            Unit::Millimeters => write!(writer, "MM")?,
20            Unit::Inches => write!(writer, "IN")?,
21        };
22        Ok(())
23    }
24}
25
26// ApertureDefinition
27
28#[derive(Debug, Clone, PartialEq)]
29pub struct ApertureDefinition {
30    pub code: i32,
31    pub aperture: Aperture,
32}
33
34impl ApertureDefinition {
35    pub fn new(code: i32, aperture: Aperture) -> Self {
36        ApertureDefinition { code, aperture }
37    }
38}
39
40impl<W: Write> PartialGerberCode<W> for ApertureDefinition {
41    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
42        write!(writer, "{}", self.code)?;
43        self.aperture.serialize_partial(writer)?;
44        Ok(())
45    }
46}
47
48// Aperture
49
50#[derive(Debug, Clone, PartialEq)]
51pub enum Aperture {
52    Circle(Circle),
53    Rectangle(Rectangular),
54    Obround(Rectangular),
55    Polygon(Polygon),
56    Other(String),
57}
58
59impl<W: Write> PartialGerberCode<W> for Aperture {
60    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
61        match *self {
62            Aperture::Circle(ref circle) => {
63                write!(writer, "C,")?;
64                circle.serialize_partial(writer)?;
65            }
66            Aperture::Rectangle(ref rectangular) => {
67                write!(writer, "R,")?;
68                rectangular.serialize_partial(writer)?;
69            }
70            Aperture::Obround(ref rectangular) => {
71                write!(writer, "O,")?;
72                rectangular.serialize_partial(writer)?;
73            }
74            Aperture::Polygon(ref polygon) => {
75                write!(writer, "P,")?;
76                polygon.serialize_partial(writer)?;
77            }
78            Aperture::Other(ref string) => write!(writer, "{}", string)?,
79        };
80        Ok(())
81    }
82}
83
84// Circle
85
86#[derive(Debug, Clone, PartialEq)]
87pub struct Circle {
88    pub diameter: f64,
89    pub hole_diameter: Option<f64>,
90}
91
92impl Circle {
93    pub fn new(diameter: f64) -> Self {
94        Circle {
95            diameter,
96            hole_diameter: None,
97        }
98    }
99
100    pub fn with_hole(diameter: f64, hole_diameter: f64) -> Self {
101        Circle {
102            diameter,
103            hole_diameter: Some(hole_diameter),
104        }
105    }
106}
107
108impl<W: Write> PartialGerberCode<W> for Circle {
109    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
110        match self.hole_diameter {
111            Some(hole_diameter) => {
112                write!(writer, "{}X{}", self.diameter, hole_diameter)?;
113            }
114            None => write!(writer, "{}", self.diameter)?,
115        };
116        Ok(())
117    }
118}
119
120// Rectangular
121
122#[derive(Debug, Clone, PartialEq)]
123pub struct Rectangular {
124    pub x: f64,
125    pub y: f64,
126    pub hole_diameter: Option<f64>,
127}
128
129impl Rectangular {
130    pub fn new(x: f64, y: f64) -> Self {
131        Rectangular {
132            x,
133            y,
134            hole_diameter: None,
135        }
136    }
137
138    pub fn with_hole(x: f64, y: f64, hole_diameter: f64) -> Self {
139        Rectangular {
140            x,
141            y,
142            hole_diameter: Some(hole_diameter),
143        }
144    }
145}
146
147impl<W: Write> PartialGerberCode<W> for Rectangular {
148    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
149        match self.hole_diameter {
150            Some(hole_diameter) => write!(writer, "{}X{}X{}", self.x, self.y, hole_diameter)?,
151            None => write!(writer, "{}X{}", self.x, self.y)?,
152        };
153        Ok(())
154    }
155}
156
157// Polygon
158
159#[derive(Debug, Clone, PartialEq)]
160pub struct Polygon {
161    pub diameter: f64,
162    pub vertices: u8, // 3--12
163    pub rotation: Option<f64>,
164    pub hole_diameter: Option<f64>,
165}
166
167impl Polygon {
168    pub fn new(diameter: f64, vertices: u8) -> Self {
169        Polygon {
170            diameter,
171            vertices,
172            rotation: None,
173            hole_diameter: None,
174        }
175    }
176
177    pub fn with_rotation(mut self, angle: f64) -> Self {
178        self.rotation = Some(angle);
179        self
180    }
181
182    pub fn with_diameter(mut self, diameter: f64) -> Self {
183        self.diameter = diameter;
184        self
185    }
186}
187
188impl<W: Write> PartialGerberCode<W> for Polygon {
189    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
190        match (self.rotation, self.hole_diameter) {
191            (Some(rot), Some(hd)) => {
192                write!(writer, "{}X{}X{}X{}", self.diameter, self.vertices, rot, hd)?
193            }
194            (Some(rot), None) => write!(writer, "{}X{}X{}", self.diameter, self.vertices, rot)?,
195            (None, Some(hd)) => write!(writer, "{}X{}X0X{}", self.diameter, self.vertices, hd)?,
196            (None, None) => write!(writer, "{}X{}", self.diameter, self.vertices)?,
197        };
198        Ok(())
199    }
200}
201
202// Polarity
203
204#[derive(Debug, Clone, Copy, PartialEq, Eq)]
205pub enum Polarity {
206    Clear,
207    Dark,
208}
209
210impl<W: Write> PartialGerberCode<W> for Polarity {
211    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
212        match *self {
213            Polarity::Clear => write!(writer, "C")?,
214            Polarity::Dark => write!(writer, "D")?,
215        };
216        Ok(())
217    }
218}
219
220// StepAndRepeat
221
222#[derive(Debug, Clone, PartialEq)]
223pub enum StepAndRepeat {
224    Open {
225        repeat_x: u32,
226        repeat_y: u32,
227        distance_x: f64,
228        distance_y: f64,
229    },
230    Close,
231}
232
233impl<W: Write> PartialGerberCode<W> for StepAndRepeat {
234    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
235        match *self {
236            StepAndRepeat::Open {
237                repeat_x: rx,
238                repeat_y: ry,
239                distance_x: dx,
240                distance_y: dy,
241            } => write!(writer, "X{}Y{}I{}J{}", rx, ry, dx, dy)?,
242            StepAndRepeat::Close => {}
243        };
244        Ok(())
245    }
246}
247
248#[cfg(test)]
249mod test {
250    use super::*;
251
252    #[test]
253    fn test_aperture_definition_new() {
254        let ad1 = ApertureDefinition::new(10, Aperture::Circle(Circle::new(3.0)));
255        let ad2 = ApertureDefinition {
256            code: 10,
257            aperture: Aperture::Circle(Circle::new(3.0)),
258        };
259        assert_eq!(ad1, ad2);
260    }
261
262    #[test]
263    fn test_rectangular_new() {
264        let r1 = Rectangular::new(2.0, 3.0);
265        let r2 = Rectangular {
266            x: 2.0,
267            y: 3.0,
268            hole_diameter: None,
269        };
270        assert_eq!(r1, r2);
271    }
272
273    #[test]
274    fn test_rectangular_with_hole() {
275        let r1 = Rectangular::with_hole(3.0, 2.0, 1.0);
276        let r2 = Rectangular {
277            x: 3.0,
278            y: 2.0,
279            hole_diameter: Some(1.0),
280        };
281        assert_eq!(r1, r2);
282    }
283
284    #[test]
285    fn test_circle_new() {
286        let c1 = Circle::new(3.0);
287        let c2 = Circle {
288            diameter: 3.0,
289            hole_diameter: None,
290        };
291        assert_eq!(c1, c2);
292    }
293
294    #[test]
295    fn test_circle_with_hole() {
296        let c1 = Circle::with_hole(3.0, 1.0);
297        let c2 = Circle {
298            diameter: 3.0,
299            hole_diameter: Some(1.0),
300        };
301        assert_eq!(c1, c2);
302    }
303
304    #[test]
305    fn test_polygon_new() {
306        let p1 = Polygon::new(3.0, 4).with_rotation(45.0);
307        let p2 = Polygon {
308            diameter: 3.0,
309            vertices: 4,
310            rotation: Some(45.0),
311            hole_diameter: None,
312        };
313        assert_eq!(p1, p2);
314    }
315}