32 个版本
0.3.9 | 2024年4月17日 |
---|---|
0.3.8 | 2023年12月6日 |
0.3.7 | 2023年11月28日 |
0.3.5 | 2023年5月1日 |
0.2.4 | 2021年3月31日 |
在 Rust 模式 中排名第 72
每月下载量 289,035
在 89 个crate中使用 (15 个直接使用)
545KB
9K SLoC
std 函数的常量等效和常量解析。
功能
本crate提供
-
标准库函数和方法的常量等效。
-
通过
Parser
类型,以及parser_method
宏进行编译时解析。
示例
解析枚举
本示例演示了如何在编译时从环境变量中解析一个简单的枚举。
use konst::{
eq_str,
option,
result::unwrap_ctx,
};
#[derive(Debug, PartialEq)]
enum Direction {
Forward,
Backward,
Left,
Right,
}
impl Direction {
const fn try_parse(input: &str) -> Result<Self, ParseDirectionError> {
// As of Rust 1.65.0, string patterns don't work in const contexts
match () {
_ if eq_str(input, "forward") => Ok(Direction::Forward),
_ if eq_str(input, "backward") => Ok(Direction::Backward),
_ if eq_str(input, "left") => Ok(Direction::Left),
_ if eq_str(input, "right") => Ok(Direction::Right),
_ => Err(ParseDirectionError),
}
}
}
const CHOICE: &str = option::unwrap_or!(option_env!("chosen-direction"), "forward");
const DIRECTION: Direction = unwrap_ctx!(Direction::try_parse(CHOICE));
fn main() {
match DIRECTION {
Direction::Forward => assert_eq!(CHOICE, "forward"),
Direction::Backward => assert_eq!(CHOICE, "backward"),
Direction::Left => assert_eq!(CHOICE, "left"),
Direction::Right => assert_eq!(CHOICE, "right"),
}
}
#[derive(Debug, PartialEq)]
pub struct ParseDirectionError;
use std::fmt::{self, Display};
impl Display for ParseDirectionError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Failed to parse a Direction")
}
}
impl ParseDirectionError {
const fn panic(&self) -> ! {
panic!("failed to parse a Direction")
}
}
解析 CSV
本示例演示了如何将 CSV 解析为整数。
此示例需要 "parsing" 和
"iter"
功能(两者都默认启用)。
use konst::{
primitive::parse_u64,
result::unwrap_ctx,
iter, string,
};
const CSV: &str = "3, 8, 13, 21, 34";
static PARSED: [u64; 5] = iter::collect_const!(u64 =>
string::split(CSV, ","),
map(string::trim),
map(|s| unwrap_ctx!(parse_u64(s))),
);
assert_eq!(PARSED, [3, 8, 13, 21, 34]);
解析结构体
本示例演示了如何将键值对格式解析为结构体。
此需要 "parsing" 功能(默认启用)。
use konst::{
parsing::{Parser, ParseValueResult},
eq_str,
for_range, parser_method, try_, unwrap_ctx,
};
const PARSED: Struct = {
// You can also parse strings from environment variables, or from an `include_str!(....)`
let input = "\
colors = red, blue, green, blue
amount = 1000
repeating = circle
name = bob smith
";
unwrap_ctx!(parse_struct(Parser::new(input))).0
};
fn main(){
assert_eq!(
PARSED,
Struct{
name: "bob smith",
amount: 1000,
repeating: Shape::Circle,
colors: [Color::Red, Color::Blue, Color::Green, Color::Blue],
}
);
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Struct<'a> {
pub name: &'a str,
pub amount: usize,
pub repeating: Shape,
pub colors: [Color; 4],
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Shape {
Circle,
Square,
Line,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Color {
Red,
Blue,
Green,
}
pub const fn parse_struct(mut parser: Parser<'_>) -> ParseValueResult<'_, Struct<'_>> {
let mut name = "<none>";
let mut amount = 0;
let mut repeating = Shape::Circle;
let mut colors = [Color::Red; 4];
parser = parser.trim_end();
if !parser.is_empty() {
loop {
let mut prev_parser = parser.trim_start();
parser = try_!(parser.find_skip('='));
parser_method!{prev_parser, strip_prefix;
"name" => (name, parser) = try_!(parser.trim_start().split_keep('\n')),
"amount" => (amount, parser) = try_!(parser.trim_start().parse_usize()),
"repeating" => (repeating, parser) = try_!(parse_shape(parser.trim_start())),
"colors" => (colors, parser) = try_!(parse_colors(parser.trim_start())),
_ => {
let err = &"could not parse Struct field name";
return Err(prev_parser.into_other_error(err));
}
}
if parser.is_empty() {
break
}
parser = try_!(parser.strip_prefix("\n"));
}
}
Ok((Struct{name, amount, repeating, colors}, parser))
}
pub const fn parse_shape(mut parser: Parser<'_>) -> ParseValueResult<'_, Shape> {
let shape = parser_method!{parser, strip_prefix;
"circle" => Shape::Circle,
"square" => Shape::Square,
"line" => Shape::Line,
_ => return Err(parser.into_other_error(&"could not parse Shape"))
};
Ok((shape, parser))
}
pub const fn parse_colors<const LEN: usize>(
mut parser: Parser<'_>,
) -> ParseValueResult<'_, [Color; LEN]> {
let mut colors = [Color::Red; LEN];
for_range!{i in 0..LEN =>
(colors[i], parser) = try_!(parse_color(parser.trim_start()));
match parser.strip_prefix(",") {
Ok(next) => parser = next,
Err(_) if i == LEN - 1 => {}
Err(e) => return Err(e),
}
}
Ok((colors, parser))
}
pub const fn parse_color(mut parser: Parser<'_>) -> ParseValueResult<'_, Color> {
let color = parser_method!{parser, strip_prefix;
"red" => Color::Red,
"blue" => Color::Blue,
"green" => Color::Green,
_ => return Err(parser.into_other_error(&"could not parse Color"))
};
Ok((color, parser))
}
Cargo 功能
以下为这些crate的功能
-
"iter"
(默认启用):启用所有迭代项,包括接受/返回迭代器的宏/函数, -
"cmp"
(默认启用):启用所有比较函数和宏,字符串相等性和排序比较函数不需要此功能。 -
"parsing_proc"
(默认启用):启用"parsing"
功能,编译konst_proc_macros
依赖项,并启用parser_method
宏。如果编译时间稍长不是问题,可以使用此功能代替"parsing"
。 -
"parsing"
(默认启用):启用parsing
模块(用于从&str
和&[u8]
解析),primitive::parse_*
函数,以及try_rebind
和rebind_if_ok
宏。 -
alloc"
:启用使用alloc
crate 中的类型的项,包括Vec
和String
。
Rust 发布相关
默认情况下,所有这些功能都没有启用。
-
"rust_latest_stable"
:启用最新的"rust_1_*"
功能(目前没有)。只有当你能够每发布一个稳定版本的 Rust 编译器时才推荐使用。 -
"mut_refs"
(默认禁用):启用接受可变引用的常量函数。在可变引用在常量上下文中稳定时使用此功能。还启用"rust_latest_stable"
功能。 -
"nightly_mut_refs"
(默认禁用):启用"mut_refs"
功能。需要 Rust 夜间版本。
No-std 支持
konst
是 #![no_std]
,可以在任何可以使用 Rust 的地方使用。
最低支持的 Rust 版本
konst
需要 Rust 1.65.0。
需要较新版本的 Rust 或夜间编译器的功能需要通过 crate 功能显式启用。
依赖项
~0.5–8MB
~54K SLoC