use std::fmt; pub struct Ram { pub array: [u8; u16::max_value() as usize + 1], } impl fmt::Debug for Ram { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut c = 0; let mut v: Vec = vec![]; for x in self.array.into_iter() { for hex_char in format!("{:02X}", *x).chars() { v.push(hex_char); } v.push(' '); if c % 8 == 7 { v.push('\n'); } c += 1; } write!(f, "{}", v.iter().collect::()) } } enum Rectyp { Data, EndOfFile, //ExtendedSegAddr, //StartSegAddr, //ExtendedLinearAddr, //StartLinearAddr, } struct HexLine { rectyp: Rectyp, offset: u16, data: Vec, } impl HexLine { fn from(s: &str) -> Result { // The shortest possible sequence is EOF (:00000001FF) if s.len() < 11 { return Err(usize::max_value()) } if &s[0..1] != ":" { return Err(0) } let offset = match u16::from_str_radix(&s[3..7], 16) { Ok(value) => value, Err(_) => return Err(3), }; let bytecount = match usize::from_str_radix(&s[1..3], 16) { Ok(value) => value, Err(_) => return Err(1), }; // If EOF reached if &s[7..9] == "01" { return Ok(HexLine { rectyp: Rectyp::EndOfFile, offset, data: vec![0] }) } else if &s[7..9] == "00" { let mut counter = 9; let mut data = vec![]; while counter < s.len() - 2 && counter < (9 + bytecount * 2) { data.push(match u8::from_str_radix(&s[counter..counter+2], 16) { Ok(value) => value, Err(_) => return Err(counter), }); counter += 2; } // TODO: check checksum return Ok(HexLine { rectyp: Rectyp::Data, offset, data }) } Err(3) } } impl Ram { pub fn from_hex(hex: String) -> Result { let mut array = [0; u16::max_value() as usize + 1]; for (linenum, line) in hex.lines().enumerate() { let hex_line = match HexLine::from(line) { Ok(value) => value, Err(charnum) => return Err(format!("ihex parsing error {}:{}", linenum, charnum)), }; let offset = hex_line.offset; match hex_line.rectyp { Rectyp::Data => { for (ptr, byte) in hex_line.data.iter().enumerate() { array[ptr + offset as usize] = *byte; } } Rectyp::EndOfFile => {} } } Ok(Self { array }) } }