30 个版本

0.2.32 2023 年 10 月 14 日
0.2.31 2023 年 5 月 29 日
0.2.30 2022 年 10 月 11 日
0.2.26 2022 年 7 月 5 日
0.2.10 2020 年 11 月 21 日

#5 in 文本处理

Download history 267087/week @ 2024-04-23 250901/week @ 2024-04-30 247732/week @ 2024-05-07 254316/week @ 2024-05-14 264192/week @ 2024-05-21 285246/week @ 2024-05-28 293776/week @ 2024-06-04 289393/week @ 2024-06-11 259807/week @ 2024-06-18 291099/week @ 2024-06-25 270472/week @ 2024-07-02 284068/week @ 2024-07-09 282114/week @ 2024-07-16 303691/week @ 2024-07-23 308266/week @ 2024-07-30 300570/week @ 2024-08-06

1,248,439 每月下载量
用于 933 个 Crates (249 直接)

Zlib 许可证

400KB
6K SLoC

Rust crates-io api-docs

编译时字符串格式化。

此crate提供在编译时格式化字符串的类型和宏。

Rust 版本

一些功能需要各种稳定的 Rust 版本,而另一些则需要 Rust 夜间版本,下面的部分描述了每个版本可用的功能。

Rust 1.57.0

这些宏在 Rust 1.57.0 中可用

  • concatcp: 连接 integersboolchar&str 常量到一个 &'static str 常量。

  • formatcp: 类似于 format 的格式化,它接受 integersboolchar&str 常量,并输出一个 &'static str 常量。

  • str_get: 索引一个 &'static str 常量,当索引超出范围时返回 None

  • str_index: 索引一个 &'static str 常量。

  • str_repeat: 通过重复一个 &'static str 常量 times 次来创建一个 &'static str

  • str_splice:替换一个静态字符串常量中的子字符串。

  • map_ascii_case:将一个静态字符串常量转换为不同的格式,由一个Case参数决定。

  • str_replace:将一个静态字符串常量中所有模式实例替换为另一个静态字符串常量。

“assertcp”特性使assertcpassertcp_eqassertcp_ne宏可用。这些宏类似于标准库中的assert宏,但它们在编译时进行评估,限制是它们只能接受基本类型作为参数(就像concatcpformatcp)。

Rust 1.64.0

“rust_1_64”特性使这些宏可用

Rust nightly

通过启用“fmt”特性,您可以使用类似std::fmt的API。

这需要nightly编译器,因为它在const fn中使用可变引用,而这些引用在编写这些文档时还没有稳定下来。

此crate的所有其他特性都是基于const_format::fmt API实现的

  • concatc:将许多标准库和用户定义类型连接成一个静态字符串常量。

  • formatc:类似于format的宏,可以将许多标准库和用户定义类型格式化为一个静态字符串常量。

  • writec:类似于write的宏,可以将许多标准库和用户定义类型格式化为实现了WriteMarker的类型。

"derive"”特性启用了ConstDebug宏和“"fmt"”特性。
ConstDebug宏派生了FormatMarker特质,并在编译时实现了内建的const_debug_fmt方法以进行调试格式化。

"assertc"”特性启用了assertcassertc_eqassertc_ne宏和“"fmt"”特性。
这些宏类似于标准库中的assert宏,但它们在编译时进行评估。

示例

原始类型的连接

use const_format::concatcp;

const NAME: &str = "Bob";
const FOO: &str = concatcp!(NAME, ", age ", 21u8,"!");

assert_eq!(FOO, "Bob, age 21!");

格式化原始类型

use const_format::formatcp;

const NAME: &str = "John";

const FOO: &str = formatcp!("{NAME}, age {}!", compute_age(NAME));

assert_eq!(FOO, "John, age 24!");

const fn compute_age(s: &str) -> usize { s.len() * 6 }

格式化自定义类型

此示例演示了如何使用ConstDebug派生宏,并将类型格式化为一个&'static str常量。

此示例需要Rust的nightly版本和“"derive"”特性。

#![feature(const_mut_refs)]

use const_format::{ConstDebug, formatc};

#[derive(ConstDebug)]
struct Message{
    ip: [Octet; 4],
    value: &'static str,
}

#[derive(ConstDebug)]
struct Octet(u8);

const MSG: Message = Message{
    ip: [Octet(127), Octet(0), Octet(0), Octet(1)],
    value: "Hello, World!",
};

const FOO: &str = formatc!("{:?}", MSG);

assert_eq!(
    FOO,
    "Message { ip: [Octet(127), Octet(0), Octet(0), Octet(1)], value: \"Hello, World!\" }"
);

格式化const断言

此示例演示了如何使用assertcp_ne宏进行带有格式化错误消息的编译时不等式断言。

这需要“"assertcp"”特性。

use const_format::assertcp_ne;

macro_rules! check_valid_pizza{
    ($user:expr, $topping:expr) => {
        assertcp_ne!(
            $topping,
            "pineapple",
            "You can't put pineapple on pizza, {}",
            $user,
        );
    }
}

check_valid_pizza!("John", "salami");
check_valid_pizza!("Dave", "sausage");
check_valid_pizza!("Bob", "pineapple");

这是编译器的输出

error[E0080]: evaluation of constant value failed
  --> src/lib.rs:178:27
   |
20 | check_valid_pizza!("Bob", "pineapple");
   |                           ^^^^^^^^^^^ the evaluated program panicked at '
assertion failed: `(left != right)`
 left: `"pineapple"`
right: `"pineapple"`
You can't put pineapple on pizza, Bob
', src/lib.rs:20:27


限制

来自const_format的所有宏都有以下限制

  • 扩展为&'static str的格式化宏只能使用具体类型的常量,因此虽然Type::<u8>::FOO参数是可行的,但Type::<T>::FOO则不行(T是一个类型参数)。

  • 整型参数必须具有从上下文中推断出的类型,有关整型参数的更多信息请参阅整型参数部分

  • 它们不能用于需要字符串字面量的地方。因此,#[doc = "foobar"]不能替换为#[doc = concatcp!("foo", "bar") ]

整型参数

整型参数必须从上下文中推断类型。因此,如果你只传递一个整型字面量,它必须有一个后缀。

编译示例

const N: u32 = 1;
assert_eq!(const_format::concatcp!(N + 1, 2 + N), "23");

assert_eq!(const_format::concatcp!(2u32, 2 + 1u8, 3u8 + 1), "234");

不编译示例

assert_eq!(const_format::concatcp!(1 + 1, 2 + 1), "23");

计划

目前没有。

重命名crate

当crate重命名时,可以使用来自const_format的所有类似函数宏。

ConstDebug派生宏具有#[cdeb(crate = "foo::bar")]属性,以告诉它在哪里可以找到const_format crate。

在Cargo.toml文件中重命名const_format crate的示例

[dependencies]
cfmt = {version = "0.*", package = "const_format"}

Cargo功能

  • "fmt":启用类似std::fmt的API,需要Rust nightly版本,因为它在const fn中使用可变引用。
    此功能包括formatc/writec格式化宏。

  • "derive":需要Rust nightly版本,隐含了"fmt"功能,提供在编译时格式化用户定义类型的ConstDebug派生宏。
    这隐式使用syn crate,因此带有此功能的清洁编译比没有此功能的时间要长一些。

  • "assertc":需要Rust nightly版本,隐含了"fmt"功能,启用assertcassertc_eqassertc_ne断言宏。
    此功能之前命名为"assert",但为了避免与"assertcp"功能混淆,已将其重命名。

  • "assertcp":启用 assertcpassertcp_eqassertcp_ne 断言宏。

  • "rust_1_64":启用 str_split 宏。允许 as_bytes_alt 方法和 slice_up_to_len_alt 方法在常数时间内运行,而不是线性时间(与切片截断部分成正比)。

无标准支持

const_format 无条件地 #![no_std],可以在任何可以使用 Rust 的地方使用。

支持的 Rust 版本最低

const_format 需要 Rust 1.57.0。

需要较新版本 Rust 或夜间编译器的功能需要通过 cargo features 显式启用。

依赖关系

~71–460KB