Introduce target_spec_enum macro to avoid duplication

With this macro we only need to enumerate every variant once. This saves
a lot of duplication already between the definition, the `FromStr` impl
and the `ToJson` impl.

It also enables us to do further things with it like JSON schema
generation.
This commit is contained in:
Noratrieb 2025-07-26 12:15:19 +02:00
parent a171994070
commit a0bb9cc57d
2 changed files with 248 additions and 719 deletions

View file

@ -72,3 +72,63 @@ fn find_relative_libdir(sysroot: &Path) -> std::borrow::Cow<'static, str> {
Some(libdir) => libdir.into(),
}
}
macro_rules! target_spec_enum {
(
$( #[$attr:meta] )*
pub enum $name:ident {
$(
$( #[$variant_attr:meta] )*
$variant:ident = $string:literal,
)*
}
parse_error_type = $parse_error_type:literal;
) => {
$( #[$attr] )*
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub enum $name {
$(
$( #[$variant_attr] )*
$variant,
)*
}
impl FromStr for $name {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
$( $string => Self::$variant, )*
_ => {
let all = [$( concat!("'", $string, "'") ),*].join(", ");
return Err(format!("invalid {}: '{s}'. allowed values: {all}", $parse_error_type));
}
})
}
}
impl $name {
pub fn desc(&self) -> &'static str {
match self {
$( Self::$variant => $string, )*
}
}
}
impl crate::json::ToJson for $name {
fn to_json(&self) -> crate::json::Json {
self.desc().to_json()
}
}
crate::json::serde_deserialize_from_str!($name);
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.desc())
}
}
};
}
use target_spec_enum;

File diff suppressed because it is too large Load diff