1use crate::attributes;
8use crate::coordinates;
9use crate::extended_codes;
10use crate::function_codes;
11use crate::macros;
12use chrono::{DateTime, FixedOffset};
13use std::convert::From;
14
15macro_rules! impl_from {
18 ($from:ty, $target:ty, $variant:expr) => {
19 impl From<$from> for $target {
20 fn from(val: $from) -> Self {
21 $variant(val)
22 }
23 }
24 };
25}
26
27#[derive(Debug, Clone, PartialEq)]
30pub enum Command {
31 FunctionCode(FunctionCode),
32 ExtendedCode(ExtendedCode),
33}
34
35impl_from!(FunctionCode, Command, Command::FunctionCode);
36impl_from!(ExtendedCode, Command, Command::ExtendedCode);
37
38macro_rules! impl_command_fromfrom {
39 ($from:ty, $inner:path) => {
40 impl From<$from> for Command {
41 fn from(val: $from) -> Self {
42 Command::from($inner(val))
43 }
44 }
45 };
46}
47
48#[derive(Debug, Clone, PartialEq)]
51pub enum FunctionCode {
52 DCode(function_codes::DCode),
53 GCode(function_codes::GCode),
54 MCode(function_codes::MCode),
55}
56
57impl_from!(function_codes::DCode, FunctionCode, FunctionCode::DCode);
58impl_from!(function_codes::GCode, FunctionCode, FunctionCode::GCode);
59impl_from!(function_codes::MCode, FunctionCode, FunctionCode::MCode);
60
61impl_command_fromfrom!(function_codes::DCode, FunctionCode::from);
62impl_command_fromfrom!(function_codes::GCode, FunctionCode::from);
63impl_command_fromfrom!(function_codes::MCode, FunctionCode::from);
64
65#[derive(Debug, Clone, PartialEq)]
66pub enum ExtendedCode {
67 CoordinateFormat(coordinates::CoordinateFormat),
69 Unit(extended_codes::Unit),
71 ApertureDefinition(extended_codes::ApertureDefinition),
73 ApertureMacro(macros::ApertureMacro),
75 LoadPolarity(extended_codes::Polarity),
77 LoadMirroring(extended_codes::Mirroring),
79 LoadRotation(extended_codes::Rotation),
81 LoadScaling(extended_codes::Scaling),
83 StepAndRepeat(extended_codes::StepAndRepeat),
85 ApertureBlock(extended_codes::ApertureBlock),
87 FileAttribute(attributes::FileAttribute),
89 ObjectAttribute(attributes::ObjectAttribute),
91 ApertureAttribute(attributes::ApertureAttribute),
93 DeleteAttribute(attributes::AttributeDeletionCriterion),
95 MirrorImage(extended_codes::ImageMirroring),
97 OffsetImage(extended_codes::ImageOffset),
99 ScaleImage(extended_codes::ImageScaling),
101 RotateImage(extended_codes::ImageRotation),
103 ImagePolarity(extended_codes::ImagePolarity),
105 AxisSelect(extended_codes::AxisSelect),
107 ImageName(extended_codes::ImageName),
109}
110
111impl_from!(
112 coordinates::CoordinateFormat,
113 ExtendedCode,
114 ExtendedCode::CoordinateFormat
115);
116impl_from!(extended_codes::Unit, ExtendedCode, ExtendedCode::Unit);
117impl_from!(
118 extended_codes::ApertureDefinition,
119 ExtendedCode,
120 ExtendedCode::ApertureDefinition
121);
122impl_from!(
123 macros::ApertureMacro,
124 ExtendedCode,
125 ExtendedCode::ApertureMacro
126);
127impl_from!(
128 extended_codes::Polarity,
129 ExtendedCode,
130 ExtendedCode::LoadPolarity
131);
132impl_from!(
133 extended_codes::Mirroring,
134 ExtendedCode,
135 ExtendedCode::LoadMirroring
136);
137impl_from!(
138 extended_codes::Rotation,
139 ExtendedCode,
140 ExtendedCode::LoadRotation
141);
142impl_from!(
143 extended_codes::Scaling,
144 ExtendedCode,
145 ExtendedCode::LoadScaling
146);
147impl_from!(
148 extended_codes::StepAndRepeat,
149 ExtendedCode,
150 ExtendedCode::StepAndRepeat
151);
152impl_from!(
153 extended_codes::ApertureBlock,
154 ExtendedCode,
155 ExtendedCode::ApertureBlock
156);
157impl_from!(
158 attributes::FileAttribute,
159 ExtendedCode,
160 ExtendedCode::FileAttribute
161);
162impl_from!(
163 attributes::ApertureAttribute,
164 ExtendedCode,
165 ExtendedCode::ApertureAttribute
166);
167
168impl_command_fromfrom!(coordinates::CoordinateFormat, ExtendedCode::from);
169impl_command_fromfrom!(extended_codes::Unit, ExtendedCode::from);
170impl_command_fromfrom!(extended_codes::ApertureDefinition, ExtendedCode::from);
171impl_command_fromfrom!(macros::ApertureMacro, ExtendedCode::from);
172impl_command_fromfrom!(extended_codes::Polarity, ExtendedCode::from);
173impl_command_fromfrom!(extended_codes::Scaling, ExtendedCode::from);
174impl_command_fromfrom!(extended_codes::Mirroring, ExtendedCode::from);
175impl_command_fromfrom!(extended_codes::Rotation, ExtendedCode::from);
176impl_command_fromfrom!(extended_codes::StepAndRepeat, ExtendedCode::from);
177impl_command_fromfrom!(extended_codes::ApertureBlock, ExtendedCode::from);
178impl_command_fromfrom!(attributes::FileAttribute, ExtendedCode::from);
179impl_command_fromfrom!(attributes::ApertureAttribute, ExtendedCode::from);
180
181#[cfg(test)]
182mod test {
183 use super::*;
184
185 use std::io::BufWriter;
186
187 use crate::extended_codes::Polarity;
188 use crate::function_codes::GCode;
189 use crate::traits::GerberCode;
190 use crate::{
191 ApertureBlock, AttributeDeletionCriterion, CommentContent, Mirroring, Rotation, Scaling,
192 StepAndRepeat,
193 };
194
195 #[test]
196 fn test_debug() {
197 let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment(CommentContent::String(
199 "test".to_string(),
200 ))));
201 let debug = format!("{:?}", c);
202 assert_eq!(debug, "FunctionCode(GCode(Comment(String(\"test\"))))");
203 }
204
205 #[test]
206 fn test_function_code_serialize() {
207 let c = FunctionCode::GCode(GCode::Comment(CommentContent::String(
209 "comment".to_string(),
210 )));
211 assert_code!(c, "G04 comment*\n");
212 }
213
214 #[test]
215 fn test_function_code_from_gcode() {
216 let comment = GCode::Comment(CommentContent::String("hello".into()));
217 let f1: FunctionCode = FunctionCode::GCode(comment.clone());
218 let f2: FunctionCode = comment.into();
219 assert_eq!(f1, f2);
220 }
221
222 #[test]
223 fn test_command_from_function_code() {
224 let comment = FunctionCode::GCode(GCode::Comment(CommentContent::String("hello".into())));
225 let c1: Command = Command::FunctionCode(comment.clone());
226 let c2: Command = comment.into();
227 assert_eq!(c1, c2);
228 }
229
230 #[test]
231 fn test_command_from_extended_code() {
232 let delete_attr = ExtendedCode::DeleteAttribute(
233 AttributeDeletionCriterion::SingleApertureAttribute("test".to_string()),
234 );
235 let c1: Command = Command::ExtendedCode(delete_attr.clone());
236 let c2: Command = delete_attr.into();
237 assert_eq!(c1, c2);
238 }
239
240 #[test]
241 fn test_extended_code_from_step_and_repeat() {
242 let e1: ExtendedCode = ExtendedCode::StepAndRepeat(StepAndRepeat::Close);
243 let e2: ExtendedCode = StepAndRepeat::Close.into();
244 assert_eq!(e1, e2);
245 }
246
247 #[test]
248 fn test_extended_code_from_aperture_block() {
249 let e1: ExtendedCode = ExtendedCode::ApertureBlock(ApertureBlock::Open { code: 102 });
250 let e2: ExtendedCode = ApertureBlock::Open { code: 102 }.into();
251 assert_eq!(e1, e2);
252 }
253 #[test]
254 fn test_extended_code_from_polarity() {
255 let e1: ExtendedCode = ExtendedCode::LoadPolarity(Polarity::Dark);
256 let e2: ExtendedCode = Polarity::Dark.into();
257 assert_eq!(e1, e2);
258 }
259
260 #[test]
261 fn test_extended_code_from_mirroring() {
262 let e1: ExtendedCode = ExtendedCode::LoadMirroring(Mirroring::XY);
263 let e2: ExtendedCode = Mirroring::XY.into();
264 assert_eq!(e1, e2);
265 }
266
267 #[test]
268 fn test_extended_code_from_scaling() {
269 let e1: ExtendedCode = ExtendedCode::LoadScaling(Scaling { scale: 50.0 });
270 let e2: ExtendedCode = Scaling { scale: 50.0 }.into();
271 assert_eq!(e1, e2);
272 }
273
274 #[test]
275 fn test_extended_code_from_rotation() {
276 let e1: ExtendedCode = ExtendedCode::LoadRotation(Rotation { rotation: 90.0 });
277 let e2: ExtendedCode = Rotation { rotation: 90.0 }.into();
278 assert_eq!(e1, e2);
279 }
280}
281
282pub type GerberDate = DateTime<FixedOffset>;