#validation #invariants #generation #macro

prae

一个旨在提供更好的方式来定义需要验证的类型的大 crate。

22 个版本

0.8.4 2022 年 6 月 16 日
0.8.2 2022 年 3 月 18 日
0.6.0 2021 年 9 月 2 日
0.5.1 2021 年 7 月 11 日

#1028 in 开发工具

Download history • Rust 包仓库 14/week @ 2024-04-22 • Rust 包仓库 39/week @ 2024-04-29 • Rust 包仓库 42/week @ 2024-05-06 • Rust 包仓库 40/week @ 2024-05-13 • Rust 包仓库 127/week @ 2024-05-20 • Rust 包仓库 49/week @ 2024-05-27 • Rust 包仓库 52/week @ 2024-06-03 • Rust 包仓库 37/week @ 2024-06-10 • Rust 包仓库 27/week @ 2024-06-17 • Rust 包仓库 69/week @ 2024-06-24 • Rust 包仓库 64/week @ 2024-07-01 • Rust 包仓库 50/week @ 2024-07-08 • Rust 包仓库 31/week @ 2024-07-15 • Rust 包仓库 45/week @ 2024-07-22 • Rust 包仓库 82/week @ 2024-07-29 • Rust 包仓库 57/week @ 2024-08-05 • Rust 包仓库

219 每月下载量

Unlicense

37KB
474

prae

crates.io version docs.rs crates.io license

prae 是一个旨在提供更好的方式来定义需要验证的类型的大 crate。

库的主要概念是 Wrapper trait。此 trait 描述了一个包含某些内部值并提供构建、读取和修改它的方法的 Newtype 包装结构体。

创建实现 Wrapper 的类型的最简单方法是使用 define!extend! 宏。

示例

假设你想要创建一个类型 Username。你希望这个类型是 String,并且你不希望它为空。传统上,你会创建一个包装结构体,带有获取器和设置器函数,如下面的简化示例所示

#[derive(Debug)]
pub struct Username(String);

impl Username {
    pub fn new(username: &str) -> Result<Self, &'static str> {
        let username = username.trim().to_owned();
        if username.is_empty() {
            Err("value is invalid")
        } else {
            Ok(Self(username))
        }
    }

    pub fn get(&self) -> &str {
        &self.0
    }

    pub fn set(&mut self, username: &str) -> Result<(), &'static str> {
        let username = username.trim().to_owned();
        if username.is_empty() {
            Err("value is invalid")
        } else {
            self.0 = username;
            Ok(())
        }
   }
}

let username = Username::new(" my username ").unwrap();
assert_eq!(username.get(), "my username");

let err = Username::new("  ").unwrap_err();
assert_eq!(err, "value is invalid");

使用 prae,你会这样做

use prae::Wrapper;

prae::define! {
    #[derive(Debug)]
    pub Username: String;
    adjust |username| *username = username.trim().to_owned();
    ensure |username| !username.is_empty();
}

let username = Username::new(" my username ").unwrap();
assert_eq!(username.get(), "my username");

let err = Username::new("  ").unwrap_err();
assert_eq!(err.original, "value is invalid");
assert_eq!(err.value, "");

此外,prae 允许你使用自定义错误并扩展你的类型。有关 define!extend! 的更多信息,请参阅文档和示例。

编译速度

此 crate 提供的宏是声明性的,因此对编译速度几乎没有影响。

性能影响

如果你发现自己处于一个内部调整和验证你的类型成为性能瓶颈的情况(例如,你执行了重量级验证并在热点循环中修改了你的类型) - 尝试使用 _unprocessed 变体 [Wrapper] 方法。它们不会调用 [Wrapper::PROCESS]。然而,我强烈建议你在这些操作之后调用 [Wrapper::verify]。

特性标志

prae 提供了额外的功能

名称 描述
serde 添加了 [impl_serde] 插件。

致谢

这个软件包高度受到 tightness 软件包的启发。它基本上是 tightness 的一个分支,但有着略微不同的理念。有关详细信息,请参阅 这个问题

许可证:Unlicense

依赖项

~165KB