1pub mod emit;
3pub mod parse;
5
6#[cfg(test)]
7mod test {
8 use crate::{emit::FormatOptions, parse::into_diagnostic};
9 use pretty_assertions::assert_eq;
10
11 #[test]
12 #[cfg(feature = "codespan_helpers")]
13 fn parsing_gcode_then_emitting_then_parsing_again_returns_functionally_identical_gcode() {
14 use codespan_reporting::diagnostic::{Diagnostic, Label};
15 use codespan_reporting::term::{
16 emit,
17 termcolor::{ColorChoice, StandardStream},
18 };
19
20 let mut writer = StandardStream::stderr(ColorChoice::Auto);
21 let config = codespan_reporting::term::Config::default();
22
23 for str in [
24 include_str!("../tests/square.gcode"),
25 include_str!("../tests/edge_cases.gcode"),
26 include_str!("../tests/vandy_commodores_logo.gcode"),
27 include_str!("../tests/ncviewer_sample.gcode"),
28 ] {
29 let parsed_file = crate::parse::file_parser(str).unwrap();
30 let emission_tokens = parsed_file.iter_emit_tokens().collect::<Vec<_>>();
31
32 for format_options in [true, false]
33 .iter()
34 .copied()
35 .map(|a| [[a, true], [a, false]])
36 .flatten()
37 .map(|[a, b]| [[a, b, true], [a, b, false]])
38 .flatten()
39 .map(|[a, b, c]| [[a, b, c, true], [a, b, c, false]])
40 .flatten()
41 .map(
42 |[checksums, line_numbers, delimit_with_percent, newline_before_comment]| {
43 FormatOptions {
44 checksums,
45 line_numbers,
46 delimit_with_percent,
47 newline_before_comment,
48 }
49 },
50 )
51 {
52 let mut emitted_gcode = String::new();
53 crate::emit::format_gcode_fmt(
54 emission_tokens.iter(),
55 format_options,
56 &mut emitted_gcode,
57 )
58 .unwrap();
59
60 let reparsed_file = match super::parse::file_parser(&emitted_gcode) {
61 Ok(reparsed) => reparsed,
62 Err(err) => {
63 emit(
64 &mut writer,
65 &config,
66 &codespan_reporting::files::SimpleFile::new(
67 "test_input.gcode",
68 emitted_gcode,
69 ),
70 &into_diagnostic(&err),
71 )
72 .unwrap();
73 panic!("{}", err);
74 }
75 };
76
77 for line in reparsed_file.iter() {
78 let validated_checksum = line.validate_checksum();
79 assert!(
80 validated_checksum.clone().transpose().is_ok(),
81 "got {:?} for {:#?}",
82 validated_checksum,
83 line
84 );
85 }
86
87 parsed_file
88 .iter_fields()
89 .filter(|field| field.letters != "N")
90 .zip(
91 reparsed_file
92 .iter_fields()
93 .filter(|field| field.letters != "N"),
94 )
95 .for_each(|(expected, actual)| {
96 if expected.value != actual.value || expected.letters != actual.letters {
97 emit(
98 &mut writer,
99 &config,
100 &codespan_reporting::files::SimpleFile::new(
101 "test_input.gcode",
102 str,
103 ),
104 &Diagnostic::error()
105 .with_message("fields do not match")
106 .with_labels(vec![Label::primary((), expected.span)
107 .with_message("this one here officer")]),
108 )
109 .unwrap();
110 }
111 assert_eq!(
112 expected.letters, actual.letters,
113 "{:?} vs {:?}",
114 expected, actual
115 );
116 assert_eq!(
117 expected.value, actual.value,
118 "{:?} vs {:?}",
119 expected, actual
120 );
121 })
122 }
123 }
124 }
125}