3个不稳定版本

0.2.0 2024年6月28日
0.1.1 2024年1月15日
0.1.0 2024年1月4日

数据结构 中排名 341

Download history 75/week @ 2024-06-22 139/week @ 2024-06-29 1/week @ 2024-07-06

每月下载 169

MIT/Apache

71KB
1K SLoC

你是一枚小小的锈虫吗?

你想写10,000行的函数并且永远地链式调用迭代器吗?

你喜欢看着编译器在试图弄清楚WTF是一个 Fold<Map<Filter<TakeWhile<Map<StepBy<Zip<SkipWhile... 的时候哭泣吗?

你对自己的丑陋、恶心的 命令式 代码感到不安吗?

介绍...

validiter (版本 0.2.0)

validiter 旨在提供一个漂亮的Rust API,用于对迭代器执行验证。这里提供了一个它提供的适配器的非常简单的示例

(0..10).validate().at_most(7, "too many!") // wraps the first 7 elements in Ok(i32) and the rest in a Err(ValidErr::WithElement(i32, Rc("too many!")))

不幸的是,我们美丽而纯净的函数经常被未清洗的数据所困扰。那么我们如何允许数据预处理集成到大型、LAZY迭代器链中呢?这就是validiter发挥作用的地方。总的来说,这个crate相当简单 - 拿一个迭代器,并声明你想要验证它。有2种方法可以这样做

  1. validiter::Unvalidatable 导入你的作用域,并在这个迭代器上调用 validate() - 现在你可以调用所有的 ValidIter 类型适配器。
  2. 有点磨损,但也是有效的 - 如果你的迭代器已经产生了结果,你可以将它们映射到 ValidIter::ValidErr<the--type-you-want>::<with--or-element-or-just-description>,然后导入 validiter::ErrCastable 到你的作用域,并在迭代器上调用 cast_errs - 这也将允许你调用 ValidIter 方法。

我们为这两种方法都有示例。我们将从一个简单的例子开始,使用 validate 方法(这是 examples 文件夹中的 multi_validated_iterator

use validiter::{Unvalidatable, ValidIter};

fn main() {
    // This is the standard way to use validiter - call validate on
    // some 'Unvalidatable' iterator, and then place restrictions
    // on the iteration. Notice that 'ValidErr' type errors are always
    // ignored by validiter adapters, so the order of validation
    // placement matters, if the iteration fails - there may be 
    // ignored errors, on elements that already failed a different
    // validation.
    (0..10)
        .validate()
        .at_most(7, "too many!")
        .between(2, 8, "out of bounds!")
        .ensure(|i| i % 2 == 0, "odd!")
        .at_least(4, "not enough!")
        .for_each(|v| println!("{:?}", v));
}

第二个示例稍微复杂一些,使用了cast_errs方法(在examples文件夹中的numeric_csv_parsing)。

use std::rc::Rc;

use validiter::{ErrCastable, ValidErr, ValidIter};

fn main() {
    // In this example we will use the 'cast_errs' method to
    // create a 'Vec<Vec<f64>>' collection, while ensuring
    // the mathematical validity if this collection as a numerical
    // matrix. We will also force the matrix to be non-negative,
    // just for funsies.

    // this is a CSV format str, with 2 rows and 2 columns
    let csv = "1.2, 3.0
                4.2, 0.5";

    // we'll use iterator methods on the CSV to build an actual
    // split the csv by rows/lines
    let mat = csv
        .lines()
        // convert each row to a matrix row
        .map(|line| {
            // split by elements
            line.split(",")
                // trim whitespace
                .map(|s| s.trim())
                .map(|s| {
                    // map to f64
                    s.parse::<f64>()
                        // if we get a parse error, we want to map it to our own error types - ValidErr<f64>
                        .map_err(|e| ValidErr::<f64>::Description(Rc::from(format!("{e}"))))
                })
                // the iterator is over VResult<f64>, but map is not a ValidIter!
                // because 'Map' is not a 'ValidIter', we need to convert the underlying data structure type
                .cast_errs() 
                // force non-empty rows
                .at_least(1, "no columns!")
                // simple 'greater than 0' validation
                .ensure(|f| *f >= 0.0, "negative!")
                // collecting each row to a vector, but now Ok Type is a vector, and Err Type is f64!
                .collect::<Result<Vec<f64>, ValidErr<f64>>>()
        })
        // we use cast_errs again to fix the typing issues
        .cast_errs()
        // force non-empty matrix
        .at_least(1, "no rows!")
        // force equal-sized rows
        .const_over(|vec| vec.len(), "row size changed!")
        // collect into a matrix
        .collect::<Result<Vec<_>, _>>();
    assert_eq!(mat, Ok(vec![vec![1.2, 3.0], vec![4.2, 0.5]]));
    print!("{:?}", mat)
}

该crate的大部分文档只是ValidIter特质各种方法的docstrings,所以如果你不确定某个验证适配器做什么,那可能就是你要去的地方。

许可证

根据以下任何一个许可证授权:

由你选择。

贡献

除非你明确表示,否则,根据Apache-2.0许可证定义,你故意提交以包含在作品中的任何贡献,将如上所述双重许可,不附加任何额外条款或条件。

依赖项

约165KB