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
106
use std::collections::HashMap;
use memory::repr::FlatMemoryRepr;
fn read_byte<'a, T: Iterator<Item=&'a u8>>(data: T) -> Result<u8, String> {
let hex = data.take(2).map(|x| *x).collect::<Vec<u8>>();
if hex.len() != 2 {
return Err("Not enough data.".to_owned());
}
match String::from_utf8(hex) {
Ok(hexstr) => {
match u8::from_str_radix(&hexstr, 16) {
Ok(value) => Ok(value),
Err(e) => Err(format!("{}", e).to_owned())
}
},
Err(e) => Err(format!("{}", e).to_owned())
}
}
pub fn from_hex(data: &Vec<u8>) -> Result<HashMap<u8, FlatMemoryRepr>, String> {
let lines = data.split(|x| *x == ('\n' as u8));
let parsed_lines: Result<Vec<(u8, u16, Vec<u8>)>, String> = lines.enumerate().filter(|(_, line)| line.len() != 0).map(|(idx, line)| {
if line.len() < 3 {
return Err(format!("Invalid line: {}", idx).to_owned());
}
if line[0] != ':' as u8 {
return Err(format!("Line {} does not begin with ':'", idx).to_owned());
}
let mut bytesiter = line[1..].into_iter();
let length = match read_byte(bytesiter.by_ref()) {
Ok(value) => value,
Err(e) => return Err(e)
};
let address = match (read_byte(bytesiter.by_ref()), read_byte(bytesiter.by_ref())) {
(Ok(high), Ok(low)) => ((high as u16) << 8) | (low as u16),
_ => return Err(format!("Line {} was invalid", idx).to_owned())
};
let tag = match read_byte(bytesiter.by_ref()) {
Ok(value) => value,
Err(e) => return Err(e)
};
let data: Vec<u8> = match (0..length).map(|_| {
read_byte(bytesiter.by_ref())
}).collect() {
Ok(data) => data,
Err(e) => return Err(e)
};
Ok((tag, address, data))
}).collect();
match parsed_lines {
Ok(lines) => {
let mut section = 0u8;
let mut end = false;
let mut repr: HashMap<u8, FlatMemoryRepr> = HashMap::new();
let _: Result<Vec<()>, String> = lines.into_iter().map(|(tag, address, data)| {
if end {
return Err("Malformed data: data after end of file.".to_owned());
}
match tag {
0 => {
let mem = repr.entry(section).or_insert_with(|| FlatMemoryRepr::empty("from_hex".to_string()));
mem.add(data, address as usize).unwrap();
Ok(())
},
1 => {
end = true;
Ok(())
},
4 => {
if data.len() != 2 {
return Err("Invalid length of data line".to_owned());
}
if data[0] != 0 {
return Err("Section too large".to_owned());
}
section = data[1];
Ok(())
}
_ => { panic!("unrecognized tag type: {}", tag); }
}
}).collect();
Ok(repr)
},
Err(e) => Err(e)
}
}