gerber_types/
function_codes.rs

1//! Function code types.
2
3use crate::coordinates::{CoordinateOffset, Coordinates};
4use crate::errors::GerberResult;
5use crate::traits::{GerberCode, PartialGerberCode};
6use crate::{attributes, CoordinateMode, Unit};
7use std::io::Write;
8
9// DCode
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum DCode {
13    Operation(Operation),
14    SelectAperture(i32),
15}
16
17impl<W: Write> GerberCode<W> for DCode {
18    fn serialize(&self, writer: &mut W) -> GerberResult<()> {
19        match *self {
20            DCode::Operation(ref operation) => operation.serialize(writer)?,
21            DCode::SelectAperture(code) => writeln!(writer, "D{}*", code)?,
22        };
23        Ok(())
24    }
25}
26
27// GCode
28
29#[derive(Debug, Clone, PartialEq)]
30pub enum GCode {
31    InterpolationMode(InterpolationMode),
32    RegionMode(bool),
33    QuadrantMode(QuadrantMode),
34    Comment(CommentContent),
35    /// Deprecated since December 2012, but still in use
36    Unit(Unit),
37    /// Deprecated since December 2012, but still in use
38    CoordinateMode(CoordinateMode),
39    /// Deprecated since December 2012, but still in use
40    SelectAperture,
41}
42
43impl<W: Write> GerberCode<W> for GCode {
44    fn serialize(&self, writer: &mut W) -> GerberResult<()> {
45        match *self {
46            GCode::InterpolationMode(ref mode) => mode.serialize(writer)?,
47            GCode::RegionMode(enabled) => {
48                if enabled {
49                    writeln!(writer, "G36*")?;
50                } else {
51                    writeln!(writer, "G37*")?;
52                }
53            }
54            GCode::QuadrantMode(ref mode) => mode.serialize(writer)?,
55            GCode::Comment(ref content) => {
56                write!(writer, "G04 ")?;
57                content.serialize_partial(writer)?;
58                writeln!(writer, "*")?;
59            }
60            GCode::Unit(ref unit) => match unit {
61                Unit::Inches => writeln!(writer, "G70*")?,
62                Unit::Millimeters => writeln!(writer, "G71*")?,
63            },
64            GCode::CoordinateMode(ref mode) => match mode {
65                CoordinateMode::Absolute => writeln!(writer, "G90*")?,
66                CoordinateMode::Incremental => writeln!(writer, "G91*")?,
67            },
68            GCode::SelectAperture => writeln!(writer, "G54*")?,
69        };
70        Ok(())
71    }
72}
73
74/// See Gerber spec 2024.05.
75/// 1) 4.1 - Comment (G04)
76/// 2) 5.1.1 - Comment attributes
77#[derive(Debug, Clone, PartialEq)]
78pub enum CommentContent {
79    String(String),
80    /// "Content starting with ”#@!“ is reserved for standard comments. The purpose of standard
81    ///  comments is to add meta-information in a formally defined manner, without affecting image
82    ///  generation. They can only be used if defined in this specification"
83    Standard(StandardComment),
84}
85
86impl<W: Write> PartialGerberCode<W> for CommentContent {
87    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
88        match *self {
89            CommentContent::String(ref string) => {
90                write!(writer, "{}", string)?;
91            }
92            CommentContent::Standard(ref standard) => {
93                standard.serialize_partial(writer)?;
94            }
95        }
96        Ok(())
97    }
98}
99
100/// See Gerber spec 2024.05.
101/// 1) 4.1 - Comment (G04)
102/// 2) 5.1.1 - Comment attributes
103#[derive(Debug, Clone, PartialEq)]
104pub enum StandardComment {
105    /// TF
106    FileAttribute(attributes::FileAttribute),
107    /// TO
108    ObjectAttribute(attributes::ObjectAttribute),
109    /// TA
110    ApertureAttribute(attributes::ApertureAttribute),
111    /// TD
112    DeleteAttribute(attributes::AttributeDeletionCriterion),
113}
114
115impl<W: Write> PartialGerberCode<W> for StandardComment {
116    fn serialize_partial(&self, writer: &mut W) -> GerberResult<()> {
117        write!(writer, "#@! ")?;
118        match *self {
119            StandardComment::FileAttribute(ref fa) => {
120                write!(writer, "TF")?;
121                fa.serialize_partial(writer)?;
122            }
123            StandardComment::ObjectAttribute(ref oa) => {
124                write!(writer, "TO")?;
125                oa.serialize_partial(writer)?;
126            }
127            StandardComment::ApertureAttribute(ref aa) => {
128                write!(writer, "TA")?;
129                aa.serialize_partial(writer)?;
130            }
131            StandardComment::DeleteAttribute(ref adc) => {
132                write!(writer, "TD")?;
133                adc.serialize_partial(writer)?;
134            }
135        }
136        Ok(())
137    }
138}
139
140// MCode
141
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub enum MCode {
144    EndOfFile,
145}
146
147impl<W: Write> GerberCode<W> for MCode {
148    fn serialize(&self, writer: &mut W) -> GerberResult<()> {
149        match *self {
150            MCode::EndOfFile => writeln!(writer, "M02*")?,
151        };
152        Ok(())
153    }
154}
155
156// Operation
157
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub enum Operation {
160    /// D01 Command
161    /// `D01 = ['X' integer] ['Y' integer] ['I' integer 'J' integer] 'D01*';`
162    Interpolate(Option<Coordinates>, Option<CoordinateOffset>),
163    /// D02 Command
164    /// `['X' integer] ['Y' integer] 'D02*';`
165    Move(Option<Coordinates>),
166    /// D03 Command
167    /// `['X' integer] ['Y' integer] 'D03*';`
168    Flash(Option<Coordinates>),
169}
170
171impl<W: Write> GerberCode<W> for Operation {
172    fn serialize(&self, writer: &mut W) -> GerberResult<()> {
173        match *self {
174            Operation::Interpolate(ref coords, ref offset) => {
175                coords.serialize_partial(writer)?;
176                offset.serialize_partial(writer)?;
177                writeln!(writer, "D01*")?;
178            }
179            Operation::Move(ref coords) => {
180                coords.serialize_partial(writer)?;
181                writeln!(writer, "D02*")?;
182            }
183            Operation::Flash(ref coords) => {
184                coords.serialize_partial(writer)?;
185                writeln!(writer, "D03*")?;
186            }
187        };
188        Ok(())
189    }
190}
191
192// InterpolationMode
193
194#[derive(Debug, Clone, Copy, PartialEq, Eq)]
195pub enum InterpolationMode {
196    Linear,
197    ClockwiseCircular,
198    CounterclockwiseCircular,
199}
200
201impl<W: Write> GerberCode<W> for InterpolationMode {
202    fn serialize(&self, writer: &mut W) -> GerberResult<()> {
203        match *self {
204            InterpolationMode::Linear => writeln!(writer, "G01*")?,
205            InterpolationMode::ClockwiseCircular => writeln!(writer, "G02*")?,
206            InterpolationMode::CounterclockwiseCircular => writeln!(writer, "G03*")?,
207        };
208        Ok(())
209    }
210}
211
212// QuadrantMode
213
214#[derive(Debug, Clone, Copy, PartialEq, Eq)]
215pub enum QuadrantMode {
216    Single,
217    Multi,
218}
219
220impl<W: Write> GerberCode<W> for QuadrantMode {
221    fn serialize(&self, writer: &mut W) -> GerberResult<()> {
222        match *self {
223            QuadrantMode::Single => writeln!(writer, "G74*")?,
224            QuadrantMode::Multi => writeln!(writer, "G75*")?,
225        };
226        Ok(())
227    }
228}
229
230#[cfg(test)]
231mod test {}