avr_mcu/
load.rs

1use model::Mcu;
2use pack;
3
4use std::path::{Path, PathBuf};
5use std::{fs, io};
6
7/// The extension on the pack files.
8const PACK_FILE_EXT: &str = "atdf";
9
10/// All pack collections inside the 'packs' folder
11/// of this repository.
12const PACK_COLLECTIONS: &[&str] =
13    &["atmega", "tiny", "xmegaa", "xmegab", "xmegac", "xmegad", "xmegae", "automotive"];
14
15/// The on-disk path of the crate root.
16const 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
33/// Retrieves a list of `Mcu` objects for all microcontrollers.
34pub fn microcontrollers() -> &'static [Mcu] {
35    &MCUS[..]
36}
37
38/// Retrieves a list of all microcontroller names.
39///
40/// # Examples
41///
42/// * `atmega328p`
43/// * `attiny85`
44pub fn microcontroller_names() -> &'static [String] {
45    &MCU_NAMES[..]
46}
47
48/// Retrieves information for a specific microcontroller.
49pub 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
58/// Retrieves a list of `Mcu` objects in a directory containg `PACK_COLLECTIONS`.
59fn 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
89/// Finds all pack files in a directory.
90fn 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}