Trait validiter::ConstOver

source ·
pub trait ConstOver<T, E, A, M, Factory>: Iterator<Item = Result<T, E>> + Sized
where A: PartialEq, M: Fn(&T) -> A, Factory: Fn(usize, T, A, &A) -> E,
{ // Provided method fn const_over( self, extractor: M, factory: Factory, ) -> ConstOverIter<Self, T, E, A, M, Factory> { ... } }

Provided Methods§

source

fn const_over( self, extractor: M, factory: Factory, ) -> ConstOverIter<Self, T, E, A, M, Factory>

Fails an iteration if extractor does not give the same result for all elements.

const_over(extractor, factory) takes a Fn argument that computes some value for each element in iteration. If for some element this results in a value which is not equal to value computed from the first element, factory is called on the current iteration index, the element, the value extracted from this element, and the first value (which the extraction failed to equal). Otherwise, the element is wrapped in Ok(element). The first valid element is always wrapped in Ok.

§Examples

Basic usage:

use validiter::ConstOver;
let somecase = "ABc";
let mut iter = somecase.chars().map(|c| Ok(c)).const_over(
    |c| c.is_uppercase(),
    |index, char, case, expected_case| {
        (index, char, case, *expected_case == 'A'.is_uppercase())
    },
);
 
assert_eq!(iter.next(), Some(Ok('A')));
assert_eq!(iter.next(), Some(Ok('B')));
assert_eq!(
    iter.next(),
    Some(Err((2, 'c', false, true)))
);

const_over ignores errors:

use validiter::ConstOver;
use validiter::Ensure;
 
#[derive(Debug, PartialEq)]
enum IterErr {
    IsA,
    CaseChanged,
}
let uppercase = "Abc";
let mut iter = uppercase
    .chars()
    .map(|v| Ok(v))
    .ensure(|c| *c != 'A', |_, _| IterErr::IsA)
    .const_over(|c| c.is_uppercase(), |_, _, _, _| IterErr::CaseChanged);
 
assert_eq!(
    iter.next(),
    Some(Err(IterErr::IsA))
);
assert_eq!(iter.next(), Some(Ok('b')));
assert_eq!(iter.next(), Some(Ok('c')));
Examples found in repository?
examples/numeric_csv_parsing.rs (lines 44-47)
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, A, M, Factory> ConstOver<T, E, A, M, Factory> for I
where I: Iterator<Item = Result<T, E>>, A: PartialEq, M: Fn(&T) -> A, Factory: Fn(usize, T, A, &A) -> E,