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
107
108
109
110
111
112
113
use model::Mcu;
use pack;
use std::path::{Path, PathBuf};
use std::{fs, io};
const PACK_FILE_EXT: &'static str = "atdf";
const PACK_COLLECTIONS: &'static [&'static str] = &[
"atmega", "tiny", "xmegaa", "xmegab",
"xmegac", "xmegad", "xmegae", "automotive",
];
const CRATE_ROOT: &'static str = env!("CARGO_MANIFEST_DIR");
lazy_static! {
static ref MCUS: Vec<Mcu> = self::load_microcontrollers().expect("failed to load microcontrollers");
static ref MCU_NAMES: Vec<String> = pack_informations()
.expect("could not find packfiles")
.into_iter()
.map(|pack| pack.mcu_name)
.collect();
}
struct PackInfo {
pub mcu_name: String,
pub path: PathBuf,
}
pub fn microcontrollers() -> &'static [Mcu] {
&MCUS[..]
}
pub fn microcontroller_names() -> &'static [String] {
&MCU_NAMES[..]
}
pub fn microcontroller(name: &str) -> Mcu {
let pack_info = pack_informations().unwrap()
.into_iter()
.find(|pack_info| pack_info.mcu_name == name)
.expect(&format!("no microcontroller with the name '{}' found", name));
pack::load(&pack_info.path).expect("could not parse microcontroller pack")
}
fn load_microcontrollers() -> Result<Vec<Mcu>, io::Error> {
let microcontrollers = pack_informations()?.into_iter()
.map(|pack_info| pack::load(&pack_info.path).unwrap())
.collect();
Ok(microcontrollers)
}
fn pack_informations() -> Result<Vec<PackInfo>, io::Error> {
let path = Path::new(CRATE_ROOT).join("packs");
pack_informations_from(&path)
}
fn pack_informations_from(path: &Path) -> Result<Vec<PackInfo>, io::Error> {
let mut pack_paths = Vec::new();
for pack_name in PACK_COLLECTIONS {
pack_paths.extend(find_packs(&path.join(pack_name)).unwrap());
}
Ok(pack_paths.into_iter().map(|path| PackInfo {
mcu_name: path.file_stem().unwrap().to_str().unwrap().to_lowercase().to_owned(),
path: path.to_owned(),
}).collect())
}
fn find_packs(in_dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
let mut paths = Vec::new();
for entry in fs::read_dir(in_dir)? {
let entry = entry?;
if let Some(PACK_FILE_EXT) = entry.path().extension().map(|s| s.to_str().unwrap()) {
paths.push(entry.path());
}
}
Ok(paths)
}
#[cfg(test)]
mod test {
#[test]
fn there_are_at_least_100_microcontrollers() {
let mcus = super::microcontrollers();
assert!(mcus.len() > 100, "there should be at least 100 microcontrollers");
}
#[test]
fn can_get_atmega328p_by_name() {
let mcu = super::microcontroller("atmega328p");
assert_eq!("ATmega328P", mcu.device.name);
}
}