#literals #const-generics #const #overloading #generic #generics #no-alloc

无 std overloaded_literals

重载字面量,无需样板代码,并具有编译时验证来构建你的数据类型

10 个不稳定版本 (3 个重大更改)

0.8.3 2023年11月23日
0.8.2 2023年4月12日
0.7.1 2023年4月11日
0.6.0 2023年4月8日
0.5.2 2023年4月8日

#395Rust 模式

MIT/Apache

38KB
295

overloaded_literals — 最新版本 许可 要求 tests_badge

重载字面量,无需样板代码,并具有编译时验证来构建你的数据类型。

特性

  • 字面量的编译时验证(具有合理的编译器错误)
    • 支持 bool、有符号和无符号整数、浮点数和 &'static str
  • 无需仪式或样板代码即可构建你的类型。
  • 100% no_std 兼容。
  • 在稳定 Rust 上运行。MSRV: 1.65.0

包含对 std 的各种 NonZero 和 Wrapping 结构和 CStr 的实现。

用法

overloaded_literals 属性添加到函数中。这将把任何字面量重写为具有字面量作为泛型常量参数的特质的调用。因为使用了特质,所以自动构建任何所需的实现目标类型

use std::num::NonZeroI8;
use overloaded_literals::overloaded_literals;

#[overloaded_literals]
fn example() {
    let three: NonZeroI8 = 3;
    let result = three.saturating_mul(2); // <- This '2' also turns into a `NonZero` automatically because of the signature of `saturating_mul`.
    let six = 6; // <- And this '6' as well
    assert_eq!(result, six);
}
example()

特质实现可以对传递的字面量执行编译时验证(使用 'const evaluation')。这意味着无效的字面量将在编译时被拒绝,并显示描述性的错误消息

use std::num::NonZeroI8;
use overloaded_literals::overloaded_literals;

#[overloaded_literals]
fn mistake() -> NonZeroI8 {
    let oops: NonZeroI8 = 0; // <- compile error 'NonZero integer literal was 0'.
    oops.saturating_mul(2)
}
mistake();

实现特质

以下是一个示例,展示了类型 EvenI32 的特性实现,该类型确保存储的值是偶数,类似于 NonZeroI32 确保包含的值是非零。

use overloaded_literals::{overloaded_literals, FromLiteralUnsigned, FromLiteralSigned};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct EvenI32(i32);

impl EvenI32 {
    fn new(val: i32) -> Option<Self> {
        if val % 2 != 0 {
            None
        } else {
            Some(EvenI32(val))
        }
    }
}

// Called for 0 and positive literals:
impl<const LIT: u128> FromLiteralUnsigned<LIT> for EvenI32 {
    const VALID_LITERAL: u128 = {
        if LIT % 2 != 0 {
            panic!("Odd EvenI32 integer literal")
        } else {
            LIT
        }
    };
    fn into_self() -> Self {
        let raw = <Self as FromLiteralUnsigned<LIT>>::VALID_LITERAL as i32;
        EvenI32(raw)
    }
}

// Called for negative literals:
impl<const LIT: i128> FromLiteralSigned<LIT> for EvenI32 {
    const VALID_LITERAL: i128 = {
        if LIT % 2 != 0 {
            panic!("Odd EvenI32 integer literal")
        } else {
            LIT
        }
    };
    fn into_self() -> Self {
        let raw = <Self as FromLiteralSigned<LIT>>::VALID_LITERAL as i32;
        EvenI32(raw)
    }
}


#[overloaded_literals]
fn example() {
    let x: EvenI32 = 100;
    // let y: EvenI32 = 7; // <- This would cause a compile error :-)
}
example()

另一个完整的示例,说明如何为您的数据类型接受一个 str 文字面量,可以在 FromLiteralStr 的文档中找到。

缺失的特性

以下特性目前尚不支持,但可以轻松添加到库的后续版本中

  • char 文字面量的支持
  • 支持原始字节字符串文字面量(需要与 TypeStr 类似的抽象。

依赖关系

~280–720KB
~17K SLoC