1use model::Mcu;
2use pack;
3
4use std::path::{Path, PathBuf};
5use std::{fs, io};
6
7const PACK_FILE_EXT: &str = "atdf";
9
10const PACK_COLLECTIONS: &[&str] =
13 &["atmega", "tiny", "xmegaa", "xmegab", "xmegac", "xmegad", "xmegae", "automotive"];
14
15const CRATE_ROOT: &str = env!("CARGO_MANIFEST_DIR");
17
18lazy_static! {
19 static ref MCUS: Vec<Mcu> =
20 self::load_microcontrollers().expect("failed to load microcontrollers");
21 static ref MCU_NAMES: Vec<String> = pack_informations()
22 .expect("could not find packfiles")
23 .into_iter()
24 .map(|pack| pack.mcu_name)
25 .collect();
26}
27
28struct PackInfo {
29 pub mcu_name: String,
30 pub path: PathBuf,
31}
32
33pub fn microcontrollers() -> &'static [Mcu] {
35 &MCUS[..]
36}
37
38pub fn microcontroller_names() -> &'static [String] {
45 &MCU_NAMES[..]
46}
47
48pub fn microcontroller(name: &str) -> Mcu {
50 let pack_info = pack_informations()
51 .unwrap()
52 .into_iter()
53 .find(|pack_info| pack_info.mcu_name == name)
54 .expect(&format!("no microcontroller with the name '{}' found", name));
55 pack::load(&pack_info.path).expect("could not parse microcontroller pack")
56}
57
58fn load_microcontrollers() -> Result<Vec<Mcu>, io::Error> {
60 let microcontrollers = pack_informations()?
61 .into_iter()
62 .map(|pack_info| pack::load(&pack_info.path).unwrap())
63 .collect();
64
65 Ok(microcontrollers)
66}
67
68fn pack_informations() -> Result<Vec<PackInfo>, io::Error> {
69 let path = Path::new(CRATE_ROOT).join("packs");
70 pack_informations_from(&path)
71}
72
73fn pack_informations_from(path: &Path) -> Result<Vec<PackInfo>, io::Error> {
74 let mut pack_paths = Vec::new();
75
76 for pack_name in PACK_COLLECTIONS {
77 pack_paths.extend(find_packs(&path.join(pack_name)).unwrap());
78 }
79
80 Ok(pack_paths
81 .into_iter()
82 .map(|path| PackInfo {
83 mcu_name: path.file_stem().unwrap().to_str().unwrap().to_lowercase().to_owned(),
84 path: path.to_owned(),
85 })
86 .collect())
87}
88
89fn find_packs(in_dir: &Path) -> Result<Vec<PathBuf>, io::Error> {
91 let mut paths = Vec::new();
92
93 for entry in fs::read_dir(in_dir)? {
94 let entry = entry?;
95 if let Some(PACK_FILE_EXT) = entry.path().extension().map(|s| s.to_str().unwrap()) {
96 paths.push(entry.path());
97 }
98 }
99 Ok(paths)
100}
101
102#[cfg(test)]
103mod test {
104 #[test]
105 fn there_are_at_least_100_microcontrollers() {
106 let mcus = super::microcontrollers();
107 assert!(mcus.len() > 100, "there should be at least 100 microcontrollers");
108 }
109
110 #[test]
111 fn can_get_atmega328p_by_name() {
112 let mcu = super::microcontroller("atmega328p");
113 assert_eq!("ATmega328P", mcu.device.name);
114 }
115}