1use byteorder::ByteOrder;
4use std::io::{Error, ErrorKind, Read, Result};
5
6use crate::record::checksum::ChecksumRecord;
7use crate::record::descriptor::descriptor_data::DescriptorDecoded;
8use crate::record::descriptor::{DescriptorRecord, DescriptorTypeRecord};
9use crate::record::filler::FillerRecord;
10use crate::record::firmware::FirmwareRecord;
11use crate::record::main::MainRecord;
12use crate::record::text::TextRecord;
13use crate::{GcdDefaultEndian, Record, RecordHeader};
14
15use std::marker::PhantomData;
16
17#[derive(Debug, PartialEq, Copy, Clone)]
27enum ParseState {
28 TextGlobal,
29 Main,
30 DescriptorType,
31 DescriptorData,
32 FirmwareData,
33 End,
34}
35
36struct ReadCheckSum<F> {
37 file: F,
38 sum: u8,
39}
40
41impl<F> Read for ReadCheckSum<F>
42where
43 F: std::io::Read,
44{
45 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
46 let read = self.file.read(buf)?;
47 for byte in buf[0..read].iter() {
48 self.sum = self.sum.wrapping_add(*byte);
49 }
50 Ok(read)
51 }
52}
53
54impl<F> ReadCheckSum<F>
55where
56 F: std::io::Read,
57{
58 fn new(file: F) -> Self {
59 ReadCheckSum { file, sum: 0 }
60 }
61}
62
63impl<F> ReadCheckSum<F> {
64 const fn sum(&self) -> u8 {
65 self.sum
66 }
67}
68
69#[derive(Default)]
71struct FirmwareData {
72 id: u16,
74 xor_key: u8,
76 lenght: u32,
78 lenght_left: u32,
80}
81
82pub struct Parser<F, B = GcdDefaultEndian>
83where
84 F: std::io::Read,
85 B: ByteOrder,
86{
87 state: ParseState,
88 file: ReadCheckSum<F>,
89 descriptor_type: DescriptorTypeRecord,
90 firmware: FirmwareData,
91 endian: PhantomData<B>,
92}
93
94impl<F, B> Parser<F, B>
95where
96 F: std::io::Read,
97 B: ByteOrder,
98{
99 pub fn new(file: F) -> Result<Self> {
100 let state = ParseState::TextGlobal;
101 let mut file = ReadCheckSum::new(file);
102
103 let mut header_sign = [0u8; 8];
104 file.read_exact(&mut header_sign)?;
105 match &header_sign[..6] {
106 b"GARMIN" => {}
107 _ => {
108 return Err(Error::new(
109 ErrorKind::InvalidData,
110 "Invalid/Unknown Header Signature",
111 ))
112 }
113 }
114
115 let header_version = B::read_u16(&header_sign[6..]);
116 match header_version {
117 100 => {}
118 _ => {
119 return Err(Error::new(
120 ErrorKind::InvalidData,
121 "Invalid/Unknown Header Version",
122 ))
123 }
124 }
125
126 Ok(Self {
127 state,
128 file,
129 descriptor_type: Default::default(),
130 firmware: Default::default(),
131 endian: PhantomData,
132 })
133 }
134
135 pub fn read_record(&mut self) -> Result<Record> {
137 loop {
139 if let ParseState::End = self.state {
140 return Err(Error::new(
143 ErrorKind::InvalidData,
144 "Unable to read after End Record",
145 ));
146 }
147
148 let state = self.state; let record = self.parse_record()?;
150
151 match (state, record) {
153 (_, RecordHeader::Checksum) => {
155 return Ok(Record::Checksum(self.parse_checksum()?));
157 }
158 (_, RecordHeader::Filler(len)) => {
159 return Ok(Record::Filler(self.parse_filler(len)?))
160 }
161
162 (ParseState::TextGlobal, RecordHeader::Text(len)) => {
164 return Ok(Record::Text(self.parse_text(len)?));
165 }
166 (ParseState::TextGlobal, RecordHeader::MainHeader(len)) => {
167 self.state = ParseState::Main;
169 return Ok(Record::MainHeader(
170 self.parse_main_header(len)?,
171 ));
172 }
173
174 (ParseState::Main, RecordHeader::DescriptorType(len)) => {
176 self.state = ParseState::DescriptorType;
178 self.descriptor_type = self.parse_descriptor_type(len)?;
180 }
181 (ParseState::Main, RecordHeader::Text(len)) => {
182 return Ok(Record::Text(self.parse_text(len)?));
184 }
185
186 (
188 ParseState::DescriptorType,
189 RecordHeader::DescriptorData(len),
190 ) => {
191 self.state = ParseState::DescriptorData;
192 return Ok(Record::Descriptor(
194 self.parse_descriptor_data(len)?,
195 ));
196 }
197
198 (
200 ParseState::DescriptorData,
201 RecordHeader::DescriptorType(len),
202 ) => {
203 self.state = ParseState::DescriptorType;
205 self.check_firmware_end()?;
208 self.descriptor_type = self.parse_descriptor_type(len)?;
209 }
210 (
211 ParseState::DescriptorData,
212 RecordHeader::Unknown { id, len },
213 ) => {
214 self.state = ParseState::FirmwareData;
216 return Ok(Record::FirmwareData(
218 self.parse_firmware_data(id, len)?,
219 ));
220 }
221 (ParseState::DescriptorData, RecordHeader::Text(len)) => {
222 return Ok(Record::Text(self.parse_text(len)?));
224 }
225 (ParseState::DescriptorData, RecordHeader::End) => {
226 self.state = ParseState::End;
229 self.check_firmware_end()?;
231 return Ok(Record::End);
232 }
233
234 (ParseState::FirmwareData, RecordHeader::Text(len)) => {
236 let text = self.parse_text(len)?;
237 return Ok(Record::Text(text));
238 }
239 (
240 ParseState::FirmwareData,
241 RecordHeader::Unknown { id, len },
242 ) => {
243 return Ok(Record::FirmwareData(
246 self.parse_firmware_data(id, len)?,
247 ));
248 }
249 (ParseState::FirmwareData, RecordHeader::End) => {
250 self.state = ParseState::End;
252 self.check_firmware_end()?;
254 return Ok(Record::End);
255 }
256 (
257 ParseState::FirmwareData,
258 RecordHeader::DescriptorType(len),
259 ) => {
260 self.state = ParseState::DescriptorType;
263 self.check_firmware_end()?;
265 self.parse_descriptor_type(len)?;
266 }
267
268 (state, record) => {
269 return Err(Error::new(
270 ErrorKind::InvalidInput,
271 format!(
272 "State {:?} record received {:?}",
273 state, record
274 ),
275 ));
276 }
277 }
278 }
279 }
280
281 fn parse_record(&mut self) -> Result<RecordHeader> {
282 let mut header = [0; 4];
283 self.file.read_exact(&mut header)?;
284 let (_, ret) = RecordHeader::from_raw::<B>(&mut header)?;
285 Ok(ret)
286 }
287
288 fn parse_checksum(&mut self) -> Result<ChecksumRecord> {
289 let mut data = [0];
290 self.file.read_exact(&mut data)?;
291 let checksum = self.file.sum();
292 return Ok(ChecksumRecord::new(&data, checksum)?);
293 }
294
295 fn parse_filler(&mut self, lenght: u16) -> Result<FillerRecord> {
296 let mut data = vec![0; lenght as usize];
297 self.file.read_exact(&mut data)?;
298 return Ok(FillerRecord::new(&data)?);
299 }
300
301 fn parse_main_header(&mut self, lenght: u16) -> Result<MainRecord> {
302 MainRecord::new::<ReadCheckSum<F>, B>(&mut self.file, lenght)
303 }
304
305 fn parse_text(&mut self, lenght: u16) -> Result<TextRecord> {
306 TextRecord::new(&mut self.file, lenght)
307 }
308
309 fn parse_descriptor_type(
310 &mut self,
311 lenght: u16,
312 ) -> Result<DescriptorTypeRecord> {
313 DescriptorTypeRecord::new::<ReadCheckSum<F>, B>(&mut self.file, lenght)
314 }
315
316 fn parse_descriptor_data(&mut self, lenght: u16) -> Result<DescriptorRecord>
317 where
318 F: std::io::Read,
319 {
320 let descriptor = DescriptorRecord::new::<ReadCheckSum<F>, B>(
321 &mut self.file,
322 lenght,
323 &self.descriptor_type,
324 )?;
325
326 let mut firmware_id = None;
328 let mut firmware_lenght = None;
329 let mut xor_key = None;
330 for desc in descriptor.iter() {
332 match desc.decode() {
333 Some(DescriptorDecoded::FirmwareId(x)) => {
334 firmware_id = Some(x);
335 }
336 Some(DescriptorDecoded::FirmwareLen(x)) => {
337 firmware_lenght = Some(x);
338 }
339 Some(DescriptorDecoded::XorKey(x)) => {
340 xor_key = Some(x);
341 }
342 Some(DescriptorDecoded::Firmware2000P1Len(x))
343 | Some(DescriptorDecoded::Firmware2000P2Len(x))
344 | Some(DescriptorDecoded::Firmware2000P3Len(x)) => {
345 firmware_lenght = Some(x);
348 }
349 Some(_) => {}
350 None => {}
351 }
352 }
353 match firmware_id {
355 None => {
356 return Err(Error::new(
357 ErrorKind::InvalidData,
358 "Firmware Id not found",
359 ))
360 }
361 Some(x) => self.firmware.id = x,
362 }
363 match firmware_lenght {
364 None => {
365 return Err(Error::new(
366 ErrorKind::InvalidData,
367 "Firmware Lenght not found",
368 ))
369 }
370 Some(x) => self.firmware.lenght = x,
371 }
372 self.firmware.xor_key = xor_key.unwrap_or(0);
373 self.firmware.lenght_left = self.firmware.lenght;
374 Ok(descriptor)
375 }
376
377 fn parse_firmware_data(
378 &mut self,
379 record_id: u16,
380 record_len: u16,
381 ) -> Result<FirmwareRecord>
382 where
383 F: std::io::Read,
384 {
385 if record_id != self.firmware.id {
386 return Err(Error::new(
387 ErrorKind::InvalidInput,
388 format!(
389 "Firmware id expected {:#x} found {:#x}",
390 self.firmware.id, record_id,
391 ),
392 ));
393 }
394 if self.firmware.lenght_left < record_len as u32 {
396 return Err(Error::new(
397 ErrorKind::InvalidInput,
398 "Firmware Chunk is bigger than expected",
399 ));
400 }
401 self.firmware.lenght_left -= record_len as u32;
402 let mut buf = vec![0u8; record_len as usize];
404 self.file.read_exact(&mut buf)?;
405 if self.firmware.xor_key != 0 {
406 buf.iter_mut().for_each(|x| *x = *x ^ self.firmware.xor_key);
407 }
408 match self.firmware.id {
409 0x05A5 => buf.iter_mut().for_each(|x| *x = *x ^ 0x76),
411 _ => {}
412 }
413 Ok(FirmwareRecord::new(buf, record_id))
414 }
415
416 fn check_firmware_end(&mut self) -> Result<()> {
417 if self.firmware.lenght_left != 0 {
419 return Err(Error::new(
420 ErrorKind::InvalidInput,
421 format!(
422 "Firmware Chunk too small, received {} from {} bytes",
423 self.firmware.lenght - self.firmware.lenght_left,
424 self.firmware.lenght
425 ),
426 ));
427 }
428 Ok(())
429 }
430}