1use std::collections::HashMap;
2use std::convert::TryFrom;
3
4use anyhow::{anyhow, bail};
5
6pub fn parse_optional_param<'a, T>(
7 parameters: &'a HashMap<&str, &str>,
8 param_name: &str,
9) -> anyhow::Result<Option<T>, anyhow::Error>
10where
11 T: TryFrom<&'a str, Error = anyhow::Error>,
12{
13 parameters
14 .get(param_name)
15 .map(|s| T::try_from(*s))
16 .transpose()
17}
18
19pub fn parse_mandatory_param<'a, T>(
20 parameters: &'a HashMap<&str, &str>,
21 param_name: &str,
22) -> anyhow::Result<T, anyhow::Error>
23where
24 T: TryFrom<&'a str, Error = anyhow::Error>,
25{
26 let ¶m = parameters
27 .get(param_name)
28 .ok_or_else(|| anyhow!("{} parameter required", param_name))?;
29 T::try_from(param)
30}
31
32pub fn parse_mandatory_u32(
33 parameters: &HashMap<&str, &str>,
34 param_name: &str,
35) -> anyhow::Result<u32> {
36 Ok(parameters
37 .get(param_name)
38 .ok_or_else(|| anyhow!(f!("{param_name} parameter not found")))?
39 .parse()
40 .map_err(|_| anyhow!(f!("{param_name} parameter invalid integer")))?)
41}
42
43pub fn parse_optional_u32(
44 parameters: &HashMap<&str, &str>,
45 param_name: &str,
46) -> anyhow::Result<Option<u32>> {
47 parameters
48 .get(param_name)
49 .map(|s| {
50 s.parse()
51 .map_err(|_| anyhow!(f!("{param_name} parameter invalid integer")))
52 })
53 .transpose()
54}
55
56macro_rules! parameter {
59 ($enumname:ident, [$($variant: ident), *]) => {
60 #[allow(non_camel_case_types)]
61 #[derive(Debug, Copy, Clone, PartialEq)]
62 pub enum $enumname {
63 $(
64 $variant,
65 )*
66 }
67
68 impl std::convert::TryFrom<&str> for $enumname {
69 type Error = anyhow::Error;
70
71 fn try_from(text: &str) -> anyhow::Result<Self, Self::Error> {
72 match text {
73 $(
74 stringify!($variant) => Ok($enumname::$variant),
75 )*
76 _ => bail!(concat!("invalid ", stringify!($enumname), " {}"), text),
77 }
78 }
79 }
80 };
81 ($enumname:ident, [$($variant: ident), *], default=$default_variant: ident) => {
82 parameter!($enumname, [$($variant), *]);
83 impl Default for $enumname {
84 fn default() -> Self {
85 $enumname::$default_variant
86 }
87 }
88 };
89}
90
91parameter!(
92 MCUFamily,
93 [
94 STM32F0, STM32F1, STM32F2, STM32F3, STM32F4, STM32F7, STM32G0, STM32G4, STM32H7, STM32L0,
95 STM32L1, STM32L4, STM32L5, STM32MP1, STM32WB, STM32WL
96 ]
97);
98
99pub struct GeneratedString {
100 pub string: String,
101 indent: usize,
102}
103
104impl GeneratedString {
105 pub fn new() -> Self {
106 GeneratedString {
107 string: String::new(),
108 indent: 0,
109 }
110 }
111
112 pub fn line<T: AsRef<str>>(&mut self, line: T) {
113 let indent = " ".repeat(self.indent);
114 let content = line.as_ref();
115 self.string.push_str(&f!("{indent}{content}\n"));
116 }
117
118 pub fn empty_line(&mut self) {
119 self.string.push_str("\n");
120 }
121
122 pub fn indent_right(&mut self) {
123 self.indent += 4;
124 }
125
126 pub fn indent_left(&mut self) {
127 self.indent = self.indent.saturating_sub(4);
128 }
129}