use crate::attributes;
use crate::coordinates;
use crate::extended_codes;
use crate::function_codes;
use crate::macros;
use chrono::{DateTime, FixedOffset};
use std::convert::From;
macro_rules! impl_from {
($from:ty, $target:ty, $variant:expr) => {
impl From<$from> for $target {
fn from(val: $from) -> Self {
$variant(val)
}
}
};
}
#[derive(Debug, Clone, PartialEq)]
pub enum Command {
FunctionCode(FunctionCode),
ExtendedCode(ExtendedCode),
}
impl_from!(FunctionCode, Command, Command::FunctionCode);
impl_from!(ExtendedCode, Command, Command::ExtendedCode);
macro_rules! impl_command_fromfrom {
($from:ty, $inner:path) => {
impl From<$from> for Command {
fn from(val: $from) -> Self {
Command::from($inner(val))
}
}
};
}
#[derive(Debug, Clone, PartialEq)]
pub enum FunctionCode {
DCode(function_codes::DCode),
GCode(function_codes::GCode),
MCode(function_codes::MCode),
}
impl_from!(function_codes::DCode, FunctionCode, FunctionCode::DCode);
impl_from!(function_codes::GCode, FunctionCode, FunctionCode::GCode);
impl_from!(function_codes::MCode, FunctionCode, FunctionCode::MCode);
impl_command_fromfrom!(function_codes::DCode, FunctionCode::from);
impl_command_fromfrom!(function_codes::GCode, FunctionCode::from);
impl_command_fromfrom!(function_codes::MCode, FunctionCode::from);
#[derive(Debug, Clone, PartialEq)]
pub enum ExtendedCode {
CoordinateFormat(coordinates::CoordinateFormat),
Unit(extended_codes::Unit),
ApertureDefinition(extended_codes::ApertureDefinition),
ApertureMacro(macros::ApertureMacro),
LoadPolarity(extended_codes::Polarity),
LoadMirroring(extended_codes::Mirroring),
LoadRotation(extended_codes::Rotation),
LoadScaling(extended_codes::Scaling),
StepAndRepeat(extended_codes::StepAndRepeat),
ApertureBlock(extended_codes::ApertureBlock),
FileAttribute(attributes::FileAttribute),
ObjectAttribute(attributes::ObjectAttribute),
ApertureAttribute(attributes::ApertureAttribute),
DeleteAttribute(attributes::AttributeDeletionCriterion),
MirrorImage(extended_codes::ImageMirroring),
OffsetImage(extended_codes::ImageOffset),
ScaleImage(extended_codes::ImageScaling),
RotateImage(extended_codes::ImageRotation),
ImagePolarity(extended_codes::ImagePolarity),
AxisSelect(extended_codes::AxisSelect),
ImageName(extended_codes::ImageName),
}
impl_from!(
coordinates::CoordinateFormat,
ExtendedCode,
ExtendedCode::CoordinateFormat
);
impl_from!(extended_codes::Unit, ExtendedCode, ExtendedCode::Unit);
impl_from!(
extended_codes::ApertureDefinition,
ExtendedCode,
ExtendedCode::ApertureDefinition
);
impl_from!(
macros::ApertureMacro,
ExtendedCode,
ExtendedCode::ApertureMacro
);
impl_from!(
extended_codes::Polarity,
ExtendedCode,
ExtendedCode::LoadPolarity
);
impl_from!(
extended_codes::Mirroring,
ExtendedCode,
ExtendedCode::LoadMirroring
);
impl_from!(
extended_codes::Rotation,
ExtendedCode,
ExtendedCode::LoadRotation
);
impl_from!(
extended_codes::Scaling,
ExtendedCode,
ExtendedCode::LoadScaling
);
impl_from!(
extended_codes::StepAndRepeat,
ExtendedCode,
ExtendedCode::StepAndRepeat
);
impl_from!(
extended_codes::ApertureBlock,
ExtendedCode,
ExtendedCode::ApertureBlock
);
impl_from!(
attributes::FileAttribute,
ExtendedCode,
ExtendedCode::FileAttribute
);
impl_from!(
attributes::ApertureAttribute,
ExtendedCode,
ExtendedCode::ApertureAttribute
);
impl_command_fromfrom!(coordinates::CoordinateFormat, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::Unit, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::ApertureDefinition, ExtendedCode::from);
impl_command_fromfrom!(macros::ApertureMacro, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::Polarity, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::Scaling, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::Mirroring, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::Rotation, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::StepAndRepeat, ExtendedCode::from);
impl_command_fromfrom!(extended_codes::ApertureBlock, ExtendedCode::from);
impl_command_fromfrom!(attributes::FileAttribute, ExtendedCode::from);
impl_command_fromfrom!(attributes::ApertureAttribute, ExtendedCode::from);
#[cfg(test)]
mod test {
use super::*;
use std::io::BufWriter;
use crate::extended_codes::Polarity;
use crate::function_codes::GCode;
use crate::traits::GerberCode;
use crate::{
ApertureBlock, AttributeDeletionCriterion, CommentContent, Mirroring, Rotation, Scaling,
StepAndRepeat,
};
#[test]
fn test_debug() {
let c = Command::FunctionCode(FunctionCode::GCode(GCode::Comment(CommentContent::String(
"test".to_string(),
))));
let debug = format!("{:?}", c);
assert_eq!(debug, "FunctionCode(GCode(Comment(String(\"test\"))))");
}
#[test]
fn test_function_code_serialize() {
let c = FunctionCode::GCode(GCode::Comment(CommentContent::String(
"comment".to_string(),
)));
assert_code!(c, "G04 comment*\n");
}
#[test]
fn test_function_code_from_gcode() {
let comment = GCode::Comment(CommentContent::String("hello".into()));
let f1: FunctionCode = FunctionCode::GCode(comment.clone());
let f2: FunctionCode = comment.into();
assert_eq!(f1, f2);
}
#[test]
fn test_command_from_function_code() {
let comment = FunctionCode::GCode(GCode::Comment(CommentContent::String("hello".into())));
let c1: Command = Command::FunctionCode(comment.clone());
let c2: Command = comment.into();
assert_eq!(c1, c2);
}
#[test]
fn test_command_from_extended_code() {
let delete_attr = ExtendedCode::DeleteAttribute(
AttributeDeletionCriterion::SingleApertureAttribute("test".to_string()),
);
let c1: Command = Command::ExtendedCode(delete_attr.clone());
let c2: Command = delete_attr.into();
assert_eq!(c1, c2);
}
#[test]
fn test_extended_code_from_step_and_repeat() {
let e1: ExtendedCode = ExtendedCode::StepAndRepeat(StepAndRepeat::Close);
let e2: ExtendedCode = StepAndRepeat::Close.into();
assert_eq!(e1, e2);
}
#[test]
fn test_extended_code_from_aperture_block() {
let e1: ExtendedCode = ExtendedCode::ApertureBlock(ApertureBlock::Open { code: 102 });
let e2: ExtendedCode = ApertureBlock::Open { code: 102 }.into();
assert_eq!(e1, e2);
}
#[test]
fn test_extended_code_from_polarity() {
let e1: ExtendedCode = ExtendedCode::LoadPolarity(Polarity::Dark);
let e2: ExtendedCode = Polarity::Dark.into();
assert_eq!(e1, e2);
}
#[test]
fn test_extended_code_from_mirroring() {
let e1: ExtendedCode = ExtendedCode::LoadMirroring(Mirroring::XY);
let e2: ExtendedCode = Mirroring::XY.into();
assert_eq!(e1, e2);
}
#[test]
fn test_extended_code_from_scaling() {
let e1: ExtendedCode = ExtendedCode::LoadScaling(Scaling { scale: 50.0 });
let e2: ExtendedCode = Scaling { scale: 50.0 }.into();
assert_eq!(e1, e2);
}
#[test]
fn test_extended_code_from_rotation() {
let e1: ExtendedCode = ExtendedCode::LoadRotation(Rotation { rotation: 90.0 });
let e2: ExtendedCode = Rotation { rotation: 90.0 }.into();
assert_eq!(e1, e2);
}
}
pub type GerberDate = DateTime<FixedOffset>;