strum
strum copied to clipboard
EnumString: have a const version
Hello,
I was wondering why there is no EnumStringConst proc-macro since it's used in a lot of cases when wanting to do compile-time validation on a string literral.
e.g
#[allow(non_camel_case_types)]
#[derive(
Debug,
Clone,
Copy,
serde::Serialize,
serde::Deserialize,
strum::Display,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
utoipa::ToSchema,
EnumString,
)]
pub enum Currency {
USD,
EUR,
}
impl Currency {
pub fn to_ascii_uppercase(&self) -> String {
format!("{}", self).to_ascii_uppercase()
}
const fn from_str_const(s: &str) -> Option<Self> {
// Manual matching since we can't iterate in const fn
match s.as_bytes() {
b"USD" => Some(Currency::USD),
b"EUR" => Some(Currency::EUR),
_ => None,
}
}
}
// Macro for compile-time validation
macro_rules! currency {
($s:literal) => {{
const _: () = {
if Currency::from_str_const($s).is_none() {
panic!(concat!("Invalid Currency: ", $s));
}
};
// Use the strum-generated FromStr at runtime
<Currency as std::str::FromStr>::from_str($s).unwrap()
}};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_valid_currency_creation() {
let currency = currency!("USD");
assert_eq!(currency, Currency::USD);
let currency = currency!("EUR");
assert_eq!(currency, Currency::EUR);
// let currency = currency!("BTC");
// assert_eq!(currency, Currency::BTC);
}
}
I figured out that the from_str_const could easily be automatically generated in a similar fashion as the from_str method.
Any objection or reason not to do that ?
Happy to contribute if necessary.