1pub mod gcode_block;
22pub mod inflate;
24
25mod block_header;
26mod compression_type;
27mod default_params;
28mod file_handler;
29mod file_metadata_block;
30
31mod print_metadata_block;
32mod printer_metadata_block;
33mod slicer_block;
34mod thumbnail_block;
35
36use core::fmt::Display;
37
38use file_handler::FileHeader;
39use file_handler::file_header_parser;
40use file_metadata_block::FileMetadataBlock;
41use file_metadata_block::file_metadata_parser;
42use file_metadata_block::file_metadata_parser_with_checksum;
43use nom::IResult;
44use nom::Parser;
45use nom::combinator::eof;
46use nom::combinator::map;
47use nom::combinator::opt;
48use nom::error::ErrorKind;
49use nom::error::ParseError;
50use nom::multi::many_till;
51use nom::multi::many0;
52
53use compression_type::CompressionType;
54use gcode_block::GCodeBlock;
55use gcode_block::gcode_parser;
56use gcode_block::gcode_parser_with_checksum;
57use print_metadata_block::PrintMetadataBlock;
58use print_metadata_block::print_metadata_parser;
59use print_metadata_block::print_metadata_parser_with_checksum;
60use printer_metadata_block::PrinterMetadataBlock;
61use printer_metadata_block::printer_metadata_parser;
62use printer_metadata_block::printer_metadata_parser_with_checksum;
63use slicer_block::SlicerBlock;
64use slicer_block::slicer_parser;
65use slicer_block::slicer_parser_with_checksum;
66use thumbnail_block::ThumbnailBlock;
67use thumbnail_block::thumbnail_parser;
68use thumbnail_block::thumbnail_parser_with_checksum;
69
70pub trait Markdown {
72 fn markdown<W>(&self, f: &mut W) -> core::fmt::Result
77 where
78 W: core::fmt::Write;
79}
80
81#[derive(Debug)]
83pub enum BlockError {
84 FileHeader,
86 FileMetaData,
88 Gcode,
90 PrinterMetaData,
92 PrintMetaData,
94 Slicer,
96 Thumbnail,
98 EOF,
100 ParseError,
102}
103
104impl<I> ParseError<I> for BlockError
105where
106 I: std::fmt::Debug,
107{
108 fn from_error_kind(_input: I, _kind: ErrorKind) -> Self {
109 Self::EOF
111 }
112
113 fn append(_input: I, _kind: ErrorKind, _other: Self) -> Self {
115 Self::ParseError
116 }
117
118 fn from_char(input: I, c: char) -> Self {
119 let message = format!("'{c}':\t{input:?}\n",);
120 println!("{message}");
121 Self::ParseError
123 }
124
125 fn or(self, _other: Self) -> Self {
126 Self::ParseError
127 }
128}
129
130#[derive(Clone, Debug, PartialEq, Eq)]
134pub struct Bgcode<'a> {
135 fh: FileHeader,
136 pub file_metadata: Option<FileMetadataBlock<'a>>,
138 pub printer_metadata: PrinterMetadataBlock<'a>,
140 pub thumbnails: Vec<ThumbnailBlock<'a>>,
142 pub print_metadata: PrintMetadataBlock<'a>,
144 pub slicer: SlicerBlock<'a>,
146 pub gcode: Vec<GCodeBlock<'a>>,
148}
149
150impl Display for Bgcode<'_> {
151 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
152 writeln!(f, "{}", self.fh)?;
153
154 if let Some(file_metadata) = &self.file_metadata {
155 writeln!(f, "{file_metadata}")?;
156 } else {
157 writeln!(f, "No optional file metadata block")?;
158 }
159
160 writeln!(f, "{}", &self.printer_metadata)?;
161
162 if self.thumbnails.is_empty() {
163 writeln!(f, "No optional thumbnail block")?;
164 } else {
165 for thumb in &self.thumbnails {
166 writeln!(f, "{thumb}")?;
167 }
168 }
169
170 writeln!(f, "{}", self.print_metadata)?;
171
172 writeln!(f, "{}", self.slicer)?;
173
174 if self.gcode.is_empty() {
175 writeln!(f, "No optional thumbnail block")?;
176 } else {
177 for g in &self.gcode {
178 writeln!(f, "{g}")?;
179 }
180 }
181 Ok(())
182 }
183}
184
185impl Markdown for Bgcode<'_> {
186 fn markdown<W>(&self, f: &mut W) -> core::fmt::Result
191 where
192 W: std::fmt::Write,
193 {
194 self.fh.markdown(&mut *f)?;
195
196 if let Some(file_metadata) = &self.file_metadata {
197 file_metadata.markdown(&mut *f)?;
198 } else {
199 writeln!(f, "No optional file metadata block")?;
200 }
201
202 self.printer_metadata.markdown(&mut *f)?;
203
204 self.thumbnails.markdown(&mut *f)?;
205
206 self.print_metadata.markdown(&mut *f)?;
207
208 self.slicer.markdown(&mut *f)?;
209
210 self.gcode.markdown(f)?;
211
212 Ok(())
213 }
214}
215
216pub fn bgcode_parser(input: &[u8]) -> IResult<&[u8], Bgcode<'_>, BlockError> {
223 map(
224 (
225 file_header_parser,
226 opt(file_metadata_parser),
227 printer_metadata_parser,
228 many0(thumbnail_parser),
229 print_metadata_parser,
230 slicer_parser,
231 many_till(gcode_parser, eof),
233 ),
234 |(
235 fh,
236 file_metadata,
237 printer_metadata,
238 thumbnail,
239 print_metadata,
240 slicer,
241 (gcode, _remain),
242 )| {
243 log::info!("File has been validated");
244 Bgcode {
245 fh,
246 file_metadata,
247 printer_metadata,
248 thumbnails: thumbnail,
249 print_metadata,
250 slicer,
251 gcode,
252 }
253 },
254 )
255 .parse(input)
256}
257
258pub fn bgcode_parser_with_checksum(input: &[u8]) -> IResult<&[u8], Bgcode<'_>, BlockError> {
266 map(
267 (
268 file_header_parser,
269 opt(file_metadata_parser_with_checksum),
270 printer_metadata_parser_with_checksum,
271 many0(thumbnail_parser_with_checksum),
272 print_metadata_parser_with_checksum,
273 slicer_parser_with_checksum,
274 many_till(gcode_parser_with_checksum, eof),
276 ),
277 |(
278 fh,
279 file_metadata,
280 printer_metadata,
281 thumbnail,
282 print_metadata,
283 slicer,
284 (gcode, _remain),
285 )| {
286 log::info!("File has been validated");
287 Bgcode {
288 fh,
289 file_metadata,
290 printer_metadata,
291 thumbnails: thumbnail,
292 print_metadata,
293 slicer,
294 gcode,
295 }
296 },
297 )
298 .parse(input)
299}