|
| 1 | +use ihex::*; |
| 2 | +use thiserror::Error; |
| 3 | + |
| 4 | +#[derive(Debug, Error)] |
| 5 | +pub enum UnpackingError { |
| 6 | + #[error("Unsupported record type")] |
| 7 | + UnsupportedRecordType(Record), |
| 8 | + #[error("Error while parsing IHEX records")] |
| 9 | + Parsing(#[from] ReaderError), |
| 10 | + #[error("Address ({0}) greater than binary size ({1})")] |
| 11 | + AddressTooHigh(usize, usize), |
| 12 | +} |
| 13 | + |
| 14 | +#[derive(Debug, Error)] |
| 15 | +pub enum ConversionError { |
| 16 | + #[error("Error while unpacking IHEX into array")] |
| 17 | + Unpacking(#[from] UnpackingError), |
| 18 | + #[error("Errow while writing IHEX to string")] |
| 19 | + Serializing(#[from] WriterError) |
| 20 | +} |
| 21 | + |
| 22 | +pub fn to_ihex(byte_array: Vec<u8>) -> Result<String, ConversionError> { |
| 23 | + let mut result: Vec<Record> = vec![]; |
| 24 | + for (i, chunk) in byte_array.chunks(16).enumerate() { |
| 25 | + result.push(Record::Data { |
| 26 | + offset: (i as u16) * 16, |
| 27 | + value: chunk.to_vec(), |
| 28 | + }); |
| 29 | + } |
| 30 | + result.push(Record::EndOfFile); |
| 31 | + return create_object_file_representation(&result) |
| 32 | + .map_err(ConversionError::from); |
| 33 | +} |
| 34 | + |
| 35 | +pub fn from_ihex(ihex_string: &str, max_length: usize) -> Result<Vec<u8>, ConversionError> { |
| 36 | + let mut reader = Reader::new(ihex_string); |
| 37 | + return unpack_records(&mut reader, max_length) |
| 38 | + .map_err(ConversionError::from); |
| 39 | +} |
| 40 | + |
| 41 | +fn unpack_records( |
| 42 | + records: &mut impl Iterator<Item = Result<Record, ReaderError>>, |
| 43 | + max_length: usize, |
| 44 | +) -> Result<Vec<u8>, UnpackingError> { |
| 45 | + let mut result: Vec<u8> = vec![]; |
| 46 | + for rec in records { |
| 47 | + match rec { |
| 48 | + Ok(rec) => match rec { |
| 49 | + Record::Data { offset, value } => { |
| 50 | + let end_addr = offset as usize + value.len(); |
| 51 | + if end_addr > max_length { |
| 52 | + return Err(UnpackingError::AddressTooHigh(end_addr, max_length)); |
| 53 | + } |
| 54 | + if end_addr > result.len() { |
| 55 | + result.resize(end_addr, 0); |
| 56 | + } |
| 57 | + |
| 58 | + for (n, b) in value.iter().enumerate() { |
| 59 | + result[offset as usize + n] = *b; |
| 60 | + } |
| 61 | + } |
| 62 | + Record::ExtendedSegmentAddress(_base) => { |
| 63 | + return Err(UnpackingError::UnsupportedRecordType(rec)) |
| 64 | + } |
| 65 | + Record::ExtendedLinearAddress(_base) => { |
| 66 | + return Err(UnpackingError::UnsupportedRecordType(rec)) |
| 67 | + } |
| 68 | + Record::EndOfFile => break, |
| 69 | + Record::StartLinearAddress(_) | Record::StartSegmentAddress { .. } => {} |
| 70 | + }, |
| 71 | + Err(err) => return Err(UnpackingError::Parsing(err)), |
| 72 | + } |
| 73 | + } |
| 74 | + return Ok(result); |
| 75 | +} |
0 commit comments