1use std::io::Write;
4
5use crate::errors::GerberResult;
6use crate::traits::PartialGerberCode;
7
8#[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#[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#[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#[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#[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#[derive(Debug, Clone, PartialEq)]
160pub struct Polygon {
161 pub diameter: f64,
162 pub vertices: u8, 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#[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#[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}