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::{file_header_parser, FileHeader};
39use file_metadata_block::{
40 file_metadata_parser, file_metadata_parser_with_checksum, FileMetadataBlock,
41};
42use nom::{
43 combinator::{eof, map, opt},
44 error::{ErrorKind, ParseError},
45 multi::{many0, many_till},
46 IResult, Parser,
47};
48
49use compression_type::CompressionType;
50use gcode_block::{gcode_parser, gcode_parser_with_checksum, GCodeBlock};
51use print_metadata_block::{
52 print_metadata_parser, print_metadata_parser_with_checksum, PrintMetadataBlock,
53};
54use printer_metadata_block::PrinterMetadataBlock;
55use printer_metadata_block::{printer_metadata_parser, printer_metadata_parser_with_checksum};
56use slicer_block::{slicer_parser, slicer_parser_with_checksum, SlicerBlock};
57use thumbnail_block::ThumbnailBlock;
58use thumbnail_block::{thumbnail_parser, thumbnail_parser_with_checksum};
59
60pub trait Markdown {
62 fn markdown<W>(&self, f: &mut W) -> core::fmt::Result
67 where
68 W: core::fmt::Write;
69}
70
71#[derive(Debug)]
73pub enum BlockError {
74 FileHeader,
76 FileMetaData,
78 Gcode,
80 PrinterMetaData,
82 PrintMetaData,
84 Slicer,
86 Thumbnail,
88 EOF,
90 ParseError,
92}
93
94impl<I> ParseError<I> for BlockError
95where
96 I: std::fmt::Debug,
97{
98 fn from_error_kind(_input: I, _kind: ErrorKind) -> Self {
99 Self::EOF
101 }
102
103 fn append(_input: I, _kind: ErrorKind, _other: Self) -> Self {
105 Self::ParseError
106 }
107
108 fn from_char(input: I, c: char) -> Self {
109 let message = format!("'{c}':\t{input:?}\n",);
110 println!("{message}");
111 Self::ParseError
113 }
114
115 fn or(self, _other: Self) -> Self {
116 Self::ParseError
117 }
118}
119
120#[derive(Clone, Debug, PartialEq, Eq)]
124pub struct Bgcode<'a> {
125 fh: FileHeader,
126 pub file_metadata: Option<FileMetadataBlock<'a>>,
128 pub printer_metadata: PrinterMetadataBlock<'a>,
130 pub thumbnails: Vec<ThumbnailBlock<'a>>,
132 pub print_metadata: PrintMetadataBlock<'a>,
134 pub slicer: SlicerBlock<'a>,
136 pub gcode: Vec<GCodeBlock<'a>>,
138}
139
140impl Display for Bgcode<'_> {
141 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
142 writeln!(f, "{}", self.fh)?;
143
144 if let Some(file_metadata) = &self.file_metadata {
145 writeln!(f, "{file_metadata}")?;
146 } else {
147 writeln!(f, "No optional file metadata block")?;
148 }
149
150 writeln!(f, "{}", &self.printer_metadata)?;
151
152 if self.thumbnails.is_empty() {
153 writeln!(f, "No optional thumbnail block")?;
154 } else {
155 for thumb in &self.thumbnails {
156 writeln!(f, "{thumb}")?;
157 }
158 }
159
160 writeln!(f, "{}", self.print_metadata)?;
161
162 writeln!(f, "{}", self.slicer)?;
163
164 if self.gcode.is_empty() {
165 writeln!(f, "No optional thumbnail block")?;
166 } else {
167 for g in &self.gcode {
168 writeln!(f, "{g}")?;
169 }
170 }
171 Ok(())
172 }
173}
174
175impl Markdown for Bgcode<'_> {
176 fn markdown<W>(&self, f: &mut W) -> core::fmt::Result
181 where
182 W: std::fmt::Write,
183 {
184 self.fh.markdown(&mut *f)?;
185
186 if let Some(file_metadata) = &self.file_metadata {
187 file_metadata.markdown(&mut *f)?;
188 } else {
189 writeln!(f, "No optional file metadata block")?;
190 }
191
192 self.printer_metadata.markdown(&mut *f)?;
193
194 self.thumbnails.markdown(&mut *f)?;
195
196 self.print_metadata.markdown(&mut *f)?;
197
198 self.slicer.markdown(&mut *f)?;
199
200 self.gcode.markdown(f)?;
201
202 Ok(())
203 }
204}
205
206pub fn bgcode_parser(input: &[u8]) -> IResult<&[u8], Bgcode, BlockError> {
213 map(
214 (
215 file_header_parser,
216 opt(file_metadata_parser),
217 printer_metadata_parser,
218 many0(thumbnail_parser),
219 print_metadata_parser,
220 slicer_parser,
221 many_till(gcode_parser, eof),
223 ),
224 |(
225 fh,
226 file_metadata,
227 printer_metadata,
228 thumbnail,
229 print_metadata,
230 slicer,
231 (gcode, _remain),
232 )| {
233 log::info!("File has been validated");
234 Bgcode {
235 fh,
236 file_metadata,
237 printer_metadata,
238 thumbnails: thumbnail,
239 print_metadata,
240 slicer,
241 gcode,
242 }
243 },
244 )
245 .parse(input)
246}
247
248pub fn bgcode_parser_with_checksum(input: &[u8]) -> IResult<&[u8], Bgcode, BlockError> {
256 map(
257 (
258 file_header_parser,
259 opt(file_metadata_parser_with_checksum),
260 printer_metadata_parser_with_checksum,
261 many0(thumbnail_parser_with_checksum),
262 print_metadata_parser_with_checksum,
263 slicer_parser_with_checksum,
264 many_till(gcode_parser_with_checksum, eof),
266 ),
267 |(
268 fh,
269 file_metadata,
270 printer_metadata,
271 thumbnail,
272 print_metadata,
273 slicer,
274 (gcode, _remain),
275 )| {
276 log::info!("File has been validated");
277 Bgcode {
278 fh,
279 file_metadata,
280 printer_metadata,
281 thumbnails: thumbnail,
282 print_metadata,
283 slicer,
284 gcode,
285 }
286 },
287 )
288 .parse(input)
289}