Trait validiter::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)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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. To exercise the 'ensure' adapter, we'll force all
    // elements to be non-negative as well

    // Here we define the errors we expect to encounter in
    // the parsing process:
    #[derive(Debug)]
    enum MatParseErr {
        NotAFloat(usize, usize, ParseFloatError),
        NoColumns(usize),
        Negative(usize, usize, f64),
        NoRows,
        JaggedArray(usize, Vec<f64>, usize, usize),
    }

    // 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 matrix over f64
    let mat = csv
        .lines()
        .enumerate()
        .map(|(i, line)| {
            line.split(",")
                .map(|s| s.trim())
                .enumerate()
                .map(|(j, s)| {
                    s.parse::<f64>()
                        .map_err(|parse_err| MatParseErr::NotAFloat(i, j, parse_err))
                })
                .ensure(|val| *val >= 0.0, |j, val| MatParseErr::Negative(i, j, val))
                .at_least(1, |_| MatParseErr::NoColumns(i))
                .collect::<Result<Vec<f64>, MatParseErr>>()
        })
        .at_least(1, |_| MatParseErr::NoRows)
        .const_over(
            |vec| vec.len(),
            |i, vec, len, expected_len| MatParseErr::JaggedArray(i, vec, len, *expected_len),
        )
        .collect::<Result<Vec<_>, _>>();

    match mat {
        Ok(mat) => {
            assert_eq!(mat, vec![vec![1.2, 3.0], vec![4.2, 0.5]]);
            println!("{mat:?}")
        }
        Err(mperr) => match mperr {
            MatParseErr::NotAFloat(i, j, err) => println!("Got {err} at pos [{i}, {j}]"),
            MatParseErr::NoColumns(i) => {
                println!("Row {i} is without any data, which would force the matrix to be empty")
            }
            MatParseErr::Negative(i, j, val) => {
                println!("value {val} at pos [{i}, {j}] is negative")
            }
            MatParseErr::NoRows => println!("There are no rows in the matrix"),
            MatParseErr::JaggedArray(i, _vec, len, expected_len) => {
                println!("Row {i} has len {len}, when all rows should have length {expected_len}")
            }
        },
    }
}

Object Safety§

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,