【typenum】 4 标记特质(marker_traits.rs)

一、源码

代码定义了一系列用于类型级别编程的标记特质(marker traits)。typenum 是一个在类型级别上表示和操作数字的库,常用于编译时计算和类型约束。

//! All of the **marker traits** used in typenum.
//!
//! Note that the definition here for marker traits is slightly different than
//! the conventional one -- we include traits with functions that convert a type
//! to the corresponding value, as well as associated constants that do the
//! same.
//!
//! For example, the `Integer` trait includes the function (among others) `fn
//! to_i32() -> i32` and the associated constant `I32` so that one can do this:
//!
//! ```
//! use typenum::{Integer, N42};
//!
//! assert_eq!(-42, N42::to_i32());
//! assert_eq!(-42, N42::I32);
//! ```

use crate::sealed::Sealed;

/// 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 {}

/// A **marker trait** to designate that a type is zero. Only `B0`, `U0`, and `Z0`
/// implement this trait.
pub trait Zero: Sealed {}

/// A **Marker trait** for the types `Greater`, `Equal`, and `Less`.
pub trait Ord: Sealed {
    #[allow(missing_docs)]
    fn to_ordering() -> ::core::cmp::Ordering;
}

/// The **marker trait** for compile time bits.
pub trait Bit: Sealed + Copy + Default + 'static {
    #[allow(missing_docs)]
    const U8: u8;
    #[allow(missing_docs)]
    const BOOL: bool;

    /// Instantiates a singleton representing this bit.
    fn new() -> Self;

    #[allow(missing_docs)]
    fn to_u8() -> u8;
    #[allow(missing_docs)]
    fn to_bool() -> bool;
}

/// The **marker trait** for compile time unsigned integers.
///
/// # Example
/// ```rust
/// use typenum::{Unsigned, U3};
///
/// assert_eq!(U3::to_u32(), 3);
/// assert_eq!(U3::I32, 3);
/// ```
pub trait Unsigned: Sealed + Copy + Default + 'static {
    #[allow(missing_docs)]
    const U8: u8;
    #[allow(missing_docs)]
    const U16: u16;
    #[allow(missing_docs)]
    const U32: u32;
    #[allow(missing_docs)]
    const U64: u64;
    #[cfg(feature = "i128")]
    #[allow(missing_docs)]
    const U128: u128;
    #[allow(missing_docs)]
    const USIZE: usize;

    #[allow(missing_docs)]
    const I8: i8;
    #[allow(missing_docs)]
    const I16: i16;
    #[allow(missing_docs)]
    const I32: i32;
    #[allow(missing_docs)]
    const I64: i64;
    #[cfg(feature = "i128")]
    #[allow(missing_docs)]
    const I128: i128;
    #[allow(missing_docs)]
    const ISIZE: isize;

    #[allow(missing_docs)]
    fn to_u8() -> u8;
    #[allow(missing_docs)]
    fn to_u16() -> u16;
    #[allow(missing_docs)]
    fn to_u32() -> u32;
    #[allow(missing_docs)]
    fn to_u64() -> u64;
    #[cfg(feature = "i128")]
    #[allow(missing_docs)]
    fn to_u128() -> u128;
    #[allow(missing_docs)]
    fn to_usize() -> usize;

    #[allow(missing_docs)]
    fn to_i8() -> i8;
    #[allow(missing_docs)]
    fn to_i16() -> i16;
    #[allow(missing_docs)]
    fn to_i32() -> i32;
    #[allow(missing_docs)]
    fn to_i64() -> i64;
    #[cfg(feature = "i128")]
    #[allow(missing_docs)]
    fn to_i128() -> i128;
    #[allow(missing_docs)]
    fn to_isize() -> isize;
}

/// The **marker trait** for compile time signed integers.
///
/// # Example
/// ```rust
/// use typenum::{Integer, P3};
///
/// assert_eq!(P3::to_i32(), 3);
/// assert_eq!(P3::I32, 3);
/// ```
pub trait Integer: Sealed + Copy + Default + 'static {
    #[allow(missing_docs)]
    const I8: i8;
    #[allow(missing_docs)]
    const I16: i16;
    #[allow(missing_docs)]
    const I32: i32;
    #[allow(missing_docs)]
    const I64: i64;
    #[cfg(feature = "i128")]
    #[allow(missing_docs)]
    const I128: i128;
    #[allow(missing_docs)]
    const ISIZE: isize;

    #[allow(missing_docs)]
    fn to_i8() -> i8;
    #[allow(missing_docs)]
    fn to_i16() -> i16;
    #[allow(missing_docs)]
    fn to_i32() -> i32;
    #[allow(missing_docs)]
    fn to_i64() -> i64;
    #[cfg(feature = "i128")]
    #[allow(missing_docs)]
    fn to_i128() -> i128;
    #[allow(missing_docs)]
    fn to_isize() -> isize;
}

/// The **marker trait** for type-level arrays of type-level numbers.
///
/// Someday, it may contain an associated constant to produce a runtime array,
/// like the other marker traits here. However, that is blocked by [this
/// issue](https://github.com/rust-lang/rust/issues/44168).
pub trait TypeArray: Sealed {}

/// The **marker trait** for type-level numbers which are a power of two.
///
/// # Examples
///
/// Here's a working example:
///
/// ```rust
/// use typenum::{PowerOfTwo, P4, P8};
///
/// fn only_p2<P: PowerOfTwo>() {}
///
/// only_p2::<P4>();
/// only_p2::<P8>();
/// ```
///
/// Numbers which are not a power of two will fail to compile in this example:
///
/// ```rust,compile_fail
/// use typenum::{P9, P511, P1023, PowerOfTwo};
///
/// fn only_p2<P: PowerOfTwo>() { }
///
/// only_p2::<P9>();
/// only_p2::<P511>();
/// only_p2::<P1023>();
/// ```
pub trait PowerOfTwo: Sealed {}

二、模块文档注释

//! All of the **marker traits** used in typenum.
//!
//! Note that the definition here for marker traits is slightly different than
//! the conventional one -- we include traits with functions that convert a type
//! to the corresponding value, as well as associated constants that do the
//! same.
//!
//! For example, the `Integer` trait includes the function (among others) `fn
//! to_i32() -> i32` and the associated constant `I32` so that one can do this:
//!
//! ```
//! use typenum::{Integer, N42};
//!
//! assert_eq!(-42, N42::to_i32());
//! assert_eq!(-42, N42::I32);
//! ```
  • 这部分是模块级别的文档注释,说明了这些特质是 typenum 中使用的标记特质。

  • 这里的标记特质和传统的标记特质(无方法的空特质)略有不同,因为它们可能包含方法或关联常量,用于将类型转换为对应的值。

  • 示例展示了如何使用 Integer 特质的 to_i32() 方法和 I32 关联常量来获取类型的值。

三、引入 Sealed 特质

use crate::sealed::Sealed;
  • Sealed 是一个私有特质(通常用于防止下游用户实现这些标记特质,即“密封模式”)。

  • 所有标记特质都继承 Sealed,确保只有 typenum 内部可以为实现这些特质的类型。

四、标记特质定义

  1. NonZero 和 Zero
pub trait NonZero: Sealed {}
pub trait Zero: Sealed {}
  • NonZero:标记非零类型。除 B0、U0 和 Z0 外,所有数字类型都实现此特质。

  • Zero:标记零类型。只有 B0、U0 和 Z0 实现此特质。

  • 用途:用于编译时区分零和非零值(例如在类型级别除法中避免除零错误)。

  1. Ord
pub trait Ord: Sealed {
    fn to_ordering() -> ::core::cmp::Ordering;
}
  • 用于类型级别的比较结果(Greater、Equal、Less)。

  • to_ordering() 方法将类型转换为运行时的 Ordering 枚举值(Less、Equal、Greater)。

  1. Bit
pub trait Bit: Sealed + Copy + Default + 'static {
    const U8: u8;
    const BOOL: bool;
    fn new() -> Self;
    fn to_u8() -> u8;
    fn to_bool() -> bool;
}
  • 表示类型级别的位(0 或 1)。

  • 提供关联常量(U8、BOOL)和方法(to_u8、to_bool)将位转换为运行时值。

  • new() 用于创建该位的单例实例。

  1. Unsigned
pub trait Unsigned: Sealed + Copy + Default + 'static {
    const U8: u8;
    const U16: u16;
    // ... 其他整数类型的常量(U32, U64, USIZE, I8, I16, ...)
    fn to_u8() -> u8;
    fn to_u16() -> u16;
    // ... 其他整数类型的转换方法
}
  • 表示类型级别的无符号整数(如 U3、U42)。

  • 提供关联常量和方法将类型转换为各种整数类型的值(u8、i32 等)。

  • 示例:

use typenum::{Unsigned, U3};
assert_eq!(U3::to_u32(), 3);  // 使用方法
assert_eq!(U3::I32, 3);       // 使用关联常量
  1. Integer
pub trait Integer: Sealed + Copy + Default + 'static {
    const I8: i8;
    const I16: i16;
    // ... 其他有符号整数类型的常量(I32, I64, ISIZE)
    fn to_i8() -> i8;
    fn to_i16() -> i16;
    // ... 其他有符号整数类型的转换方法
}
  • 表示类型级别的有符号整数(如 P3、N42)。

  • 类似于 Unsigned,但提供有符号整数的转换。

  1. TypeArray
pub trait TypeArray: Sealed {}
  • 表示类型级别的数字数组(如 [U1, U2, U3])。

  • 目前仅作为标记特质,未来可能添加关联常量以生成运行时数组。

  1. PowerOfTwo
pub trait PowerOfTwo: Sealed {}
  • 标记类型级别的 2 的幂次方数(如 P1、P2、P4)。

  • 用途:在需要 2 的幂次方的上下文中约束类型(例如位掩码或对齐)。

  • 示例:

fn only_p2<P: PowerOfTwo>() {}
only_p2::<P4>(); // 合法
only_p2::<P3>(); // 编译错误

五、总结

这段代码定义了 typenum 的核心标记特质,用于:

  1. 区分零和非零类型(Zero、NonZero)。

  2. 表示类型级别的位(Bit)、无符号整数(Unsigned)和有符号整数(Integer)。

  3. 支持类型级别的比较(Ord)和数组(TypeArray)。

  4. 标记 2 的幂次方数(PowerOfTwo)。

这些特质通过关联常量和方法将类型级别的值映射到运行时值,同时利用 Rust 的类型系统在编译时强制执行约束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

liuyuan77

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

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

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

打赏作者

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

抵扣说明:

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

余额充值