【typenum】 16 非零标记及改进建议
一、源码
这段代码定义了一个标记 trait NonZero,用于在类型系统中表示"非零"的数值类型。这是 Rust 类型级编程(type-level programming)的典型模式,常见于类型算术(type-level arithmetic)库中。
- 定义
/// A **marker trait** to designate that a type is not zero. All number types in this
/// crate implement `NonZero` except `B0`, `U0`, and `Z0`.
pub trait NonZero: Sealed {}
- B1实现(bit.rs)
impl NonZero for B1 {}
- UInt实现(uint.rs)
impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {}
- PInt、NInt实现(int.rs)
impl<U: Unsigned + NonZero> NonZero for PInt<U> {}
impl<U: Unsigned + NonZero> NonZero for NInt<U> {}
二、核心定义 (marker_traits.rs)
pub trait NonZero: Sealed {}
-
标记 trait:没有方法或关联类型,仅用于类型分类
-
作用:标识该类型代表非零值
-
Sealed:这是一个密封 trait,防止外部类型实现
-
注释说明:除了 B0、U0 和 Z0 外,所有数值类型都实现此 trait
三、各类型实现
- 位类型实现 (bit.rs)
impl NonZero for B1 {}
-
B1 表示二进制位 1
-
只有 B1 实现 NonZero,B0 不实现(符合"非零"定义)
- 无符号整数实现 (uint.rs)
impl<U: Unsigned, B: Bit> NonZero for UInt<U, B> {}
-
UInt<U, B> 是类型级无符号整数的通用结构
-
任何由 Unsigned 类型 U 和位 B 组成的 UInt 都自动是非零
-
注意:UInt<UTerm, B0>(即 U0)不实现此 trait
- 有符号整数实现 (int.rs)
impl<U: Unsigned + NonZero> NonZero for PInt<U> {} // 正整数
impl<U: Unsigned + NonZero> NonZero for NInt<U> {} // 负整数
-
PInt 表示正整数,NInt 表示负整数
-
只有当底层无符号类型 U 是 NonZero 时,它们才是 NonZero
-
例如:
-
PInt 是 NonZero(因为 U1 是 NonZero)
-
PInt 不是 NonZero(因为 U0 不是 NonZero)
-
四、设计意义
- 类型安全:
fn divide<T: NonZero>(numerator: i32, _denominator: T) -> i32 {numerator / unsafe { std::mem::transmute::<T, i32>(_denominator) }
}
保证除数永远不会是零
- 编译时验证:
trait SafeDivision {type Output;}impl<T: NonZero> SafeDivision for T {type Output = Self;}
- 与零类型互补:
-
Zero trait 和 NonZero trait 共同覆盖所有数值类型
-
通过 trait 约束可以明确区分零/非零场景
五、典型使用场景
- 类型级算术运算:
fn generic_fn<T: NonZero>() {// 保证T不是零类型
}
- 安全数学运算:
struct Ratio<N, D: NonZero> {numerator: N,denominator: D,}
硬件寄存器操作(确保不写零值到特定寄存器)
这种模式在需要编译时保证数值属性的场景非常有用,特别是嵌入式开发、密码学、区块链等对安全性要求高的领域。
六、改进建议
- 正整数类型改名
原类型 | 新命名 | 数学含义 | 扩展性设计 |
---|---|---|---|
UInt<U,B> | UPos<U,B> | 二进制无符号正整数 (2*U + B) | 保留U前缀与无符号体系一致 |
PInt | SPos | 有符号正整数 | S前缀(Signed)为小数/浮点数预留 |
- 负整数类型改名
原类型 | 新命名 | 数学含义 | 扩展性设计 |
---|---|---|---|
NInt | SNeg | 有符号负整数 | 明确负号语义,支持后续小数/浮点数实现 |
- 扩展预留设计
/// 有符号类型标记(为小数预留)
pub trait Sign {const IS_POSITIVE: bool;
}impl<U: Unsigned> Sign for SPos<U> {const IS_POSITIVE: bool = true;
}impl<U: Unsigned> Sign for SNeg<U> {const IS_POSITIVE: bool = false;
}/// 未来可扩展的小数类型
pub struct SFrac<U: Unsigned, S: Sign> { /*...*/ }