1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
use std::fmt;
pub struct Rom {
pub array: [u8; u16::max_value() as usize + 1],
}
impl fmt::Debug for Rom {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut v: Vec<char> = vec![];
for (c, x) in self.array.iter().enumerate() {
for hex_char in format!("{:02X}", *x).chars() {
v.push(hex_char);
}
v.push(' ');
if c % 8 == 7 {
v.push('\n');
}
}
write!(f, "{}", v.iter().collect::<String>())
}
}
enum Rectyp {
Data,
EndOfFile,
//ExtendedSegAddr,
//StartSegAddr,
//ExtendedLinearAddr,
//StartLinearAddr,
}
struct HexLine {
rectyp: Rectyp,
offset: u16,
data: Vec<u8>,
}
impl HexLine {
fn from(s: &str) -> Result<Self, usize> {
// 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 Rom {
pub fn from_hex(hex: String) -> Result<Self, String> {
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 })
}
}
|