【uom】 1 storage_types宏设计与实现(storage_types.rs)

一、宏系统概述

(一)、 核心功能

storage_types! 宏系统是一个高级代码生成工具,主要功能包括:

  • 多类型代码生成:为不同数值类型自动生成重复代码结构

  • 类型分类支持:内置 7 种类型分类

分类名 包含类型
All 所有支持的类型(基本整数、大数、有理数、复数、浮点数)
PrimInt 基本整数类型(usize, u8-i128)
Ratio 有理数类型(Rational, Rational32, Rational64, BigRational)
Float 浮点类型(f32, f64)
Signed 有符号类型(isize, i8-i128, BigInt, 有理数, 浮点数)
Unsigned 无符号类型(usize, u8-u128, BigUint)
Complex 复数类型(Complex32, Complex64)
  • 模块化组织:为每种类型生成独立模块

  • 条件编译:通过 feature 标志控制类型包含

(二)、设计优势
  • 减少重复代码:避免为每种类型手动编写相似代码

  • 统一接口:为不同数值类型提供一致的使用方式

  • 灵活扩展:易于添加新类型或类型分类

  • 编译优化:未启用的类型完全不生成代码

二、宏定义详解

(一)、文档与条件编译
#[cfg_attr(all(feature = "f32", feature = "f64"), doc = " ```rust")]
#[cfg_attr(not(all(feature = "f32", feature = "f64")), doc = " ```rust,ignore")]
  • 作用:根据 feature 组合控制文档示例的编译行为

  • 逻辑:

    • 同时启用 f32 和 f64:文档示例可编译

    • 否则:文档示例仅显示不编译

(二)、主宏结构(storage_types!)
#[macro_export]
macro_rules! storage_types {
   
    // 公开/非公开模块入口
    ($(#[$attr:meta])* types: $($T:ident),+; $($tt:tt)*) => {
    ... };
    ($(#[$attr:meta])* pub types: $($T:ident),+; $($tt:tt)*) => {
    ... };
    
    // 类型分发处理器
    (@types $attr:tt @$M:ident $($T:ident),+; $tt:tt) => {
    ... };
    
    // 具体类型处理器(示例)
    (@type ($(#[$attr:meta])*) @$M:ident usize ($($tt:tt)*)) => {
    ... };
    
    // 类型分类处理器(示例)
    (@type ($(#[$attr:meta])*) @$M:ident Float ($($tt:tt)*)) => {
    ... };
    
    // 模块生成器
    (@mod ($(#[$attr:meta])*) $M:ident, $V:ty; ($($tt:tt)*)) => {
    ... };
    (@pub_mod ($(#[$attr:meta])*) $M:ident, $V:ty; ($($tt:tt)*)) => {
    ... };
    
    // 默认处理
    ($($tt:tt)*) => {
    ... };
}
第一匹配项详解
($(#[$attr:meta])* types: $($T:ident),+; $($tt:tt)*) => {
   
        storage_types!(@types ($(#[$attr])*) @mod $($T),+; ($($tt)*));
    };
  1. 输入模式:
  • $(#[$attr:meta])*

    • 匹配零个或多个属性(attributes),如 #[derive(Debug)] 或 #[allow(dead_code)]。
    • 如果输入是 #[derive(Debug)] types: u32, f64; …,那么 KaTeX parse error: Expected 'EOF', got '#' at position 2: (#̲[attr])* 会捕获 #[derive(Debug)]。
  • types::字面匹配,必须是 types: 这个标识符

  • $($T:ident),+

    • 匹配一个或多个由逗号分隔的标识符(如 u32, f64 或 All)
    • 例如,u32、u32, f64 或 All 都是有效的。
  • ;:字面分号

  • $($tt:tt)*

    • 匹配任意数量的 token tree(即任意 Rust 代码)
    • 这部分内容会被原样传递到生成的模块中。
  1. 展开规则:
  • 调用宏自身的 @types 内部规则(宏的内部转发规则,用于进一步处理),并传递以下参数:
    • ($(#[$attr])*):捕获的属性

    • @mod:字面标记,表示生成的模块默认是私有的

      • 如果是 pub types: …,则会使用 @pub_mod 生成公开模块。
    • $($T),+:捕获的类型标识符

    • ($($tt)*):捕获的其余 token tree(作为额外的模块内容)

  1. 示例展开
    假设有以下宏调用:
storage_types! {
   
    #[derive(Debug, Clone)]
    types: u32, f64;
    
    const EXAMPLE: V = 42;
}

它会展开为:

storage_types!(@types (#[derive(Debug, Clone)]) @mod u32, f64; (
    const EXAMPLE: V = 42;
));

然后 @types 规则会进一步处理,为 u32 和 f64 分别生成模块,并将 const EXAMPLE: V = 42; 放入每个模块中。

  1. 总结
    这段规则的作用是:
  • 匹配带有可选属性、types: 关键字、类型列表和额外代码的输入。

  • 将输入转发给 @types 内部规则,并标记为生成非公开模块(@mod)。

  • 最终会为每个类型生成一个模块,包含指定的额外代码。

第二匹配项详解
($(#[$attr:meta])* pub types: $($T:ident),+; $($tt:tt)*) => {
   
        storage_types!(@types ($(#[$attr])*) @pub_mod $($T),+; ($($tt)*));
    };
  • pub types::字面匹配,必须是 pub types:(注意 pub 关键字)。
  • @pub_mod:字面标记,表示生成的模块是公开的(pub mod)。
  • 其它内容与上一个匹配相同
第三匹配项详解
(@types $attr:tt @$M:ident $($T:ident),+; $tt:tt) => {
   
       $(storage_types!(@type $attr @$M $T $tt);)+
};
  1. 输入模式:
  • @types:表示这是一个内部规则,由宏的其他规则调用。

  • $attr:tt:匹配一个 token tree(通常是从外层传递过来的属性,如 #[derive(Debug)])。

  • @$M:ident:匹配一个标识符(如 @mod 或 @pub_mod),表示模块的可见性。

  • $($T:ident),+:匹配一个或多个由逗号分隔的类型标识符(如 u32, f64)。

  • $tt:tt:匹配一个 token tree(通常是模块的额外内容,如函数、常量等)。

  1. 展开规则:

对每个类型 $T,调用 @type 规则:

  • $attr:传递属性。

  • @$M:传递模块可见性标记(@mod 或 @pub_mod)。

  • $T:传递当前类型。

  • $tt:传递额外内容。

  1. 关键点说明
    $(…);+ 语法:
  • 这是 Rust 宏的重复展开语法,表示对 ( ( (T),+ 中的每个 $T 执行一次 storage_types!(@type …)。

  • ; 表示每次展开后用分号分隔(虽然在这个上下文中分号是可选的,因为宏调用本身不需要分号)。

  • @$M:ident 的作用:

    • $M 可以是 mod 或 pub_mod,决定生成的模块是否是公开的。

    • 例如:

      • 如果 @$M 是 @mod,生成的模块是 mod(私有)。

      • 如果 @$M 是 @pub_mod,生成的模块是 pub mod(公开)。

  • $attr 和 $tt 的传递:

    • $attr 是属性(如 #[derive(Debug)]),会原样传递给 @type 规则。

    • $tt 是模块的额外内容(如函数、常量等),也会原样传递。

  1. 示例展开
    假设有以下调用:
storage_types!(@types (#[derive(Debug)]) @mod u32, f64; (
    const EXAMPLE: V = 42;
));

它会展开为:

storage_types!(@type (#[derive(Debug)]) @mod u32 (
    const EXAMPLE: V = 42;
));
storage_types!(@type (#[derive(Debug)]) @mod f64 (
    const EXAMPLE: V = 42;
));

然后 @type 规则会进一步处理 u32 和 f64,生成对应的模块。

  1. 总结
    这段规则的作用是:
  • 接收一组类型(如 u32, f64)和模块内容。

  • 对每个类型调用 @type 规则,分别生成对应的模块。

  • 确保属性和模块内容正确地传递到每个类型的处理中。

它是宏的“分发器”,将批量类型处理拆分为单个类型的处理,避免重复代码。

第四匹配项详解
(@type ($(#[$attr:meta])*) @$M:ident usize ($($tt:tt)*)) => {
   
    storage_type_usize!(($(#[$attr])*) @$M ($($tt)*));
};
  1. 输入模式:
  • @type:表示这是一个内部规则。

  • ($(#[$attr:meta])*):匹配零个或多个属性(如 #[derive(Debug)])。

  • @$M:ident:匹配模块可见性标记(@mod 或 @pub_mod)。

  • usize:字面匹配,表示当前处理的类型是 usize。

  • ($($tt:tt)*):匹配任意数量的 token tree(模块的额外内容)。

  1. 展开规则:

调用 storage_type_usize! 宏,并传递:

  • ($(#[$attr])*):所有属性。

  • @$M:模块可见性标记。

  • ($($tt)*):模块的额外内容。

  1. 关键点说明
  • usize 的特化处理:

    • 这是针对 usize 类型的特化规则,类似的规则也存在于其他类型(如 u32、f64 等)。

    • 这种设计允许为不同类型定制不同的生成逻辑。

  • 委托给 storage_type_usize!:

    • 实际工作委托给专门的宏 storage_type_usize!,可能是为了:

      • 代码模块化。

      • 允许用户自定义特定类型的实现。

  • 属性和内容的传递:

    • 所有属性和模块内容都原样传递给 storage_type_usize!。
  1. 示例展开
    假设有以下调用:
storage_types!(@type (#[derive(Debug)]) @pub_mod usize (
    const MAX: V = usize::MAX;
));

它会展开为:

storage_type_usize!((#[derive(Debug)]) @pub_mod (
    const MAX: V = usize::MAX;
));

然后 storage_type_usize! 会进一步处理,生成类似以下的代码:

#[derive(Debug)]
pub mod usize {
   
    pub type V = usize;
    const MAX: V = usize::MAX;
}
  1. 为什么需要这种设计?
  • 关注点分离:

    • storage_types! 负责类型的分发。

    • storage_type_*! 负责具体类型的实现。

  • 可扩展性:

    • 可以单独修改某个类型的生成逻辑(如 storage_type_usize!),而不影响其他类型。
  • 减少重复代码:

    • 共用属性处理和模块生成的逻辑。
  1. 总结
    这段规则的作用是:
  • 捕获 usize 类型的定义请求。

  • 将属性和模块内容委托给专门的 storage_type_usize! 宏处理。

  • 最终生成包含指定内容和属性的 usize 模块。

这是典型的宏分派模式,在复杂宏设计中很常见。

第五匹配项详解
(@type ($(#[$attr:meta])*) @$M:ident u8 ($($tt:tt)*)) => {
   
        storage_type_u8!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident u16 ($($tt:tt)*)) => {
   
        storage_type_u16!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident u32 ($($tt:tt)*)) => {
   
        storage_type_u32!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident u64 ($($tt:tt)*)) => {
   
        storage_type_u64!(($(#[$attr])*) @$M ($($tt)*));
    };
    (@type ($(#[$attr:meta])*) @$M:ident 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liuyuan77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值