use std::collections::HashMap;
use std::convert::TryFrom;
use anyhow::{anyhow, bail};
pub fn parse_optional_param<'a, T>(
parameters: &'a HashMap<&str, &str>,
param_name: &str,
) -> anyhow::Result<Option<T>, anyhow::Error>
where
T: TryFrom<&'a str, Error = anyhow::Error>,
{
parameters
.get(param_name)
.map(|s| T::try_from(*s))
.transpose()
}
pub fn parse_mandatory_param<'a, T>(
parameters: &'a HashMap<&str, &str>,
param_name: &str,
) -> anyhow::Result<T, anyhow::Error>
where
T: TryFrom<&'a str, Error = anyhow::Error>,
{
let ¶m = parameters
.get(param_name)
.ok_or_else(|| anyhow!("{} parameter required", param_name))?;
T::try_from(param)
}
pub fn parse_mandatory_u32(
parameters: &HashMap<&str, &str>,
param_name: &str,
) -> anyhow::Result<u32> {
Ok(parameters
.get(param_name)
.ok_or_else(|| anyhow!(f!("{param_name} parameter not found")))?
.parse()
.map_err(|_| anyhow!(f!("{param_name} parameter invalid integer")))?)
}
pub fn parse_optional_u32(
parameters: &HashMap<&str, &str>,
param_name: &str,
) -> anyhow::Result<Option<u32>> {
parameters
.get(param_name)
.map(|s| {
s.parse()
.map_err(|_| anyhow!(f!("{param_name} parameter invalid integer")))
})
.transpose()
}
macro_rules! parameter {
($enumname:ident, [$($variant: ident), *]) => {
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum $enumname {
$(
$variant,
)*
}
impl std::convert::TryFrom<&str> for $enumname {
type Error = anyhow::Error;
fn try_from(text: &str) -> anyhow::Result<Self, Self::Error> {
match text {
$(
stringify!($variant) => Ok($enumname::$variant),
)*
_ => bail!(concat!("invalid ", stringify!($enumname), " {}"), text),
}
}
}
};
($enumname:ident, [$($variant: ident), *], default=$default_variant: ident) => {
parameter!($enumname, [$($variant), *]);
impl Default for $enumname {
fn default() -> Self {
$enumname::$default_variant
}
}
};
}
parameter!(
MCUFamily,
[
STM32F0, STM32F1, STM32F2, STM32F3, STM32F4, STM32F7, STM32G0, STM32G4, STM32H7, STM32L0,
STM32L1, STM32L4, STM32L5, STM32MP1, STM32WB, STM32WL
]
);
pub struct GeneratedString {
pub string: String,
indent: usize,
}
impl GeneratedString {
pub fn new() -> Self {
GeneratedString {
string: String::new(),
indent: 0,
}
}
pub fn line<T: AsRef<str>>(&mut self, line: T) {
let indent = " ".repeat(self.indent);
let content = line.as_ref();
self.string.push_str(&f!("{indent}{content}\n"));
}
pub fn empty_line(&mut self) {
self.string.push_str("\n");
}
pub fn indent_right(&mut self) {
self.indent += 4;
}
pub fn indent_left(&mut self) {
self.indent = self.indent.saturating_sub(4);
}
}