use indexmap::IndexMap;
use std::fmt::Formatter;
type FnvIndexMap<K, V> = IndexMap<K, V, fnv::FnvBuildHasher>;
pub struct TestCases<'node> {
map: FnvIndexMap<&'node syn::Ident, Vec<&'node syn::Expr>>,
amount_of_test_cases: Option<usize>,
}
impl std::fmt::Debug for TestCases<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let ids = self
.map
.iter()
.map(|(id, _)| format!("{}", id))
.collect::<Vec<String>>();
let joined = ids.join(", ");
f.write_str(&format!("TestCases {{ identifiers = {} }}", joined))
}
}
impl<'node> TestCases<'node> {
pub fn empty() -> Self {
Self {
map: IndexMap::default(),
amount_of_test_cases: None,
}
}
pub fn insert(&mut self, id: &'node syn::Ident, exprs: Vec<&'node syn::Expr>) {
let expressions = exprs.len();
match self.amount_of_test_cases {
Some(amount) if amount != expressions => panic!(
"parameterized-macro error: Each test-case parameter should have an equal amount of values passed to it.\n\
Expected {} arguments for '{}', but got: {}", amount, id, expressions,
),
Some(_) => {}
None => {
self.amount_of_test_cases = Some(expressions)
},
};
if expressions != self.unwrap_amount_of_test_cases() {
panic!(
"parameterized-macro: error: Each test-case parameter should have an equal amount of values passed to it.\n\
Expected {} arguments for '{}', but got: {}", self.unwrap_amount_of_test_cases(), id, expressions,
);
}
if self.map.get(id).is_none() {
self.map.insert(id, exprs);
} else {
panic!(
"parameterized-macro: error: found duplicate entry for '{}'",
id
);
}
}
pub fn get(&self, id: &syn::Ident, ith: usize) -> &syn::Expr {
if let Some(exprs) = self.map.get(id) {
exprs[ith]
} else {
panic!(
"parameterized-macro: error: Unable to find value for parameter '{}' (case #{})",
id, ith
);
}
}
pub fn amount_of_test_cases(&self) -> Option<usize> {
self.amount_of_test_cases
}
fn unwrap_amount_of_test_cases(&self) -> usize {
if let Some(amount) = self.amount_of_test_cases {
amount
} else {
unreachable!()
}
}
}