170 lines
5.1 KiB
Rust
170 lines
5.1 KiB
Rust
//! FIXME discuss about which errors to print and when to panic
|
|
|
|
use std::path::Path;
|
|
|
|
const SEPARATOR_START: &str = "# BEGIN GENERATED FEATURES\n";
|
|
const SEPARATOR_END: &str = "# END GENERATED FEATURES\n";
|
|
const HELP: &str = "# Generated by stm32-gen-features. DO NOT EDIT.\n";
|
|
|
|
/// Get the list of all the chips and their supported cores
|
|
///
|
|
/// Print errors to `stderr` when something is returned by the glob but is not in the returned
|
|
/// [`Vec`]
|
|
///
|
|
/// This function is slow because all the yaml files are parsed.
|
|
pub fn chip_names_and_cores() -> Vec<(String, Vec<String>)> {
|
|
glob::glob("../stm32-data/data/chips/*.json")
|
|
.unwrap()
|
|
.filter_map(|entry| entry.map_err(|e| eprintln!("{:?}", e)).ok())
|
|
.filter_map(|entry| {
|
|
if let Some(name) = entry.file_stem().and_then(|stem| stem.to_str()) {
|
|
Some((name.to_lowercase(), chip_cores(&entry)))
|
|
} else {
|
|
eprintln!("{:?} is not a regular file", entry);
|
|
None
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
/// Get the list of the cores of a chip by its associated file
|
|
///
|
|
/// # Panic
|
|
/// Panics if the file does not exist or if it contains yaml syntax errors.
|
|
/// Panics if "cores" is not an array.
|
|
fn chip_cores(path: &Path) -> Vec<String> {
|
|
let file_contents = std::fs::read_to_string(path).unwrap();
|
|
let doc = &yaml_rust::YamlLoader::load_from_str(&file_contents).unwrap()[0];
|
|
doc["cores"]
|
|
.as_vec()
|
|
.unwrap_or_else(|| panic!("{:?}:[cores] is not an array", path))
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(i, core)| {
|
|
core["name"]
|
|
.as_str()
|
|
.unwrap_or_else(|| panic!("{:?}:[cores][{}][name] is not a string", path, i))
|
|
.to_owned()
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
/// Generate data needed in `../embassy-stm32/Cargo.toml`
|
|
///
|
|
/// Print errors to `stderr` when something is returned by the glob but is not in the returned
|
|
/// [`Vec`]
|
|
///
|
|
/// # Panic
|
|
/// Panics if a file contains yaml syntax errors or if a value does not have a consistent type
|
|
pub fn embassy_stm32_needed_data(names_and_cores: &[(String, Vec<String>)]) -> String {
|
|
let mut result = String::new();
|
|
for (chip_name, cores) in names_and_cores {
|
|
if cores.len() > 1 {
|
|
for core_name in cores.iter() {
|
|
result += &format!(
|
|
"{chip}-{core} = [ \"stm32-metapac/{chip}-{core}\" ]\n",
|
|
chip = chip_name,
|
|
core = core_name
|
|
);
|
|
}
|
|
} else {
|
|
result += &format!("{chip} = [ \"stm32-metapac/{chip}\" ]\n", chip = chip_name);
|
|
}
|
|
}
|
|
result
|
|
}
|
|
|
|
/// Generate data needed in `../stm32-metapac/Cargo.toml`
|
|
///
|
|
/// Print errors to `stderr` when something is returned by the glob but is not in the returned
|
|
/// [`Vec`]
|
|
///
|
|
/// # Panic
|
|
/// Panics if a file contains yaml syntax errors or if a value does not have a consistent type
|
|
pub fn stm32_metapac_needed_data(names_and_cores: &[(String, Vec<String>)]) -> String {
|
|
let mut result = String::new();
|
|
for (chip_name, cores) in names_and_cores {
|
|
if cores.len() > 1 {
|
|
for core_name in cores {
|
|
result += &format!("{}-{} = []\n", chip_name, core_name);
|
|
}
|
|
} else {
|
|
result += &format!("{} = []\n", chip_name);
|
|
}
|
|
}
|
|
result
|
|
}
|
|
|
|
/// Get contents before and after generated contents
|
|
///
|
|
/// # Panic
|
|
/// Panics when a separator cound not be not found
|
|
fn split_cargo_toml_contents(contents: &str) -> (&str, &str) {
|
|
let (before, remainder) = contents
|
|
.split_once(SEPARATOR_START)
|
|
.unwrap_or_else(|| panic!("missing \"{}\" tag", SEPARATOR_START));
|
|
let (_, after) = remainder
|
|
.split_once(SEPARATOR_END)
|
|
.unwrap_or_else(|| panic!("missing \"{}\" tag", SEPARATOR_END));
|
|
|
|
(before, after)
|
|
}
|
|
|
|
/// Generates new contents for Cargo.toml
|
|
///
|
|
/// # Panic
|
|
/// Panics when a separator cound not be not found
|
|
pub fn generate_cargo_toml_file(previous_text: &str, new_contents: &str) -> String {
|
|
let (before, after) = split_cargo_toml_contents(previous_text);
|
|
before.to_owned() + SEPARATOR_START + HELP + new_contents + SEPARATOR_END + after
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn stm32f407vg_yaml_file_exists() {
|
|
assert!(chip_names_and_cores()
|
|
.as_slice()
|
|
.into_iter()
|
|
.any(|(name, _)| { name == "stm32f407vg" }))
|
|
}
|
|
|
|
#[test]
|
|
fn keeps_text_around_separators() {
|
|
let initial = "\
|
|
before
|
|
# BEGIN GENERATED FEATURES
|
|
# END GENERATED FEATURES
|
|
after
|
|
";
|
|
|
|
let expected = "\
|
|
before
|
|
# BEGIN GENERATED FEATURES
|
|
# Generated by stm32-gen-features. DO NOT EDIT.
|
|
a = [\"b\"]
|
|
# END GENERATED FEATURES
|
|
after
|
|
";
|
|
|
|
let new_contents = String::from("a = [\"b\"]\n");
|
|
assert_eq!(generate_cargo_toml_file(initial, &new_contents), expected);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn does_not_generate_if_separators_are_missing() {
|
|
let initial = "\
|
|
before
|
|
# END GENERATED FEATURES
|
|
after
|
|
";
|
|
|
|
let new_contents = String::from("a = [\"b\"]\n");
|
|
generate_cargo_toml_file(initial, &new_contents);
|
|
}
|
|
}
|