You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者江 河

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:32:04