gerber_types/
attributes.rs

1//! Attributes.
2
3use std::io::Write;
4
5use chrono::{DateTime, Utc};
6use uuid::Uuid;
7
8use crate::errors::GerberResult;
9use crate::traits::PartialGerberCode;
10
11// FileAttribute
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum FileAttribute {
15    Part(Part),
16    FileFunction(FileFunction),
17    FilePolarity(FilePolarity),
18    GenerationSoftware(GenerationSoftware),
19    CreationDate(DateTime<Utc>),
20    ProjectId {
21        id: String,
22        guid: Uuid,
23        revision: String,
24    },
25    Md5(String),
26    UserDefined {
27        name: String,
28        value: Vec<String>,
29    },
30}
31
32impl<W: Write> PartialGerberCode<W> for FileAttribute {
33    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
34        match *self {
35            FileAttribute::Part(ref part) => {
36                write!(writer, "Part,")?;
37                part.serialize_partial(writer)?;
38            }
39            FileAttribute::FileFunction(ref function) => {
40                write!(writer, "FileFunction,")?;
41                match function {
42                    FileFunction::Copper {
43                        ref layer,
44                        ref pos,
45                        ref copper_type,
46                    } => {
47                        write!(writer, "Copper,L{},", layer)?;
48                        pos.serialize_partial(writer)?;
49                        if let Some(ref t) = *copper_type {
50                            write!(writer, ",")?;
51                            t.serialize_partial(writer)?;
52                        }
53                    }
54                    FileFunction::Profile(ref plating) => {
55                        write!(writer, "Profile,")?;
56                        plating.serialize_partial(writer)?;
57                    }
58                    FileFunction::Soldermask { ref pos, ref index } => {
59                        write!(writer, "Soldermask,")?;
60                        pos.serialize_partial(writer)?;
61                        if let Some(ref i) = index {
62                            write!(writer, ",{}", *i)?;
63                        }
64                    }
65                    FileFunction::Legend { ref pos, ref index } => {
66                        write!(writer, "Legend,")?;
67                        pos.serialize_partial(writer)?;
68                        if let Some(ref i) = index {
69                            write!(writer, ",{}", *i)?;
70                        }
71                    }
72                    _ => unimplemented!(),
73                }
74            }
75            FileAttribute::GenerationSoftware(ref gs) => {
76                write!(writer, "GenerationSoftware,")?;
77                gs.serialize_partial(writer)?;
78            }
79            FileAttribute::FilePolarity(ref p) => {
80                write!(writer, "FilePolarity,")?;
81                p.serialize_partial(writer)?;
82            }
83            FileAttribute::Md5(ref hash) => write!(writer, "MD5,{}", hash)?,
84            _ => unimplemented!(),
85        };
86        Ok(())
87    }
88}
89
90// ApertureAttribute
91
92#[derive(Debug, Clone, PartialEq)]
93pub enum ApertureAttribute {
94    ApertureFunction(ApertureFunction),
95    DrillTolerance { plus: f64, minus: f64 },
96}
97
98// Part
99
100#[derive(Debug, Clone, PartialEq, Eq)]
101pub enum Part {
102    /// Single PCB
103    Single,
104    /// A.k.a. customer panel, assembly panel, shipping panel, biscuit
105    Array,
106    /// A.k.a. working panel, production panel
107    FabricationPanel,
108    /// A test coupon
109    Coupon,
110    /// None of the above
111    Other(String),
112}
113
114impl<W: Write> PartialGerberCode<W> for Part {
115    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
116        match *self {
117            Part::Single => write!(writer, "Single")?,
118            Part::Array => write!(writer, "Array")?,
119            Part::FabricationPanel => write!(writer, "FabricationPanel")?,
120            Part::Coupon => write!(writer, "Coupon")?,
121            Part::Other(ref description) => write!(writer, "Other,{}", description)?,
122        };
123        Ok(())
124    }
125}
126
127// Position
128
129#[derive(Debug, Clone, PartialEq, Eq)]
130pub enum Position {
131    Top,
132    Bottom,
133}
134
135impl<W: Write> PartialGerberCode<W> for Position {
136    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
137        match *self {
138            Position::Top => write!(writer, "Top")?,
139            Position::Bottom => write!(writer, "Bot")?,
140        };
141        Ok(())
142    }
143}
144
145// ExtendedPosition
146
147#[derive(Debug, Clone, PartialEq, Eq)]
148pub enum ExtendedPosition {
149    Top,
150    Inner,
151    Bottom,
152}
153
154impl<W: Write> PartialGerberCode<W> for ExtendedPosition {
155    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
156        match *self {
157            ExtendedPosition::Top => write!(writer, "Top")?,
158            ExtendedPosition::Inner => write!(writer, "Inr")?,
159            ExtendedPosition::Bottom => write!(writer, "Bot")?,
160        };
161        Ok(())
162    }
163}
164
165// CopperType
166
167#[derive(Debug, Clone, PartialEq, Eq)]
168pub enum CopperType {
169    Plane,
170    Signal,
171    Mixed,
172    Hatched,
173}
174
175impl<W: Write> PartialGerberCode<W> for CopperType {
176    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
177        match *self {
178            CopperType::Plane => write!(writer, "Plane")?,
179            CopperType::Signal => write!(writer, "Signal")?,
180            CopperType::Mixed => write!(writer, "Mixed")?,
181            CopperType::Hatched => write!(writer, "Hatched")?,
182        };
183        Ok(())
184    }
185}
186
187// Drill
188
189#[derive(Debug, Clone, PartialEq, Eq)]
190pub enum Drill {
191    ThroughHole,
192    Blind,
193    Buried,
194}
195
196// DrillRouteType
197
198#[derive(Debug, Clone, PartialEq, Eq)]
199pub enum DrillRouteType {
200    Drill,
201    Route,
202    Mixed,
203}
204
205// Profile
206
207#[derive(Debug, Clone, PartialEq, Eq)]
208pub enum Profile {
209    Plated,
210    NonPlated,
211}
212
213impl<W: Write> PartialGerberCode<W> for Profile {
214    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
215        match *self {
216            Profile::Plated => write!(writer, "P")?,
217            Profile::NonPlated => write!(writer, "NP")?,
218        };
219        Ok(())
220    }
221}
222
223// FileFunction
224
225#[derive(Debug, Clone, PartialEq, Eq)]
226pub enum FileFunction {
227    Copper {
228        layer: i32,
229        pos: ExtendedPosition,
230        copper_type: Option<CopperType>,
231    },
232    Soldermask {
233        pos: Position,
234        index: Option<i32>,
235    },
236    Legend {
237        pos: Position,
238        index: Option<i32>,
239    },
240    Goldmask {
241        pos: Position,
242        index: Option<i32>,
243    },
244    Silvermask {
245        pos: Position,
246        index: Option<i32>,
247    },
248    Tinmask {
249        pos: Position,
250        index: Option<i32>,
251    },
252    Carbonmask {
253        pos: Position,
254        index: Option<i32>,
255    },
256    Peelablesoldermask {
257        pos: Position,
258        index: Option<i32>,
259    },
260    Glue {
261        pos: Position,
262        index: Option<i32>,
263    },
264    Viatenting(Position),
265    Viafill,
266    Heatsink(Position),
267    Paste(Position),
268    KeepOut(Position),
269    Pads(Position),
270    Scoring(Position),
271    Plated {
272        from_layer: i32,
273        to_layer: i32,
274        drill: Drill,
275        label: Option<DrillRouteType>,
276    },
277    NonPlated {
278        from_layer: i32,
279        to_layer: i32,
280        drill: Drill,
281        label: Option<DrillRouteType>,
282    },
283    Profile(Profile),
284    Drillmap,
285    FabricationDrawing,
286    ArrayDrawing,
287    AssemblyDrawing(Position),
288    Drawing(String),
289    Other(String),
290}
291
292// FilePolarity
293
294#[derive(Debug, Clone, PartialEq, Eq)]
295pub enum FilePolarity {
296    Positive,
297    Negative,
298}
299
300impl<W: Write> PartialGerberCode<W> for FilePolarity {
301    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
302        match *self {
303            FilePolarity::Positive => write!(writer, "Positive")?,
304            FilePolarity::Negative => write!(writer, "Negative")?,
305        };
306        Ok(())
307    }
308}
309
310// GenerationSoftware
311
312#[derive(Debug, Clone, PartialEq, Eq)]
313pub struct GenerationSoftware {
314    pub vendor: String,
315    pub application: String,
316    pub version: Option<String>,
317}
318
319impl GenerationSoftware {
320    pub fn new<S: Into<String>>(vendor: S, application: S, version: Option<S>) -> Self {
321        GenerationSoftware {
322            vendor: vendor.into(),
323            application: application.into(),
324            version: version.map(|s| s.into()),
325        }
326    }
327}
328
329impl<W: Write> PartialGerberCode<W> for GenerationSoftware {
330    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
331        match self.version {
332            Some(ref v) => write!(writer, "{},{},{}", self.vendor, self.application, v)?,
333            None => write!(writer, "{},{}", self.vendor, self.application)?,
334        };
335        Ok(())
336    }
337}
338
339// ApertureFunction
340
341#[derive(Debug, Clone, PartialEq, Eq)]
342pub enum ApertureFunction {
343    // Only valid for layers with file function plated or non-plated
344    ViaDrill,
345    BackDrill,
346    ComponentDrill {
347        press_fit: Option<bool>, // TODO is this bool?
348    },
349    CastellatedDrill,
350    MechanicalDrill {
351        function: Option<DrillFunction>,
352    },
353    Slot,
354    CutOut,
355    Cavity,
356    OtherDrill(String),
357
358    // Only valid for layers with file function copper
359    ComponentPad {
360        press_fit: Option<bool>, // TODO is this bool?
361    },
362    SmdPad(SmdPadType),
363    BgaPad(SmdPadType),
364    ConnectorPad,
365    HeatsinkPad,
366    ViaPad,
367    TestPad,
368    CastellatedPad,
369    FiducialPad(FiducialScope),
370    ThermalReliefPad,
371    WasherPad,
372    AntiPad,
373    OtherPad(String),
374    Conductor,
375    NonConductor,
376    CopperBalancing,
377    Border,
378    OtherCopper(String),
379
380    // All layers
381    Profile,
382    NonMaterial,
383    Material,
384    Other(String),
385}
386
387// DrillFunction
388
389#[derive(Debug, Clone, PartialEq, Eq)]
390pub enum DrillFunction {
391    BreakOut,
392    Tooling,
393    Other,
394}
395
396// SmdPadType
397
398#[derive(Debug, Clone, PartialEq, Eq)]
399pub enum SmdPadType {
400    CopperDefined,
401    SoldermaskDefined,
402}
403
404// FiducialScope
405
406#[derive(Debug, Clone, PartialEq, Eq)]
407pub enum FiducialScope {
408    Global,
409    Local,
410}