gerber_types/
function_codes.rs

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