pub trait ConstOver<T, E, A, M, Factory>: Iterator<Item = Result<T, E>> + Sized{
// Provided method
fn const_over(
self,
extractor: M,
factory: Factory,
) -> ConstOverIter<Self, T, E, A, M, Factory> { ... }
}
Provided Methods§
sourcefn const_over(
self,
extractor: M,
factory: Factory,
) -> ConstOverIter<Self, T, E, A, M, Factory>
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.