1#![allow(clippy::new_without_default)]
20
21#[cfg(test)]
22#[macro_use]
23mod test_macros;
24
25#[macro_use]
26mod serialization_macros;
27
28mod attributes;
29mod codegen;
30mod coordinates;
31mod errors;
32mod extended_codes;
33mod function_codes;
34mod macros;
35mod traits;
36mod types;
37
38pub use crate::attributes::*;
39pub use crate::coordinates::*;
40pub use crate::errors::*;
41pub use crate::extended_codes::*;
42pub use crate::function_codes::*;
43pub use crate::macros::*;
44pub use crate::traits::GerberCode;
45pub use crate::types::*;
46
47pub use uuid::Uuid;
49
50#[cfg(test)]
51mod serialization_tests {
52 use super::traits::PartialGerberCode;
53 use super::*;
54 use std::io::BufWriter;
55 use uuid::Uuid;
56
57 #[test]
58 fn test_comment() {
59 let comment = GCode::Comment(CommentContent::String("testcomment".to_string()));
61 assert_code!(comment, "G04 testcomment*\n");
62 }
63
64 #[test]
66 fn test_standard_comment_with_standard_attributes() {
67 let comment = GCode::Comment(CommentContent::Standard(
69 StandardComment::ApertureAttribute(ApertureAttribute::ApertureFunction(
70 ApertureFunction::SmdPad(SmdPadType::CopperDefined),
71 )),
72 ));
73 assert_code!(comment, "G04 #@! TA.AperFunction,SMDPad,CuDef*\n");
74
75 let comment = GCode::Comment(CommentContent::Standard(StandardComment::FileAttribute(
76 FileAttribute::FileFunction(FileFunction::Profile(Some(Profile::NonPlated))),
77 )));
78 assert_code!(comment, "G04 #@! TF.FileFunction,Profile,NP*\n");
79
80 let comment = GCode::Comment(CommentContent::Standard(StandardComment::ObjectAttribute(
81 ObjectAttribute::Component("R1".to_string()),
82 )));
83 assert_code!(comment, "G04 #@! TO.C,R1*\n");
84
85 let comment = GCode::Comment(CommentContent::Standard(StandardComment::DeleteAttribute(
86 AttributeDeletionCriterion::SingleApertureAttribute(".AperFunction".to_string()),
87 )));
88 assert_code!(comment, "G04 #@! TD.AperFunction*\n");
89 }
90
91 #[test]
92 fn test_standard_comment_with_custom_attributes() {
93 let comment = GCode::Comment(CommentContent::Standard(
95 StandardComment::ApertureAttribute(ApertureAttribute::UserDefined {
96 name: "Example".to_string(),
97 values: vec!["value1".to_string(), "value2".to_string()],
98 }),
99 ));
100 assert_code!(comment, "G04 #@! TAExample,value1,value2*\n");
101
102 let comment = GCode::Comment(CommentContent::Standard(StandardComment::FileAttribute(
103 FileAttribute::UserDefined {
104 name: "Example".to_string(),
105 values: vec!["value1".to_string(), "value2".to_string()],
106 },
107 )));
108 assert_code!(comment, "G04 #@! TFExample,value1,value2*\n");
109
110 let comment = GCode::Comment(CommentContent::Standard(StandardComment::ObjectAttribute(
111 ObjectAttribute::UserDefined {
112 name: "Example".to_string(),
113 values: vec!["value1".to_string(), "value2".to_string()],
114 },
115 )));
116 assert_code!(comment, "G04 #@! TOExample,value1,value2*\n");
117
118 let comment = GCode::Comment(CommentContent::Standard(StandardComment::DeleteAttribute(
119 AttributeDeletionCriterion::SingleApertureAttribute("Example".to_string()),
120 )));
121 assert_code!(comment, "G04 #@! TDExample*\n");
122 }
123
124 #[test]
125 fn test_vec_of_comments() {
126 let mut v = Vec::new();
128 v.push(GCode::Comment(CommentContent::String(
129 "comment 1".to_string(),
130 )));
131 v.push(GCode::Comment(CommentContent::String(
132 "another one".to_string(),
133 )));
134 assert_code!(v, "G04 comment 1*\nG04 another one*\n");
135 }
136
137 #[test]
138 fn test_single_command() {
139 let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment(CommentContent::String(
141 "comment".to_string(),
142 ))));
143 assert_code!(c, "G04 comment*\n");
144 }
145
146 #[test]
147 fn test_interpolation_mode() {
148 let mut commands = Vec::new();
149 let c1 = GCode::InterpolationMode(InterpolationMode::Linear);
150 let c2 = GCode::InterpolationMode(InterpolationMode::ClockwiseCircular);
151 let c3 = GCode::InterpolationMode(InterpolationMode::CounterclockwiseCircular);
152 commands.push(c1);
153 commands.push(c2);
154 commands.push(c3);
155 assert_code!(commands, "G01*\nG02*\nG03*\n");
156 }
157
158 #[test]
159 fn test_region_mode() {
160 let mut commands = Vec::new();
161 commands.push(GCode::RegionMode(true));
162 commands.push(GCode::RegionMode(false));
163 assert_code!(commands, "G36*\nG37*\n");
164 }
165
166 #[test]
167 fn test_quadrant_mode() {
168 let mut commands = Vec::new();
169 commands.push(GCode::QuadrantMode(QuadrantMode::Single));
170 commands.push(GCode::QuadrantMode(QuadrantMode::Multi));
171 assert_code!(commands, "G74*\nG75*\n");
172 }
173
174 #[test]
175 fn test_end_of_file() {
176 let c = MCode::EndOfFile;
177 assert_code!(c, "M02*\n");
178 }
179
180 #[test]
181 fn test_operation_interpolate() {
182 let cf = CoordinateFormat::new(ZeroOmission::Leading, CoordinateMode::Absolute, 2, 5);
183 let c1 = Operation::Interpolate(
184 Some(Coordinates::new(1, 2, cf)),
185 Some(CoordinateOffset::new(5, 10, cf)),
186 );
187 assert_code!(c1, "X100000Y200000I500000J1000000D01*\n");
188 let c2 = Operation::Interpolate(
189 Some(Coordinates::at_y(
190 -2,
191 CoordinateFormat::new(ZeroOmission::Leading, CoordinateMode::Absolute, 4, 4),
192 )),
193 None,
194 );
195 assert_code!(c2, "Y-20000D01*\n");
196 let cf = CoordinateFormat::new(ZeroOmission::Leading, CoordinateMode::Absolute, 4, 4);
197 let c3 = Operation::Interpolate(
198 Some(Coordinates::at_x(1, cf)),
199 Some(CoordinateOffset::at_y(2, cf)),
200 );
201 assert_code!(c3, "X10000J20000D01*\n");
202 }
203
204 #[test]
205 fn test_operation_move() {
206 let c = Operation::Move(Some(Coordinates::new(
207 23,
208 42,
209 CoordinateFormat::new(ZeroOmission::Leading, CoordinateMode::Absolute, 6, 4),
210 )));
211 assert_code!(c, "X230000Y420000D02*\n");
212 }
213
214 #[test]
215 fn test_operation_flash() {
216 let c = Operation::Flash(Some(Coordinates::new(
217 23,
218 42,
219 CoordinateFormat::new(ZeroOmission::Leading, CoordinateMode::Absolute, 4, 4),
220 )));
221 assert_code!(c, "X230000Y420000D03*\n");
222 }
223
224 #[test]
225 fn test_select_aperture() {
226 let c1 = DCode::SelectAperture(10);
227 assert_code!(c1, "D10*\n");
228 let c2 = DCode::SelectAperture(2147483647);
229 assert_code!(c2, "D2147483647*\n");
230 }
231
232 #[test]
233 fn test_coordinate_format_tz() {
234 let c = ExtendedCode::CoordinateFormat(CoordinateFormat::new(
235 ZeroOmission::Leading,
236 CoordinateMode::Absolute,
237 2,
238 5,
239 ));
240 assert_code!(c, "%FSLAX25Y25*%\n");
241 }
242
243 #[test]
244 fn test_coordinate_format_lz() {
245 let c = ExtendedCode::CoordinateFormat(CoordinateFormat::new(
246 ZeroOmission::Trailing,
247 CoordinateMode::Incremental,
248 2,
249 5,
250 ));
251 assert_code!(c, "%FSTIX25Y25*%\n");
252 }
253
254 #[test]
255 fn test_unit() {
256 let c1 = ExtendedCode::Unit(Unit::Millimeters);
257 let c2 = ExtendedCode::Unit(Unit::Inches);
258 assert_code!(c1, "%MOMM*%\n");
259 assert_code!(c2, "%MOIN*%\n");
260 }
261
262 mod aperture_definition {
263 use super::*;
264
265 #[test]
266 fn test_circle_definition() {
267 let ad1 = ApertureDefinition {
268 code: 10,
269 aperture: Aperture::Circle(Circle {
270 diameter: 4.0,
271 hole_diameter: Some(2.0),
272 }),
273 };
274 let ad2 = ApertureDefinition {
275 code: 11,
276 aperture: Aperture::Circle(Circle {
277 diameter: 4.5,
278 hole_diameter: None,
279 }),
280 };
281 assert_partial_code!(ad1, "10C,4X2");
282 assert_partial_code!(ad2, "11C,4.5");
283 }
284
285 #[test]
286 fn test_rectangular_definition() {
287 let ad1 = ApertureDefinition {
288 code: 12,
289 aperture: Aperture::Rectangle(Rectangular {
290 x: 1.5,
291 y: 2.25,
292 hole_diameter: Some(3.8),
293 }),
294 };
295 let ad2 = ApertureDefinition {
296 code: 13,
297 aperture: Aperture::Rectangle(Rectangular {
298 x: 1.0,
299 y: 1.0,
300 hole_diameter: None,
301 }),
302 };
303 let ad3 = ApertureDefinition {
304 code: 14,
305 aperture: Aperture::Obround(Rectangular {
306 x: 2.0,
307 y: 4.5,
308 hole_diameter: None,
309 }),
310 };
311 assert_partial_code!(ad1, "12R,1.5X2.25X3.8");
312 assert_partial_code!(ad2, "13R,1X1");
313 assert_partial_code!(ad3, "14O,2X4.5");
314 }
315
316 #[test]
317 fn test_polygon_definition() {
318 let ad1 = ApertureDefinition {
319 code: 15,
320 aperture: Aperture::Polygon(Polygon {
321 diameter: 4.5,
322 vertices: 3,
323 rotation: None,
324 hole_diameter: None,
325 }),
326 };
327 let ad2 = ApertureDefinition {
328 code: 16,
329 aperture: Aperture::Polygon(Polygon {
330 diameter: 5.0,
331 vertices: 4,
332 rotation: Some(30.6),
333 hole_diameter: None,
334 }),
335 };
336 let ad3 = ApertureDefinition {
337 code: 17,
338 aperture: Aperture::Polygon(Polygon {
339 diameter: 5.5,
340 vertices: 5,
341 rotation: None,
342 hole_diameter: Some(1.8),
343 }),
344 };
345 assert_partial_code!(ad1, "15P,4.5X3");
346 assert_partial_code!(ad2, "16P,5X4X30.6");
347 assert_partial_code!(ad3, "17P,5.5X5X0X1.8");
348 }
349
350 #[test]
351 fn test_macro_definition() {
352 let m1 = ApertureDefinition {
353 code: 42,
354 aperture: Aperture::Macro("NO_ARGS1".to_string(), None),
355 };
356 let m2 = ApertureDefinition {
357 code: 69,
358 aperture: Aperture::Macro(
359 "With_Args2".to_string(),
360 Some(vec![
361 MacroDecimal::Variable(1),
362 MacroDecimal::Value(0.25),
363 MacroDecimal::Expression("$1x$2".to_string()),
364 ]),
365 ),
366 };
367 assert_partial_code!(m1, "42NO_ARGS1");
368 assert_partial_code!(m2, "69With_Args2,$1X0.25X$1x$2");
369 }
370 }
371
372 #[test]
373 fn test_polarity() {
374 let d = ExtendedCode::LoadPolarity(Polarity::Dark);
375 let c = ExtendedCode::LoadPolarity(Polarity::Clear);
376 assert_code!(d, "%LPD*%\n");
377 assert_code!(c, "%LPC*%\n");
378 }
379
380 #[test]
381 fn test_step_and_repeat() {
382 let o = ExtendedCode::StepAndRepeat(StepAndRepeat::Open {
383 repeat_x: 2,
384 repeat_y: 3,
385 distance_x: 2.0,
386 distance_y: 3.0,
387 });
388 let c = ExtendedCode::StepAndRepeat(StepAndRepeat::Close);
389 assert_code!(o, "%SRX2Y3I2J3*%\n");
390 assert_code!(c, "%SR*%\n");
391 }
392
393 #[test]
394 fn test_aperture_block() {
395 let o = ExtendedCode::ApertureBlock(ApertureBlock::Open { code: 102 });
396 let c = ExtendedCode::ApertureBlock(ApertureBlock::Close);
397 assert_code!(o, "%AB102*%\n");
398 assert_code!(c, "%AB*%\n");
399 }
400
401 #[test]
402 fn test_delete_aperture_attribute() {
403 let c = ExtendedCode::DeleteAttribute(AttributeDeletionCriterion::SingleApertureAttribute(
404 "CustomAttribute".to_string(),
405 ));
406 assert_code!(c, "%TDCustomAttribute*%\n");
407 let s = ExtendedCode::DeleteAttribute(AttributeDeletionCriterion::SingleApertureAttribute(
408 ".AperFunction".to_string(),
409 ));
410 assert_code!(s, "%TD.AperFunction*%\n");
411 }
412
413 #[test]
414 fn test_delete_object_attribute() {
415 let c = ExtendedCode::DeleteAttribute(AttributeDeletionCriterion::SingleObjectAttribute(
416 "CustomAttribute".to_string(),
417 ));
418 assert_code!(c, "%TDCustomAttribute*%\n");
419 let c = ExtendedCode::DeleteAttribute(AttributeDeletionCriterion::SingleObjectAttribute(
420 ".N".to_string(),
421 ));
422 assert_code!(c, "%TD.N*%\n");
423 }
424
425 #[test]
426 fn test_delete_all_object_and_aperture_attributes() {
427 let d = ExtendedCode::DeleteAttribute(
428 AttributeDeletionCriterion::AllApertureAndObjectAttributes,
429 );
430 assert_code!(d, "%TD*%\n");
431 }
432
433 mod file_attribute {
434 use super::*;
435 #[test]
436 fn test_part() {
437 let part =
438 ExtendedCode::FileAttribute(FileAttribute::Part(Part::Other("Part 1".into())));
439 assert_code!(part, "%TF.Part,Other,Part 1*%\n");
440 }
441
442 #[test]
443 fn test_generation_software() {
444 let gensw1 = ExtendedCode::FileAttribute(FileAttribute::GenerationSoftware(
445 GenerationSoftware::new("Vendor 1", "App 1", None),
446 ));
447 assert_code!(gensw1, "%TF.GenerationSoftware,Vendor 1,App 1*%\n");
448
449 let gensw2 = ExtendedCode::FileAttribute(FileAttribute::GenerationSoftware(
450 GenerationSoftware::new("Vendor 1", "App 1", Some("1.2.3")),
451 ));
452 assert_code!(gensw2, "%TF.GenerationSoftware,Vendor 1,App 1,1.2.3*%\n");
453 }
454
455 #[test]
456 fn test_creation_date() {
457 let date = GerberDate::parse_from_rfc3339("2025-06-10T16:25:00+02:00").unwrap();
458 let date = ExtendedCode::FileAttribute(FileAttribute::CreationDate(date));
459 assert_code!(date, "%TF.CreationDate,2025-06-10T16:25:00+02:00*%\n");
460 }
461
462 #[test]
463 fn test_project_id() {
464 let proj = ExtendedCode::FileAttribute(FileAttribute::ProjectId {
465 id: "Project".into(),
466 uuid: Uuid::max(),
467 revision: "rev1".into(),
468 });
469 assert_code!(
470 proj,
471 "%TF.ProjectId,Project,ffffffff-ffff-ffff-ffff-ffffffffffff,rev1*%\n"
472 );
473 }
474
475 mod file_function {
476 use super::*;
477 #[test]
478 fn test_copper() {
479 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
480 FileFunction::Copper {
481 layer: 1,
482 pos: ExtendedPosition::Top,
483 copper_type: None,
484 },
485 ));
486 assert_code!(func, "%TF.FileFunction,Copper,L1,Top*%\n");
487
488 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
489 FileFunction::Copper {
490 layer: 2,
491 pos: ExtendedPosition::Bottom,
492 copper_type: Some(CopperType::Hatched),
493 },
494 ));
495 assert_code!(func, "%TF.FileFunction,Copper,L2,Bot,Hatched*%\n");
496
497 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
498 FileFunction::Copper {
499 layer: 3,
500 pos: ExtendedPosition::Bottom,
501 copper_type: Some(CopperType::Mixed),
502 },
503 ));
504 assert_code!(func, "%TF.FileFunction,Copper,L3,Bot,Mixed*%\n");
505
506 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
507 FileFunction::Copper {
508 layer: 4,
509 pos: ExtendedPosition::Bottom,
510 copper_type: Some(CopperType::Plane),
511 },
512 ));
513 assert_code!(func, "%TF.FileFunction,Copper,L4,Bot,Plane*%\n");
514
515 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
516 FileFunction::Copper {
517 layer: 5,
518 pos: ExtendedPosition::Bottom,
519 copper_type: Some(CopperType::Signal),
520 },
521 ));
522 assert_code!(func, "%TF.FileFunction,Copper,L5,Bot,Signal*%\n");
523 }
524
525 #[test]
526 fn test_plated() {
527 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
528 FileFunction::Plated {
529 from_layer: 1,
530 to_layer: 2,
531 drill: PlatedDrill::Blind,
532 label: None,
533 },
534 ));
535 assert_code!(func, "%TF.FileFunction,Plated,1,2,Blind*%\n");
536
537 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
538 FileFunction::Plated {
539 from_layer: 1,
540 to_layer: 4,
541 drill: PlatedDrill::PlatedThroughHole,
542 label: None,
543 },
544 ));
545 assert_code!(func, "%TF.FileFunction,Plated,1,4,PTH*%\n");
546
547 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
548 FileFunction::Plated {
549 from_layer: 2,
550 to_layer: 3,
551 drill: PlatedDrill::Buried,
552 label: None,
553 },
554 ));
555 assert_code!(func, "%TF.FileFunction,Plated,2,3,Buried*%\n");
556
557 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
558 FileFunction::Plated {
559 from_layer: 1,
560 to_layer: 2,
561 drill: PlatedDrill::PlatedThroughHole,
562 label: Some(DrillRouteType::Drill),
563 },
564 ));
565 assert_code!(func, "%TF.FileFunction,Plated,1,2,PTH,Drill*%\n");
566
567 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
568 FileFunction::Plated {
569 from_layer: 1,
570 to_layer: 2,
571 drill: PlatedDrill::PlatedThroughHole,
572 label: Some(DrillRouteType::Mixed),
573 },
574 ));
575 assert_code!(func, "%TF.FileFunction,Plated,1,2,PTH,Mixed*%\n");
576
577 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
578 FileFunction::Plated {
579 from_layer: 1,
580 to_layer: 2,
581 drill: PlatedDrill::PlatedThroughHole,
582 label: Some(DrillRouteType::Route),
583 },
584 ));
585 assert_code!(func, "%TF.FileFunction,Plated,1,2,PTH,Rout*%\n");
586 }
587
588 #[test]
589 fn test_non_plated() {
590 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
591 FileFunction::NonPlated {
592 from_layer: 1,
593 to_layer: 2,
594 drill: NonPlatedDrill::Blind,
595 label: None,
596 },
597 ));
598 assert_code!(func, "%TF.FileFunction,NonPlated,1,2,Blind*%\n");
599
600 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
601 FileFunction::NonPlated {
602 from_layer: 1,
603 to_layer: 4,
604 drill: NonPlatedDrill::NonPlatedThroughHole,
605 label: None,
606 },
607 ));
608 assert_code!(func, "%TF.FileFunction,NonPlated,1,4,NPTH*%\n");
609
610 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
611 FileFunction::NonPlated {
612 from_layer: 2,
613 to_layer: 3,
614 drill: NonPlatedDrill::Buried,
615 label: None,
616 },
617 ));
618 assert_code!(func, "%TF.FileFunction,NonPlated,2,3,Buried*%\n");
619
620 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
621 FileFunction::NonPlated {
622 from_layer: 1,
623 to_layer: 2,
624 drill: NonPlatedDrill::NonPlatedThroughHole,
625 label: Some(DrillRouteType::Drill),
626 },
627 ));
628 assert_code!(func, "%TF.FileFunction,NonPlated,1,2,NPTH,Drill*%\n");
629
630 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
631 FileFunction::NonPlated {
632 from_layer: 1,
633 to_layer: 2,
634 drill: NonPlatedDrill::NonPlatedThroughHole,
635 label: Some(DrillRouteType::Mixed),
636 },
637 ));
638 assert_code!(func, "%TF.FileFunction,NonPlated,1,2,NPTH,Mixed*%\n");
639
640 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
641 FileFunction::NonPlated {
642 from_layer: 1,
643 to_layer: 2,
644 drill: NonPlatedDrill::NonPlatedThroughHole,
645 label: Some(DrillRouteType::Route),
646 },
647 ));
648 assert_code!(func, "%TF.FileFunction,NonPlated,1,2,NPTH,Rout*%\n");
649 }
650
651 #[test]
652 fn test_profile() {
653 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
654 FileFunction::Profile(None),
655 ));
656 assert_code!(func, "%TF.FileFunction,Profile*%\n");
657
658 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
659 FileFunction::Profile(Some(Profile::Plated)),
660 ));
661 assert_code!(func, "%TF.FileFunction,Profile,P*%\n");
662
663 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
664 FileFunction::Profile(Some(Profile::NonPlated)),
665 ));
666 assert_code!(func, "%TF.FileFunction,Profile,NP*%\n");
667 }
668
669 #[test]
670 fn test_keepout() {
671 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
672 FileFunction::KeepOut(Position::Top),
673 ));
674 assert_code!(func, "%TF.FileFunction,Keepout,Top*%\n");
675
676 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
677 FileFunction::KeepOut(Position::Bottom),
678 ));
679 assert_code!(func, "%TF.FileFunction,Keepout,Bot*%\n");
680 }
681
682 macro_rules! test_position_and_index {
683 ($test:ident, $ff:ident, $value:literal) => {
684 #[test]
685 fn $test() {
686 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
687 FileFunction::$ff {
688 pos: Position::Top,
689 index: None,
690 },
691 ));
692 assert_code!(func, &format!("%TF.FileFunction,{},Top*%\n", $value));
693
694 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
695 FileFunction::$ff {
696 pos: Position::Top,
697 index: Some(1),
698 },
699 ));
700 assert_code!(func, &format!("%TF.FileFunction,{},Top,1*%\n", $value));
701
702 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
703 FileFunction::$ff {
704 pos: Position::Bottom,
705 index: None,
706 },
707 ));
708 assert_code!(func, &format!("%TF.FileFunction,{},Bot*%\n", $value));
709 }
710 };
711 }
712
713 macro_rules! test_layer_and_position {
714 ($test:ident, $ff:ident, $value:literal) => {
715 #[test]
716 fn $test() {
717 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
718 FileFunction::$ff {
719 pos: Position::Top,
720 layer: 1,
721 },
722 ));
723 assert_code!(func, &format!("%TF.FileFunction,{},L{},Top*%\n", $value, 1));
724
725 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
726 FileFunction::$ff {
727 pos: Position::Bottom,
728 layer: 2,
729 },
730 ));
731 assert_code!(func, &format!("%TF.FileFunction,{},L{},Bot*%\n", $value, 2));
732 }
733 };
734 }
735
736 macro_rules! test_position {
737 ($test:ident, $ff:ident, $value:literal) => {
738 #[test]
739 fn $test() {
740 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
741 FileFunction::$ff(Position::Top),
742 ));
743 assert_code!(func, &format!("%TF.FileFunction,{},Top*%\n", $value));
744
745 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
746 FileFunction::$ff(Position::Bottom),
747 ));
748 assert_code!(func, &format!("%TF.FileFunction,{},Bot*%\n", $value));
749 }
750 };
751 }
752
753 macro_rules! test_optional_position {
754 ($test:ident, $ff:ident, $value:literal) => {
755 #[test]
756 fn $test() {
757 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
758 FileFunction::$ff(None),
759 ));
760 assert_code!(func, &format!("%TF.FileFunction,{}*%\n", $value));
761
762 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
763 FileFunction::$ff(Some(Position::Top)),
764 ));
765 assert_code!(func, &format!("%TF.FileFunction,{},Top*%\n", $value));
766
767 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
768 FileFunction::$ff(Some(Position::Bottom)),
769 ));
770 assert_code!(func, &format!("%TF.FileFunction,{},Bot*%\n", $value));
771 }
772 };
773 }
774 macro_rules! test_simple {
775 ($test:ident, $ff:ident, $value:literal) => {
776 #[test]
777 fn $test() {
778 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
779 FileFunction::$ff,
780 ));
781 assert_code!(func, &format!("%TF.FileFunction,{}*%\n", $value));
782 }
783 };
784 }
785
786 macro_rules! test_string {
787 ($test:ident, $ff:ident, $value:literal) => {
788 #[test]
789 fn $test() {
790 let string = "A String".to_string();
791 let func = ExtendedCode::FileAttribute(FileAttribute::FileFunction(
792 FileFunction::$ff(string.clone()),
793 ));
794 assert_code!(func, &format!("%TF.FileFunction,{},{}*%\n", $value, string));
795 }
796 };
797 }
798
799 test_position_and_index!(test_soldermask, SolderMask, "Soldermask");
804 test_position_and_index!(test_legend, Legend, "Legend");
805 test_layer_and_position!(test_component, Component, "Component");
806 test_position!(test_paste, Paste, "Paste");
807 test_position!(test_glue, Glue, "Glue");
808 test_position_and_index!(test_carbonmask, CarbonMask, "Carbonmask");
809 test_position_and_index!(test_goldmask, GoldMask, "Goldmask");
810 test_position_and_index!(test_heatsinkmask, HeatsinkMask, "Heatsinkmask");
811 test_position_and_index!(test_peelablemask, PeelableMask, "Peelablemask");
812 test_position_and_index!(test_silvermask, SilverMask, "Silvermask");
813 test_position_and_index!(test_tinmask, TinMask, "Tinmask");
814 test_position!(test_depthroute, DepthRoute, "Depthrout");
815 test_optional_position!(test_vcut, VCut, "Vcut");
816 test_simple!(test_viafill, ViaFill, "Viafill");
817 test_position!(test_pads, Pads, "Pads");
818 test_string!(test_other, Other, "Other");
819 test_simple!(test_drillmap, DrillMap, "Drillmap");
820 test_simple!(
821 test_fabricationdrawing,
822 FabricationDrawing,
823 "FabricationDrawing"
824 );
825 test_simple!(test_vcutmap, VCutMap, "Vcutmap");
826 test_position!(test_assemblydrawing, AssemblyDrawing, "AssemblyDrawing");
827 test_simple!(test_arraydrawing, ArrayDrawing, "ArrayDrawing");
828 test_string!(test_otherdrawing, OtherDrawing, "OtherDrawing");
829 }
830
831 #[test]
832 fn test_polarity() {
833 let pol =
834 ExtendedCode::FileAttribute(FileAttribute::FilePolarity(FilePolarity::Positive));
835 assert_code!(pol, "%TF.FilePolarity,Positive*%\n");
836
837 let pol =
838 ExtendedCode::FileAttribute(FileAttribute::FilePolarity(FilePolarity::Negative));
839 assert_code!(pol, "%TF.FilePolarity,Negative*%\n");
840 }
841
842 #[test]
843 fn test_same_coordinates() {
844 let same_coordiantes =
845 ExtendedCode::FileAttribute(FileAttribute::SameCoordinates(None));
846 assert_code!(same_coordiantes, "%TF.SameCoordinates*%\n");
847
848 let same_coordiantes = ExtendedCode::FileAttribute(FileAttribute::SameCoordinates(
849 Some(Ident::Name("Name 1".to_string())),
850 ));
851 assert_code!(same_coordiantes, "%TF.SameCoordinates,Name 1*%\n");
852
853 let same_coordiantes = ExtendedCode::FileAttribute(FileAttribute::SameCoordinates(
854 Some(Ident::Uuid(Uuid::max())),
855 ));
856 assert_code!(
857 same_coordiantes,
858 "%TF.SameCoordinates,ffffffff-ffff-ffff-ffff-ffffffffffff*%\n"
859 );
860 }
861
862 #[test]
863 fn test_md5() {
864 let md5 = ExtendedCode::FileAttribute(FileAttribute::Md5("abcd1234".into()));
865 assert_code!(md5, "%TF.MD5,abcd1234*%\n");
866 }
867
868 mod user_defined_attribute {
869 use super::*;
870
871 #[test]
872 fn test_non_standard() {
873 let function = ExtendedCode::FileAttribute(FileAttribute::UserDefined {
874 name: "NonStandardAttribute".to_string(),
875 values: vec!["Value 1 ".to_string(), " Value 2".to_string()],
876 });
877 assert_code!(function, "%TFNonStandardAttribute,Value 1 , Value 2*%\n");
879 }
880
881 #[test]
882 fn test_unsupported_standard() {
883 let function = ExtendedCode::FileAttribute(FileAttribute::UserDefined {
884 name: ".UnsupportedStandardAttribute".to_string(),
885 values: vec!["Value 1 ".to_string(), " Value 2".to_string()],
886 });
887 assert_code!(
889 function,
890 "%TF.UnsupportedStandardAttribute,Value 1 , Value 2*%\n"
891 );
892 }
893 }
894 }
895
896 mod aperture_attribute {
897 use super::*;
898 #[test]
903 fn test_via_drill() {
904 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
905 ApertureFunction::ViaDrill(None),
906 ));
907 assert_code!(function, "%TA.AperFunction,ViaDrill*%\n");
908
909 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
910 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::None)),
911 ));
912 assert_code!(function, "%TA.AperFunction,ViaDrill,None*%\n");
913
914 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
915 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::Ia)),
916 ));
917 assert_code!(function, "%TA.AperFunction,ViaDrill,Ia*%\n");
918
919 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
920 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::Ib)),
921 ));
922 assert_code!(function, "%TA.AperFunction,ViaDrill,Ib*%\n");
923
924 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
925 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::IIa)),
926 ));
927 assert_code!(function, "%TA.AperFunction,ViaDrill,IIa*%\n");
928
929 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
930 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::IIb)),
931 ));
932 assert_code!(function, "%TA.AperFunction,ViaDrill,IIb*%\n");
933
934 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
935 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::IIIa)),
936 ));
937 assert_code!(function, "%TA.AperFunction,ViaDrill,IIIa*%\n");
938
939 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
940 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::IIIb)),
941 ));
942 assert_code!(function, "%TA.AperFunction,ViaDrill,IIIb*%\n");
943
944 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
945 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::IVa)),
946 ));
947 assert_code!(function, "%TA.AperFunction,ViaDrill,IVa*%\n");
948
949 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
950 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::IVb)),
951 ));
952 assert_code!(function, "%TA.AperFunction,ViaDrill,IVb*%\n");
953
954 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
955 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::V)),
956 ));
957 assert_code!(function, "%TA.AperFunction,ViaDrill,V*%\n");
958
959 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
960 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::VI)),
961 ));
962 assert_code!(function, "%TA.AperFunction,ViaDrill,VI*%\n");
963
964 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
965 ApertureFunction::ViaDrill(Some(IPC4761ViaProtection::VII)),
966 ));
967 assert_code!(function, "%TA.AperFunction,ViaDrill,VII*%\n");
968 }
969
970 #[test]
971 fn test_backdrill() {
972 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
973 ApertureFunction::BackDrill,
974 ));
975 assert_code!(function, "%TA.AperFunction,BackDrill*%\n");
976 }
977
978 #[test]
979 fn test_component_drill() {
980 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
981 ApertureFunction::ComponentDrill { function: None },
982 ));
983 assert_code!(function, "%TA.AperFunction,ComponentDrill*%\n");
984
985 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
986 ApertureFunction::ComponentDrill {
987 function: Some(ComponentDrill::PressFit),
988 },
989 ));
990 assert_code!(function, "%TA.AperFunction,ComponentDrill,PressFit*%\n");
991 }
992
993 #[test]
994 fn test_mechanical_drill() {
995 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
996 ApertureFunction::MechanicalDrill { function: None },
997 ));
998 assert_code!(function, "%TA.AperFunction,MechanicalDrill*%\n");
999
1000 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1001 ApertureFunction::MechanicalDrill {
1002 function: Some(DrillFunction::Other),
1003 },
1004 ));
1005 assert_code!(function, "%TA.AperFunction,MechanicalDrill,Other*%\n");
1006
1007 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1008 ApertureFunction::MechanicalDrill {
1009 function: Some(DrillFunction::BreakOut),
1010 },
1011 ));
1012 assert_code!(function, "%TA.AperFunction,MechanicalDrill,Breakout*%\n");
1013
1014 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1015 ApertureFunction::MechanicalDrill {
1016 function: Some(DrillFunction::Tooling),
1017 },
1018 ));
1019 assert_code!(function, "%TA.AperFunction,MechanicalDrill,Tooling*%\n");
1020 }
1021
1022 #[test]
1023 fn test_catellated_drill() {
1024 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1025 ApertureFunction::CastellatedDrill,
1026 ));
1027 assert_code!(function, "%TA.AperFunction,CastellatedDrill*%\n");
1028 }
1029
1030 #[test]
1031 fn test_other_drill() {
1032 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1033 ApertureFunction::OtherDrill("CustomDrill".to_string()),
1034 ));
1035 assert_code!(function, "%TA.AperFunction,OtherDrill,CustomDrill*%\n");
1036 }
1037
1038 #[test]
1042 fn test_component_pad() {
1043 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1044 ApertureFunction::ComponentPad,
1045 ));
1046 assert_code!(function, "%TA.AperFunction,ComponentPad*%\n");
1047 }
1048
1049 #[test]
1050 fn test_smd_pad() {
1051 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1052 ApertureFunction::SmdPad(SmdPadType::CopperDefined),
1053 ));
1054 assert_code!(function, "%TA.AperFunction,SMDPad,CuDef*%\n");
1055
1056 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1057 ApertureFunction::SmdPad(SmdPadType::SoldermaskDefined),
1058 ));
1059 assert_code!(function, "%TA.AperFunction,SMDPad,SMDef*%\n");
1060 }
1061
1062 #[test]
1063 fn test_bga_pad() {
1064 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1065 ApertureFunction::BgaPad(SmdPadType::CopperDefined),
1066 ));
1067 assert_code!(function, "%TA.AperFunction,BGAPad,CuDef*%\n");
1068
1069 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1070 ApertureFunction::BgaPad(SmdPadType::SoldermaskDefined),
1071 ));
1072 assert_code!(function, "%TA.AperFunction,BGAPad,SMDef*%\n");
1073 }
1074
1075 #[test]
1076 fn test_connector_pad() {
1077 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1078 ApertureFunction::ConnectorPad,
1079 ));
1080 assert_code!(function, "%TA.AperFunction,ConnectorPad*%\n");
1081 }
1082
1083 #[test]
1084 fn test_headsink_pad() {
1085 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1086 ApertureFunction::HeatsinkPad,
1087 ));
1088 assert_code!(function, "%TA.AperFunction,HeatsinkPad*%\n");
1089 }
1090
1091 #[test]
1092 fn test_via_pad() {
1093 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1094 ApertureFunction::ViaPad,
1095 ));
1096 assert_code!(function, "%TA.AperFunction,ViaPad*%\n");
1097 }
1098
1099 #[test]
1100 fn test_test_pad() {
1101 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1102 ApertureFunction::TestPad,
1103 ));
1104 assert_code!(function, "%TA.AperFunction,TestPad*%\n");
1105 }
1106
1107 #[test]
1108 fn test_castellated_pad() {
1109 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1110 ApertureFunction::CastellatedPad,
1111 ));
1112 assert_code!(function, "%TA.AperFunction,CastellatedPad*%\n");
1113 }
1114
1115 #[test]
1116 fn test_fiducial_pad() {
1117 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1118 ApertureFunction::FiducialPad(FiducialScope::Global),
1119 ));
1120 assert_code!(function, "%TA.AperFunction,FiducialPad,Global*%\n");
1121
1122 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1123 ApertureFunction::FiducialPad(FiducialScope::Local),
1124 ));
1125 assert_code!(function, "%TA.AperFunction,FiducialPad,Local*%\n");
1126
1127 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1128 ApertureFunction::FiducialPad(FiducialScope::Panel),
1129 ));
1130 assert_code!(function, "%TA.AperFunction,FiducialPad,Panel*%\n");
1131 }
1132
1133 #[test]
1134 fn test_thermal_relief_pad() {
1135 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1136 ApertureFunction::ThermalReliefPad,
1137 ));
1138 assert_code!(function, "%TA.AperFunction,ThermalReliefPad*%\n");
1139 }
1140
1141 #[test]
1142 fn test_washer_pad() {
1143 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1144 ApertureFunction::WasherPad,
1145 ));
1146 assert_code!(function, "%TA.AperFunction,WasherPad*%\n");
1147 }
1148
1149 #[test]
1150 fn test_anti_pad() {
1151 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1152 ApertureFunction::AntiPad,
1153 ));
1154 assert_code!(function, "%TA.AperFunction,AntiPad*%\n");
1155 }
1156
1157 #[test]
1158 fn test_other_pad() {
1159 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1160 ApertureFunction::OtherPad("CustomPad".to_string()),
1161 ));
1162 assert_code!(function, "%TA.AperFunction,OtherPad,CustomPad*%\n");
1163 }
1164
1165 #[test]
1166 fn test_conductor() {
1167 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1168 ApertureFunction::Conductor,
1169 ));
1170 assert_code!(function, "%TA.AperFunction,Conductor*%\n");
1171 }
1172
1173 #[test]
1174 fn test_etched_component() {
1175 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1176 ApertureFunction::EtchedComponent,
1177 ));
1178 assert_code!(function, "%TA.AperFunction,EtchedComponent*%\n");
1179 }
1180
1181 #[test]
1182 fn test_non_conductor() {
1183 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1184 ApertureFunction::NonConductor,
1185 ));
1186 assert_code!(function, "%TA.AperFunction,NonConductor*%\n");
1187 }
1188
1189 #[test]
1190 fn test_copper_balancing() {
1191 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1192 ApertureFunction::CopperBalancing,
1193 ));
1194 assert_code!(function, "%TA.AperFunction,CopperBalancing*%\n");
1195 }
1196
1197 #[test]
1198 fn test_border() {
1199 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1200 ApertureFunction::Border,
1201 ));
1202 assert_code!(function, "%TA.AperFunction,Border*%\n");
1203 }
1204
1205 #[test]
1206 fn test_other_copper() {
1207 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1208 ApertureFunction::OtherCopper("CustomCopper".to_string()),
1209 ));
1210 assert_code!(function, "%TA.AperFunction,OtherCopper,CustomCopper*%\n");
1211 }
1212
1213 #[test]
1218 fn test_profile() {
1219 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1220 ApertureFunction::Profile,
1221 ));
1222 assert_code!(function, "%TA.AperFunction,Profile*%\n");
1223 }
1224
1225 #[test]
1226 fn test_material() {
1227 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1228 ApertureFunction::Material,
1229 ));
1230 assert_code!(function, "%TA.AperFunction,Material*%\n");
1231 }
1232
1233 #[test]
1234 fn test_non_material() {
1235 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1236 ApertureFunction::NonMaterial,
1237 ));
1238 assert_code!(function, "%TA.AperFunction,NonMaterial*%\n");
1239 }
1240
1241 #[test]
1242 fn test_other() {
1243 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1244 ApertureFunction::Other("CustomFunction".to_string()),
1245 ));
1246 assert_code!(function, "%TA.AperFunction,Other,CustomFunction*%\n");
1247 }
1248
1249 #[test]
1254 fn test_component_main() {
1255 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1256 ApertureFunction::ComponentMain,
1257 ));
1258 assert_code!(function, "%TA.AperFunction,ComponentMain*%\n");
1259 }
1260
1261 #[test]
1262 fn test_component_outline() {
1263 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1264 ApertureFunction::ComponentOutline(ComponentOutline::Body),
1265 ));
1266 assert_code!(function, "%TA.AperFunction,ComponentOutline,Body*%\n");
1267
1268 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1269 ApertureFunction::ComponentOutline(ComponentOutline::Lead2Lead),
1270 ));
1271 assert_code!(function, "%TA.AperFunction,ComponentOutline,Lead2Lead*%\n");
1272
1273 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1274 ApertureFunction::ComponentOutline(ComponentOutline::Footprint),
1275 ));
1276 assert_code!(function, "%TA.AperFunction,ComponentOutline,Footprint*%\n");
1277
1278 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1279 ApertureFunction::ComponentOutline(ComponentOutline::Courtyard),
1280 ));
1281 assert_code!(function, "%TA.AperFunction,ComponentOutline,Courtyard*%\n");
1282 }
1283
1284 #[test]
1285 fn test_component_pin() {
1286 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1287 ApertureFunction::ComponentPin,
1288 ));
1289 assert_code!(function, "%TA.AperFunction,ComponentPin*%\n");
1290 }
1291
1292 #[test]
1297 fn test_slot_deprecated() {
1298 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1299 ApertureFunction::Slot,
1300 ));
1301 assert_code!(function, "%TA.AperFunction,Slot*%\n");
1302 }
1303 #[test]
1304 fn test_cutout_deprecated() {
1305 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1306 ApertureFunction::CutOut,
1307 ));
1308 assert_code!(function, "%TA.AperFunction,CutOut*%\n");
1309 }
1310
1311 #[test]
1312 fn test_cavity_deprecated() {
1313 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1314 ApertureFunction::Cavity,
1315 ));
1316 assert_code!(function, "%TA.AperFunction,Cavity*%\n");
1317 }
1318
1319 #[test]
1320 fn test_drawing_deprecated() {
1321 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::ApertureFunction(
1322 ApertureFunction::Drawing,
1323 ));
1324 assert_code!(function, "%TA.AperFunction,Drawing*%\n");
1325 }
1326
1327 mod user_defined_attribute {
1328 use super::*;
1329
1330 #[test]
1331 fn test_non_standard() {
1332 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::UserDefined {
1333 name: "NonStandardAttribute".to_string(),
1334 values: vec!["Value 1 ".to_string(), " Value 2".to_string()],
1335 });
1336 assert_code!(function, "%TANonStandardAttribute,Value 1 , Value 2*%\n");
1338 }
1339
1340 #[test]
1341 fn test_unsupported_standard() {
1342 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::UserDefined {
1343 name: ".UnsupportedStandardAttribute".to_string(),
1344 values: vec!["Value 1 ".to_string(), " Value 2".to_string()],
1345 });
1346 assert_code!(
1348 function,
1349 "%TA.UnsupportedStandardAttribute,Value 1 , Value 2*%\n"
1350 );
1351 }
1352 }
1353 }
1354
1355 mod drill_tolerance {
1356 use super::*;
1357
1358 #[test]
1359 fn test_attribute() {
1360 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::DrillTolerance {
1361 plus: 1.0,
1362 minus: 2.0,
1363 });
1364 assert_code!(function, "%TA.DrillTolerance,1,2*%\n");
1365 }
1366 }
1367
1368 mod flash_text {
1369 use super::*;
1370 #[test]
1371 fn test_attribute() {
1372 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::FlashText {
1373 text: "Test".to_string(),
1374 mode: TextMode::Characters,
1375 mirroring: Some(TextMirroring::Readable),
1376 font: Some("Font Name".to_string()),
1377 size: Some(10),
1378 comment: Some("A Comment".to_string()),
1379 });
1380 assert_code!(
1381 function,
1382 "%TA.FlashText,Test,C,R,Font Name,10,A Comment*%\n"
1383 );
1384
1385 let function = ExtendedCode::ApertureAttribute(ApertureAttribute::FlashText {
1386 text: "Test".to_string(),
1387 mode: TextMode::BarCode,
1388 mirroring: Some(TextMirroring::Mirrored),
1389 font: None,
1390 size: None,
1391 comment: None,
1392 });
1393 assert_code!(function, "%TA.FlashText,Test,B,M,,,*%\n");
1395 }
1396 }
1397
1398 mod object_attribute {
1399 use super::*;
1400
1401 mod net {
1402 use super::*;
1403 #[test]
1404 fn test_none() {
1405 let function = ExtendedCode::ObjectAttribute(ObjectAttribute::Net(Net::None));
1406 assert_code!(function, "%TO.N,*%\n");
1407 }
1408
1409 #[test]
1410 fn test_not_connected() {
1411 let function =
1412 ExtendedCode::ObjectAttribute(ObjectAttribute::Net(Net::NotConnected));
1413 assert_code!(function, "%TO.N,N/C*%\n");
1414 }
1415
1416 #[test]
1417 fn test_connected() {
1418 let function =
1419 ExtendedCode::ObjectAttribute(ObjectAttribute::Net(Net::Connected(vec![
1420 "Net1".to_string(),
1421 "Net2".to_string(),
1422 "Net3".to_string(),
1423 ])));
1424 assert_code!(function, "%TO.N,Net1,Net2,Net3*%\n");
1425 }
1426 }
1427
1428 mod pin {
1429 use super::*;
1430
1431 #[test]
1432 fn test_pin() {
1433 let function = ExtendedCode::ObjectAttribute(ObjectAttribute::Pin(Pin {
1434 refdes: "U1".to_string(),
1435 name: "1".to_string(),
1436 function: None,
1437 }));
1438 assert_code!(function, "%TO.P,U1,1*%\n");
1439 }
1440
1441 #[test]
1442 fn test_pin_with_functin() {
1443 let function = ExtendedCode::ObjectAttribute(ObjectAttribute::Pin(Pin {
1444 refdes: "Q1".to_string(),
1445 name: "EP".to_string(),
1446 function: Some("Thermal pad".to_string()),
1447 }));
1448 assert_code!(function, "%TO.P,Q1,EP,Thermal pad*%\n");
1449 }
1450 }
1451
1452 mod ref_des {
1453 use super::*;
1454
1455 #[test]
1456 fn test_component() {
1457 let function =
1458 ExtendedCode::ObjectAttribute(ObjectAttribute::Component("R1".to_string()));
1459 assert_code!(function, "%TO.C,R1*%\n");
1460 }
1461 }
1462
1463 mod component_characteristics {
1464 use super::*;
1465
1466 macro_rules! test_string {
1467 ($test:ident, $cc:ident, $value:literal) => {
1468 #[test]
1469 fn $test() {
1470 let string = "A String".to_string();
1471 let func = ExtendedCode::ObjectAttribute(
1472 ObjectAttribute::ComponentCharacteristics(
1473 ComponentCharacteristics::$cc(string.clone()),
1474 ),
1475 );
1476 assert_code!(func, &format!("%TO.{},{}*%\n", $value, string));
1477 }
1478 };
1479 }
1480
1481 macro_rules! test_decimal {
1482 ($test:ident, $cc:ident, $value:literal) => {
1483 #[test]
1484 fn $test() {
1485 let decimal = 100.00;
1486 let func = ExtendedCode::ObjectAttribute(
1487 ObjectAttribute::ComponentCharacteristics(
1488 ComponentCharacteristics::$cc(decimal),
1489 ),
1490 );
1491 assert_code!(func, &format!("%TO.{},{}*%\n", $value, decimal));
1492 }
1493 };
1494 }
1495
1496 test_decimal!(test_rotation, Rotation, "CRot");
1497 test_string!(test_manufacturer, Manufacturer, "CMfr");
1498 test_string!(test_mpn, MPN, "CMPN");
1499 test_string!(test_val, Value, "CVal");
1500
1501 mod mount_type {
1502 use super::*;
1503
1504 #[test]
1505 fn test_through_hole() {
1506 let function =
1507 ExtendedCode::ObjectAttribute(ObjectAttribute::ComponentCharacteristics(
1508 ComponentCharacteristics::Mount(ComponentMounting::ThroughHole),
1509 ));
1510 assert_code!(function, "%TO.CMnt,TH*%\n");
1511 }
1512
1513 #[test]
1514 fn test_smd() {
1515 let function =
1516 ExtendedCode::ObjectAttribute(ObjectAttribute::ComponentCharacteristics(
1517 ComponentCharacteristics::Mount(ComponentMounting::SMD),
1518 ));
1519 assert_code!(function, "%TO.CMnt,SMD*%\n");
1520 }
1521
1522 #[test]
1523 fn test_press_fit() {
1524 let function =
1525 ExtendedCode::ObjectAttribute(ObjectAttribute::ComponentCharacteristics(
1526 ComponentCharacteristics::Mount(ComponentMounting::PressFit),
1527 ));
1528 assert_code!(function, "%TO.CMnt,Pressfit*%\n");
1529 }
1530
1531 #[test]
1532 fn test_press_other() {
1533 let function =
1534 ExtendedCode::ObjectAttribute(ObjectAttribute::ComponentCharacteristics(
1535 ComponentCharacteristics::Mount(ComponentMounting::Other),
1536 ));
1537 assert_code!(function, "%TO.CMnt,Other*%\n");
1538 }
1539 }
1540
1541 test_string!(test_footprint, Footprint, "CFtp");
1542 test_string!(test_packagename, PackageName, "CPgN");
1543 test_string!(test_packagedescription, PackageDescription, "CPgD");
1544 test_decimal!(test_height, Height, "CHgt");
1545 test_string!(test_libraryname, LibraryName, "CLbN");
1546 test_string!(test_librarydescription, LibraryDescription, "CLbD");
1547
1548 #[test]
1549 fn test_supplier() {
1550 let function =
1551 ExtendedCode::ObjectAttribute(ObjectAttribute::ComponentCharacteristics(
1552 ComponentCharacteristics::Supplier(vec![
1553 SupplierPart {
1554 supplier_name: "Supplier Name 1".to_string(),
1555 supplier_part_reference: "Reference 1".to_string(),
1556 },
1557 SupplierPart {
1558 supplier_name: " Supplier Name 2 ".to_string(),
1559 supplier_part_reference: "Reference 2".to_string(),
1560 },
1561 ]),
1562 ));
1563 assert_code!(
1565 function,
1566 "%TO.CSup,Supplier Name 1,Reference 1, Supplier Name 2 ,Reference 2*%\n"
1567 );
1568 }
1569 }
1570
1571 mod user_defined_attribute {
1572 use super::*;
1573
1574 #[test]
1575 fn test_non_standard() {
1576 let function = ExtendedCode::ObjectAttribute(ObjectAttribute::UserDefined {
1577 name: "NonStandardAttribute".to_string(),
1578 values: vec!["Value 1 ".to_string(), " Value 2".to_string()],
1579 });
1580 assert_code!(function, "%TONonStandardAttribute,Value 1 , Value 2*%\n");
1582 }
1583
1584 #[test]
1585 fn test_unsupported_standard() {
1586 let function = ExtendedCode::ObjectAttribute(ObjectAttribute::UserDefined {
1587 name: ".UnsupportedStandardAttribute".to_string(),
1588 values: vec!["Value 1 ".to_string(), " Value 2".to_string()],
1589 });
1590 assert_code!(
1592 function,
1593 "%TO.UnsupportedStandardAttribute,Value 1 , Value 2*%\n"
1594 );
1595 }
1596 }
1597 }
1598
1599 #[test]
1600 fn test_mirror_image() {
1601 let value = ExtendedCode::MirrorImage(ImageMirroring::None);
1602 assert_code!(value, "%MI*%\n");
1603 let value = ExtendedCode::MirrorImage(ImageMirroring::A);
1604 assert_code!(value, "%MIA1*%\n");
1605 let value = ExtendedCode::MirrorImage(ImageMirroring::B);
1606 assert_code!(value, "%MIB1*%\n");
1607 let value = ExtendedCode::MirrorImage(ImageMirroring::AB);
1608 assert_code!(value, "%MIA1B1*%\n");
1609 }
1610
1611 #[test]
1612 fn test_offset_image() {
1613 let value = ExtendedCode::OffsetImage(ImageOffset { a: 0.0, b: 0.0 });
1614 assert_code!(value, "%OF*%\n");
1615 let value = ExtendedCode::OffsetImage(ImageOffset {
1616 a: 99999.99999,
1617 b: 0.0,
1618 });
1619 assert_code!(value, "%OFA99999.99999*%\n");
1620 let value = ExtendedCode::OffsetImage(ImageOffset {
1621 a: 0.0,
1622 b: 99999.99999,
1623 });
1624 assert_code!(value, "%OFB99999.99999*%\n");
1625 let value = ExtendedCode::OffsetImage(ImageOffset {
1626 a: -99999.99999,
1627 b: -99999.99999,
1628 });
1629 assert_code!(value, "%OFA-99999.99999B-99999.99999*%\n");
1630 }
1631
1632 #[test]
1633 fn test_scale_image() {
1634 let value = ExtendedCode::ScaleImage(ImageScaling { a: 0.0, b: 0.0 });
1635 assert_code!(value, "%SF*%\n");
1636 let value = ExtendedCode::ScaleImage(ImageScaling {
1637 a: 999.99999,
1638 b: 0.0,
1639 });
1640 assert_code!(value, "%SFA999.99999*%\n");
1641 let value = ExtendedCode::ScaleImage(ImageScaling {
1642 a: 0.0,
1643 b: 999.99999,
1644 });
1645 assert_code!(value, "%SFB999.99999*%\n");
1646 let value = ExtendedCode::ScaleImage(ImageScaling {
1647 a: -999.99999,
1648 b: -999.99999,
1649 });
1650 assert_code!(value, "%SFA-999.99999B-999.99999*%\n");
1651 }
1652
1653 #[test]
1654 fn test_rotate_image() {
1655 let value = ExtendedCode::RotateImage(ImageRotation::None);
1656 assert_code!(value, "%IR0*%\n");
1657 let value = ExtendedCode::RotateImage(ImageRotation::CCW_90);
1658 assert_code!(value, "%IR90*%\n");
1659 let value = ExtendedCode::RotateImage(ImageRotation::CCW_180);
1660 assert_code!(value, "%IR180*%\n");
1661 let value = ExtendedCode::RotateImage(ImageRotation::CCW_270);
1662 assert_code!(value, "%IR270*%\n");
1663 }
1664
1665 #[test]
1666 fn test_image_polarity() {
1667 let value = ExtendedCode::ImagePolarity(ImagePolarity::Positive);
1668 assert_code!(value, "%IPPOS*%\n");
1669 let value = ExtendedCode::ImagePolarity(ImagePolarity::Negative);
1670 assert_code!(value, "%IPNEG*%\n");
1671 }
1672
1673 #[test]
1674 fn test_axis_select() {
1675 let value = ExtendedCode::AxisSelect(AxisSelect::AXBY);
1676 assert_code!(value, "%ASAXBY*%\n");
1677 let value = ExtendedCode::AxisSelect(AxisSelect::AYBX);
1678 assert_code!(value, "%ASAYBX*%\n");
1679 }
1680
1681 #[test]
1682 fn test_image_name() {
1683 let value = ExtendedCode::ImageName(ImageName {
1684 name: "PANEL_1".to_string(),
1685 });
1686 assert_code!(value, "%INPANEL_1*%\n");
1687 }
1688}