Trait AtLeast

Source
pub trait AtLeast<T, E, Factory>: Iterator<Item = Result<T, E>> + Sized
where Factory: Fn(usize) -> E,
{ // Provided method fn at_least( self, min_count: usize, factory: Factory, ) -> AtLeastIter<Self, T, E, Factory> { ... } }

Provided Methods§

Source

fn at_least( self, min_count: usize, factory: Factory, ) -> AtLeastIter<Self, T, E, Factory>

Fails a validation iterator if it does not contain n or more elements.

at_least(n, factory) yields Ok(element) values until the iteration ends. If the number of values in the iteration is less than n, a new element is added to the end of the iteration with the value returned from calling factory on the length of the iterator.

The at_least adapter cannot handle short-circuiting of iterators, so iterations such as (0..10).validate().at_least(100).take(5) will not fail.

Elements already wrapped in Result::Err will not be counted towards reaching the n elements lower bound. The length provided to factory includes elements wrapped in Result::Err.

§Examples

Basic usage:

struct NotEnough(usize);
let mut iter = a.iter().map(|v| Ok(v)).at_least(4, |i| NotEnough(i));

assert_eq!(iter.next(), Some(Ok(&1)));
assert_eq!(iter.next(), Some(Ok(&2)));
assert_eq!(iter.next(), Some(Ok(&3)));
assert_eq!(iter.next(), Some(Err(NotEnough(3))));
assert_eq!(iter.next(), None);

at_least could be used to ensure that a vector created from an iterator has a value in some index:

use validiter::AtLeast;
let iter = 0..=2; // iteration is too short, no 4th element!

let collection: Result<Vec<_>, _> = iter
    .map(|v| Ok(v))
    .at_least(4, |_| Err::<i32, ()>(()))
    .collect();

match collection {
    Ok(vec) => {
        let val = vec[3]; // doesn't crash, because the collection failed.
    }
    Err(_) => {} // handle error
};

at_least will not account for errors already in the iteration:

let mut iter = [Ok(0), Err(404)]
    .into_iter()
    .at_least(2, |_| 505);
assert_eq!(iter.next(), Some(Ok(0)));
assert_eq!(iter.next(), Some(Err(404)));
assert_eq!(iter.next(), Some(Err(505)));
Examples found in repository?
examples/numeric_csv_parsing.rs (line 40)
5fn main() {
6    // In this example we will use the 'cast_errs' method to
7    // create a 'Vec<Vec<f64>>' collection, while ensuring
8    // the mathematical validity if this collection as a numerical
9    // matrix. To exercise the 'ensure' adapter, we'll force all
10    // elements to be non-negative as well
11
12    // Here we define the errors we expect to encounter in
13    // the parsing process:
14    #[derive(Debug)]
15    enum MatParseErr {
16        NotAFloat(usize, usize, ParseFloatError),
17        NoColumns(usize),
18        Negative(usize, usize, f64),
19        NoRows,
20        JaggedArray(usize, Vec<f64>, usize, usize),
21    }
22
23    // this is a CSV format str, with 2 rows and 2 columns
24    let csv = "1.2, 3.0
25                4.2, 0.5";
26
27    // we'll use iterator methods on the CSV to build an actual matrix over f64
28    let mat = csv
29        .lines()
30        .enumerate()
31        .map(|(i, line)| {
32            line.split(",")
33                .map(|s| s.trim())
34                .enumerate()
35                .map(|(j, s)| {
36                    s.parse::<f64>()
37                        .map_err(|parse_err| MatParseErr::NotAFloat(i, j, parse_err))
38                })
39                .ensure(|val| *val >= 0.0, |j, val| MatParseErr::Negative(i, j, val))
40                .at_least(1, |_| MatParseErr::NoColumns(i))
41                .collect::<Result<Vec<f64>, MatParseErr>>()
42        })
43        .at_least(1, |_| MatParseErr::NoRows)
44        .const_over(
45            |vec| vec.len(),
46            |i, vec, len, expected_len| MatParseErr::JaggedArray(i, vec, len, *expected_len),
47        )
48        .collect::<Result<Vec<_>, _>>();
49
50    match mat {
51        Ok(mat) => {
52            assert_eq!(mat, vec![vec![1.2, 3.0], vec![4.2, 0.5]]);
53            println!("{mat:?}")
54        }
55        Err(mperr) => match mperr {
56            MatParseErr::NotAFloat(i, j, err) => println!("Got {err} at pos [{i}, {j}]"),
57            MatParseErr::NoColumns(i) => {
58                println!("Row {i} is without any data, which would force the matrix to be empty")
59            }
60            MatParseErr::Negative(i, j, val) => {
61                println!("value {val} at pos [{i}, {j}] is negative")
62            }
63            MatParseErr::NoRows => println!("There are no rows in the matrix"),
64            MatParseErr::JaggedArray(i, _vec, len, expected_len) => {
65                println!("Row {i} has len {len}, when all rows should have length {expected_len}")
66            }
67        },
68    }
69}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<I, T, E, Factory> AtLeast<T, E, Factory> for I
where I: Iterator<Item = Result<T, E>>, Factory: Fn(usize) -> E,