Rust宏生成枚举时如何配置默认#[repr]属性
Rust宏实现可选#[repr(type)]属性(默认#[repr(u8)])
你尝试的#[repr(if $repr { $repr } else { u8 })]写法无效,因为Rust属性不支持这种内联条件语法,必须通过宏的模式匹配来处理可选的repr属性。以下是两种可行的解决方法:
方法一:多分支宏匹配
直接定义两个宏分支,分别处理带#[repr($repr:ty)]和不带该属性的情况,逻辑清晰直观:
macro_rules! my_enum { // 分支1:匹配带有#[repr]属性的枚举 ( #[derive($($path:path),+)] #[repr($repr:ty)] $(#[$attr:meta])* $vis:vis enum $Name:ident { $( $(#[$field_attr:meta])* $variant:ident = $index:tt, )* } ) => { $crate::macros::paste::paste! { #[derive(Debug, Clone, Copy, $crate::Serialize_repr, $crate::Deserialize_repr, enum_sql::IntEnumFromSql, enum_sql::IntEnumToSql, $($path),*)] $(#[$attr])* #[serde(try_from="i16", into="i16")] #[repr($repr)] $vis enum $Name { $( $(#[$field_attr])* $variant = $index, )* } } }; // 分支2:匹配不带#[repr]属性的枚举,默认使用#[repr(u8)] ( #[derive($($path:path),+)] $(#[$attr:meta])* $vis:vis enum $Name:ident { $( $(#[$field_attr:meta])* $variant:ident = $index:tt, )* } ) => { $crate::macros::paste::paste! { #[derive(Debug, Clone, Copy, $crate::Serialize_repr, $crate::Deserialize_repr, enum_sql::IntEnumFromSql, enum_sql::IntEnumToSql, $($path),*)] $(#[$attr])* #[serde(try_from="i16", into="i16")] #[repr(u8)] $vis enum $Name { $( $(#[$field_attr])* $variant = $index, )* } } }; }
方法二:可选捕获+条件展开
利用Rust 1.56+支持的?可选模式捕获#[repr]属性,通过宏重复语法生成对应属性:
macro_rules! my_enum { ( #[derive($($path:path),+)] $(#[repr($repr:ty)])? $(#[$attr:meta])* $vis:vis enum $Name:ident { $( $(#[$field_attr:meta])* $variant:ident = $index:tt, )* } ) => { $crate::macros::paste::paste! { #[derive(Debug, Clone, Copy, $crate::Serialize_repr, $crate::Deserialize_repr, enum_sql::IntEnumFromSql, enum_sql::IntEnumToSql, $($path),*)] $(#[$attr])* #[serde(try_from="i16", into="i16")] // 捕获到$repr则生成指定属性,否则生成默认的#[repr(u8)] $(#[repr($repr)])? $($(#[repr(u8)])?)? $vis enum $Name { $( $(#[$field_attr])* $variant = $index, )* } } }; }
使用示例
// 不带#[repr],默认使用#[repr(u8)] my_enum! { #[derive(PartialEq, Eq)] pub enum DefaultEnum { OptionA = 0, OptionB = 1, } } // 指定#[repr(u16)] my_enum! { #[derive(PartialEq, Eq)] #[repr(u16)] pub enum CustomEnum { ValueX = 0, ValueY = 1, } }
内容的提问来源于stack exchange,提问作者江 河
相关产品推荐
相关产品推荐

