13个版本
| 0.2.32 | 2023年10月14日 |
|---|---|
| 0.2.31 | 2023年5月29日 |
| 0.2.29 | 2022年10月11日 |
| 0.2.22 | 2021年10月14日 |
| 0.2.8 | 2020年10月7日 |
#1513 在 文本处理
1,137,419 每月下载量
在 827 个crate中使用了(通过 const_format)
110KB
3K SLoC
编译时字符串格式化。
此crate提供用于编译时格式化字符串的类型和宏。
Rust版本
某些功能需要各种稳定的Rust版本,而其他功能则需要Rust nightly版本,下面的部分描述了每个版本可用的功能。
Rust 1.57.0
以下宏在Rust 1.57.0中可用
-
concatcp:将integers、bool、char和&str常量连接成一个&'static str常量。 -
formatcp:类似于format的格式化,它接受integers、bool、char和&str常量,并输出一个&'static str常量。 -
str_get:索引一个&'static str常量,当索引超出范围时返回None。 -
str_index:索引一个常量字符串。 -
str_repeat:通过重复一个常量字符串来创建一个新的常量字符串。 -
str_splice:替换一个常量字符串中的子字符串。 -
map_ascii_case:将一个常量字符串转换为不同的大小写风格,由一个Case参数决定。 -
str_replace:将一个常量字符串中所有模式实例替换为另一个常量字符串。
"assertcp" 功能启用 assertcp、assertcp_eq 和 assertcp_ne 宏。这些宏类似于标准库 assert 宏,但在编译时评估,限制是它们只能有原始类型作为参数(就像 concatcp 和 formatcp)。
Rust 1.64.0
"rust_1_64" 功能启用这些宏
str_split:分割一个字符串常量
Rust nightly
通过启用 "fmt" 功能,您可以使用类似 std::fmt 的 API。
这需要 nightly 编译器,因为它在 const fn 中使用可变引用,这在撰写这些文档时尚未稳定。
此包的所有其他功能都是在 const_format::fmt API 的基础上实现的。
-
concatc:将许多标准库和用户定义的类型连接到一个常量字符串。 -
writec:类似于write的宏,可以将许多标准库和用户定义的类型格式化为实现WriteMarker的类型。
"derive" 功能启用了 ConstDebug 宏和 "fmt" 功能。
ConstDebug 继承了 FormatMarker 特性,并实现了一个用于编译时调试格式化的内在方法 const_debug_fmt。
"assertc" 功能启用了 assertc、assertc_eq、assertc_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 夜间版本,并且需要 "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 derive宏有一个#[cdeb(crate = "foo::bar")]属性,用于指示在哪里可以找到const_format crate。
在Cargo.toml文件中重命名const_format crate的示例
[dependencies]
cfmt = {version = "0.*", package = "const_format"}
Cargo功能
-
"fmt":启用类似std::fmt的API,因为使用了在const fn中的可变引用,所以需要Rust nightly版本。
此功能包括formatc/writec格式化宏。 -
"derive":需要Rust nightly版本,隐含了"fmt"功能,提供ConstDebugderive宏,在编译时格式化用户定义的类型。
此功能隐式使用syncrate,因此带有该功能的编译会比不带该功能的编译慢一些。 -
"assertc":需要Rust nightly版本,隐含了"fmt"功能,启用了assertc、assertc_eq和assertc_ne断言宏。
此功能之前命名为"assert",但为了避免与"assertcp"功能混淆,已将其重命名。 -
"assertcp":启用assertcp、assertcp_eq和assertcp_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显式启用。
依赖项
~73–480KB
~11K SLoC