Trait 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)
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, 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,