|
1 | 1 | # quantor |
2 | 2 | [](https://crates.io/crates/quantor) |
3 | 3 | [](https://docs.rs/quantor) |
4 | | -[](https://crates.io/crates/quantor) |
5 | 4 | [](https://crates.io/crates/quantor) |
6 | | -[](https://github.com/nervousnullptr/quantor#msrv) |
| 5 | +[](https://github.com/nervousnullptr/quantor#msrv) |
7 | 6 |
|
8 | | -**Declarative quantifiers and logical assertions for Rust iterators and collections.** |
9 | | -`quantor` provides lightweight, expressive tools for validation, filtering, and testing — with zero dependencies. |
| 7 | +**Declarative logic for iterators and collections.** |
| 8 | +`quantor` lets you express conditions like `forall`, `exists`, `none`, and `existsforall` directly over data — making filtering, validation, and testing expressive, readable, and idiomatic. |
10 | 9 |
|
11 | | ---- |
| 10 | +## Why Quantor? |
12 | 11 |
|
13 | | -## ✨ Features |
14 | | -`quantor` lets you express logic over data in a way that feels natural and readable: |
| 12 | +Rust's iterator methods are powerful, but when you want to write logic that reads like: |
15 | 13 |
|
16 | | -- 📐 **Quantifiers** — Use familiar constructs like `forall`, `exists`, `none`, and `exactly_one`. |
17 | | -- 🧹 **Selection utilities** — Filter with `select_where`, extract duplicates, check for uniqueness. |
18 | | -- 🧠 **Structured logic** — Run `pairwise` comparisons or validate equality across items. |
19 | | -- 🧪 **Assertions** — Add runtime guarantees with `assert_forall!`, `assert_exists!`, etc. |
| 14 | +- "All elements are even" |
| 15 | +- "At least one user is active" |
| 16 | +- "Exactly three items matched a condition" |
20 | 17 |
|
21 | | ---- |
| 18 | +you're often stuck with `.all()`, `.any()`, `.filter().count()`, and some `assert!` noise. |
22 | 19 |
|
23 | | -## 🚀 Example |
| 20 | +With `quantor`, your code becomes declarative and reflects the logic you care about, not the mechanics. |
| 21 | + |
| 22 | +## Highlights |
| 23 | + |
| 24 | +- **Quantifiers** — `forall`, `exists`, `none`, `exactly_one`, `exactly_n`, `all_equal`, `pairwise`, `forallexists`, and more. |
| 25 | +- **Assertions** — Runtime logic assertions like `assert_forall!`, `assert_unique!`, `assert_pairwise!`, with expressive failure output. |
| 26 | +- **Predicate-based selection** — Filter, deduplicate, or extract based on logic: `select_where`, `select_unique`, `select_duplicates`. |
| 27 | +- **Diagnostics** — Inspect failing indices, collect mismatches, or integrate with fuzzing tools using `QuantorError`. |
| 28 | +- **Rust-native, ergonomic API** – Works with any `IntoIterator`, zero dependencies, and optional `.method()` trait extension. |
| 29 | + |
| 30 | +## Example |
| 31 | + |
| 32 | +If you're validating input for a product catalog: |
24 | 33 |
|
25 | 34 | ```rust |
26 | | -use quantor::{forall, select_where, assert_forall}; |
| 35 | +use quantor::{forall, exists, pairwise, assert_unique}; |
27 | 36 |
|
28 | | -let nums = vec![2, 4, 6]; |
| 37 | +#[derive(Debug)] |
| 38 | +struct Product { |
| 39 | + id: u32, |
| 40 | + price: f64, |
| 41 | + active: bool, |
| 42 | +} |
29 | 43 |
|
30 | | -// Check if all elements are even |
31 | | -assert!(forall(&nums, |x| x % 2 == 0)); |
| 44 | +let products = vec![ |
| 45 | + Product { id: 1, price: 19.99, active: true }, |
| 46 | + Product { id: 2, price: 29.99, active: true }, |
| 47 | + Product { id: 3, price: 0.0, active: false }, |
| 48 | +]; |
32 | 49 |
|
33 | | -// Use the macro version for test-friendly assertions |
34 | | -assert_forall!(&nums, |x| x % 2 == 0); |
| 50 | +// Check that all active products have a price > 0. |
| 51 | +forall(&products, |p| !p.active || p.price > 0.0)?; |
35 | 52 |
|
36 | | -// Extract matching elements |
37 | | -let evens = select_where(&nums, |x| x % 2 == 0); |
38 | | -assert_eq!(evens, vec![&2, &4, &6]); |
| 53 | +// Ensure IDs are unique. |
| 54 | +assert_unique!(&products.iter().map(|p| p.id).collect::<Vec<_>>()); |
| 55 | + |
| 56 | +// Confirm at least one product is available. |
| 57 | +exists(&products, |p| p.active)?; |
39 | 58 | ``` |
40 | | ---- |
41 | 59 |
|
42 | | -## 📦 Installation |
43 | | -Add this to your `Cargo.toml`: |
| 60 | +This is readable, declarative, and robust – and every check returns a Result with index-level error diagnostics. |
| 61 | + |
| 62 | +## Installation |
| 63 | +Add `quantor` to your `Cargo.toml`: |
44 | 64 | ``` |
45 | 65 | quantor = "0.1" |
46 | 66 | ``` |
47 | 67 | Optional features: |
48 | | -* `method-api` – Enable `.forall()` and other iterator-style methods. |
49 | | -* `debug-tools` – Add debugging macros like `debug_assert_forall!` or `debug_exists!`. |
50 | | - |
51 | | ---- |
| 68 | +* `method-api` — Enables `.forall()`, `.exists()`, `.select_where()`, etc. on slices and iterators. |
| 69 | +* `debug-tools` — Enables `debug_assert_*` and `debug_*` macros for non-panicking diagnostics. |
52 | 70 |
|
53 | 71 | ## 📚 Documentation |
54 | 72 |
|
55 | | -See docs.rs/quantor for full API documentation and examples. |
| 73 | +See [docs.rs](https://docs.rs/quantor) for full API documentation and examples. |
0 commit comments