diff options
| author | Côme ALLART <[email protected]> | 2021-09-05 20:03:52 +0200 |
|---|---|---|
| committer | Côme ALLART <[email protected]> | 2021-09-05 20:19:13 +0200 |
| commit | addee8778df6fb185a0a23658eef215ff2415d6e (patch) | |
| tree | 41db62dd8951dade2f09ff831b0c1952c41b1e76 /stm32-gen-features/src | |
| parent | 022b8092485c39cd68ad4e259ced5253b8a59460 (diff) | |
refactor(gen-features): use Rust instead of Python
Added support for /stm32-metapac
Diffstat (limited to 'stm32-gen-features/src')
| -rw-r--r-- | stm32-gen-features/src/lib.rs | 143 | ||||
| -rw-r--r-- | stm32-gen-features/src/main.rs | 16 |
2 files changed, 107 insertions, 52 deletions
diff --git a/stm32-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs index b20a1ba4a..683d0d4ed 100644 --- a/stm32-gen-features/src/lib.rs +++ b/stm32-gen-features/src/lib.rs | |||
| @@ -1,17 +1,16 @@ | |||
| 1 | use std::{ | 1 | //! FIXME discuss about which errors to print and when to panic |
| 2 | collections::HashMap, | 2 | |
| 3 | path::{Path, PathBuf}, | 3 | use std::{collections::HashMap, iter::FilterMap, path::Path, slice::Iter}; |
| 4 | }; | ||
| 5 | 4 | ||
| 6 | const SUPPORTED_FAMILIES: [&str; 8] = [ | 5 | const SUPPORTED_FAMILIES: [&str; 8] = [ |
| 7 | "STM32F0", | 6 | "stm32f0", |
| 8 | "STM32F4", | 7 | "stm32f4", |
| 9 | "STM32G0", | 8 | "stm32g0", |
| 10 | "STM32L0", | 9 | "stm32l0", |
| 11 | "STM32L4", | 10 | "stm32l4", |
| 12 | "STM32H7", | 11 | "stm32h7", |
| 13 | "STM32WB55", | 12 | "stm32wb55", |
| 14 | "STM32WL55", | 13 | "stm32wl55", |
| 15 | ]; | 14 | ]; |
| 16 | 15 | ||
| 17 | const SEPARATOR_START: &str = "# BEGIN GENERATED FEATURES\n"; | 16 | const SEPARATOR_START: &str = "# BEGIN GENERATED FEATURES\n"; |
| @@ -25,25 +24,36 @@ fn is_supported(name: &str) -> bool { | |||
| 25 | .any(|family| name.starts_with(family)) | 24 | .any(|family| name.starts_with(family)) |
| 26 | } | 25 | } |
| 27 | 26 | ||
| 28 | /// Get the yaml file names and the associated chip names for supported chips | 27 | type SupportedIter<'a> = FilterMap< |
| 28 | Iter<'a, (String, Vec<String>)>, | ||
| 29 | fn(&(String, Vec<String>)) -> Option<(&String, &Vec<String>)>, | ||
| 30 | >; | ||
| 31 | trait FilterSupported { | ||
| 32 | fn supported(&self) -> SupportedIter; | ||
| 33 | } | ||
| 34 | impl FilterSupported for &[(String, Vec<String>)] { | ||
| 35 | /// Get a new Vec with only the supported chips | ||
| 36 | fn supported(&self) -> SupportedIter { | ||
| 37 | self.iter() | ||
| 38 | .filter_map(|(name, cores)| is_supported(name).then(|| (name, cores))) | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | /// Get the list of all the chips and their supported cores | ||
| 29 | /// | 43 | /// |
| 30 | /// Print errors to `stderr` when something is returned by the glob but is not in the returned | 44 | /// Print errors to `stderr` when something is returned by the glob but is not in the returned |
| 31 | /// [`Vec`] | 45 | /// [`Vec`] |
| 32 | fn supported_chip_yaml_files_with_names() -> Vec<(PathBuf, String)> { | 46 | /// |
| 47 | /// This function is slow because all the yaml files are parsed. | ||
| 48 | pub fn chip_names_and_cores() -> Vec<(String, Vec<String>)> { | ||
| 33 | glob::glob("../stm32-data/data/chips/*.yaml") | 49 | glob::glob("../stm32-data/data/chips/*.yaml") |
| 34 | .expect("bad glob pattern") | 50 | .unwrap() |
| 35 | .filter_map(|entry| entry.map_err(|e| eprintln!("{:?}", e)).ok()) | 51 | .filter_map(|entry| entry.map_err(|e| eprintln!("{:?}", e)).ok()) |
| 36 | .filter_map(|entry| { | 52 | .filter_map(|entry| { |
| 37 | if let Some(name) = entry.file_stem().and_then(|stem| stem.to_str()) { | 53 | if let Some(name) = entry.file_stem().and_then(|stem| stem.to_str()) { |
| 38 | if is_supported(name) { | 54 | Some((name.to_lowercase(), chip_cores(&entry))) |
| 39 | let owned_name = name.to_lowercase(); | ||
| 40 | Some((entry, owned_name)) | ||
| 41 | } else { | ||
| 42 | eprintln!("{} is not supported", name); | ||
| 43 | None | ||
| 44 | } | ||
| 45 | } else { | 55 | } else { |
| 46 | eprintln!("{:?} is not a regural file", entry); | 56 | eprintln!("{:?} is not a regular file", entry); |
| 47 | None | 57 | None |
| 48 | } | 58 | } |
| 49 | }) | 59 | }) |
| @@ -53,36 +63,71 @@ fn supported_chip_yaml_files_with_names() -> Vec<(PathBuf, String)> { | |||
| 53 | /// Get the list of the cores of a chip by its associated file | 63 | /// Get the list of the cores of a chip by its associated file |
| 54 | /// | 64 | /// |
| 55 | /// # Panic | 65 | /// # Panic |
| 56 | /// Panics if the file does not exist or if it contains yaml syntax errors | 66 | /// Panics if the file does not exist or if it contains yaml syntax errors. |
| 57 | /// | 67 | /// Panics if "cores" is not an array. |
| 58 | /// # None | 68 | fn chip_cores(path: &Path) -> Vec<String> { |
| 59 | /// Returns none if "cores" is not an array | ||
| 60 | fn chip_cores(path: &Path) -> Option<Vec<yaml_rust::Yaml>> { | ||
| 61 | let file_contents = std::fs::read_to_string(path).unwrap(); | 69 | let file_contents = std::fs::read_to_string(path).unwrap(); |
| 62 | let doc = &yaml_rust::YamlLoader::load_from_str(&file_contents).unwrap()[0]; | 70 | let doc = &yaml_rust::YamlLoader::load_from_str(&file_contents).unwrap()[0]; |
| 63 | doc["cores"].as_vec().cloned() | 71 | doc["cores"] |
| 72 | .as_vec() | ||
| 73 | .unwrap_or_else(|| panic!("{:?}:[cores] is not an array", path)) | ||
| 74 | .iter() | ||
| 75 | .enumerate() | ||
| 76 | .map(|(i, core)| { | ||
| 77 | core["name"] | ||
| 78 | .as_str() | ||
| 79 | .unwrap_or_else(|| panic!("{:?}:[cores][{}][name] is not a string", path, i)) | ||
| 80 | .to_owned() | ||
| 81 | }) | ||
| 82 | .collect() | ||
| 64 | } | 83 | } |
| 65 | 84 | ||
| 66 | /// Load the list of chips | 85 | /// Generate data needed in `../embassy-stm32/Cargo.toml` |
| 86 | /// | ||
| 87 | /// Print errors to `stderr` when something is returned by the glob but is not in the returned | ||
| 88 | /// [`Vec`] | ||
| 67 | /// | 89 | /// |
| 68 | /// # Panic | 90 | /// # Panic |
| 69 | /// Panics if a file contains yaml syntax errors or if a value does not have a consistent type | 91 | /// Panics if a file contains yaml syntax errors or if a value does not have a consistent type |
| 70 | pub fn load_chip_list() -> HashMap<String, Vec<String>> { | 92 | pub fn embassy_stm32_needed_data( |
| 93 | names_and_cores: &[(String, Vec<String>)], | ||
| 94 | ) -> HashMap<String, Vec<String>> { | ||
| 71 | let mut result = HashMap::new(); | 95 | let mut result = HashMap::new(); |
| 72 | for (path, name) in supported_chip_yaml_files_with_names() { | 96 | for (chip_name, cores) in names_and_cores.supported() { |
| 73 | let cores = chip_cores(&path).unwrap_or_else(|| panic!("{}[cores] is not an array", name)); | ||
| 74 | if cores.len() > 1 { | 97 | if cores.len() > 1 { |
| 75 | for (i, core) in cores.into_iter().enumerate() { | 98 | for core_name in cores.iter() { |
| 76 | let core_name = core["name"] | 99 | let key = format!("{}_{}", chip_name, core_name); |
| 77 | .as_str() | 100 | let value = vec![format!("stm32-metapac/{}_{}", chip_name, core_name)]; |
| 78 | .unwrap_or_else(|| panic!("{}[cores][{}][name] is not a string", name, i)); | ||
| 79 | let key = format!("{}_{}", name, core_name); | ||
| 80 | let value = vec![format!("stm32-metapac/{}_{}", name, core_name)]; | ||
| 81 | result.insert(key, value); | 101 | result.insert(key, value); |
| 82 | } | 102 | } |
| 83 | } else { | 103 | } else { |
| 84 | let value = vec![format!("stm32-metapac/{}", &name)]; | 104 | let key = chip_name.to_string(); |
| 85 | result.insert(name, value); | 105 | let value = vec![format!("stm32-metapac/{}", chip_name)]; |
| 106 | result.insert(key, value); | ||
| 107 | } | ||
| 108 | } | ||
| 109 | result | ||
| 110 | } | ||
| 111 | |||
| 112 | /// Generate data needed in `../stm32-metapac/Cargo.toml` | ||
| 113 | /// | ||
| 114 | /// Print errors to `stderr` when something is returned by the glob but is not in the returned | ||
| 115 | /// [`Vec`] | ||
| 116 | /// | ||
| 117 | /// # Panic | ||
| 118 | /// Panics if a file contains yaml syntax errors or if a value does not have a consistent type | ||
| 119 | pub fn stm32_metapac_needed_data( | ||
| 120 | names_and_cores: &[(String, Vec<String>)], | ||
| 121 | ) -> HashMap<String, Vec<String>> { | ||
| 122 | let mut result = HashMap::new(); | ||
| 123 | for (chip_name, cores) in names_and_cores { | ||
| 124 | if cores.len() > 1 { | ||
| 125 | for core_name in cores { | ||
| 126 | let key = format!("{}_{}", chip_name, core_name); | ||
| 127 | result.insert(key, vec![]); | ||
| 128 | } | ||
| 129 | } else { | ||
| 130 | result.insert(chip_name.clone(), vec![]); | ||
| 86 | } | 131 | } |
| 87 | } | 132 | } |
| 88 | result | 133 | result |
| @@ -122,22 +167,22 @@ mod tests { | |||
| 122 | 167 | ||
| 123 | #[test] | 168 | #[test] |
| 124 | fn stm32f407vg_is_supported() { | 169 | fn stm32f407vg_is_supported() { |
| 125 | assert!(is_supported("STM32F407VG")) | 170 | assert!(is_supported("stm32f407vg")) |
| 126 | } | 171 | } |
| 127 | 172 | ||
| 128 | #[test] | 173 | #[test] |
| 129 | fn abcdef_is_not_supported() { | 174 | fn abcdef_is_not_supported() { |
| 130 | assert!(!is_supported("ABCDEF")) | 175 | assert!(!is_supported("abcdef")) |
| 131 | } | 176 | } |
| 132 | 177 | ||
| 133 | #[test] | 178 | #[test] |
| 134 | fn stm32f407vg_yaml_file_exists() { | 179 | #[ignore] |
| 135 | assert!(supported_chip_yaml_files_with_names() | 180 | fn stm32f407vg_yaml_file_exists_and_is_supported() { |
| 181 | assert!(chip_names_and_cores() | ||
| 182 | .as_slice() | ||
| 183 | .supported() | ||
| 136 | .into_iter() | 184 | .into_iter() |
| 137 | .any(|(path, name)| { | 185 | .any(|(name, _)| { name == "stm32f407vg" })) |
| 138 | name == "stm32f407vg" | ||
| 139 | && path.to_str() == Some("../stm32-data/data/chips/STM32F407VG.yaml") | ||
| 140 | })) | ||
| 141 | } | 186 | } |
| 142 | 187 | ||
| 143 | #[test] | 188 | #[test] |
diff --git a/stm32-gen-features/src/main.rs b/stm32-gen-features/src/main.rs index 9f1d8ef34..9edae4463 100644 --- a/stm32-gen-features/src/main.rs +++ b/stm32-gen-features/src/main.rs | |||
| @@ -1,10 +1,20 @@ | |||
| 1 | use std::collections::HashMap; | 1 | use std::collections::HashMap; |
| 2 | 2 | ||
| 3 | use gen_features::{generate_cargo_toml_file, load_chip_list}; | 3 | use gen_features::{ |
| 4 | chip_names_and_cores, embassy_stm32_needed_data, generate_cargo_toml_file, | ||
| 5 | stm32_metapac_needed_data, | ||
| 6 | }; | ||
| 4 | 7 | ||
| 5 | fn main() { | 8 | fn main() { |
| 6 | let chip_list = load_chip_list(); | 9 | let names_and_cores = chip_names_and_cores(); |
| 7 | update_cargo_file("../embassy-stm32/Cargo.toml", &chip_list); | 10 | update_cargo_file( |
| 11 | "../embassy-stm32/Cargo.toml", | ||
| 12 | &embassy_stm32_needed_data(&names_and_cores), | ||
| 13 | ); | ||
| 14 | update_cargo_file( | ||
| 15 | "../stm32-metapac/Cargo.toml", | ||
| 16 | &stm32_metapac_needed_data(&names_and_cores), | ||
| 17 | ); | ||
| 8 | } | 18 | } |
| 9 | 19 | ||
| 10 | /// Update a Cargo.toml file | 20 | /// Update a Cargo.toml file |
