use crate::{Headers, Row, RowStream, RowResult};
pub struct FilterRow<I, F> {
iter: I,
f: F,
headers: Headers,
}
impl<I, F> FilterRow<I, F>
where
I: RowStream,
F: Fn(&Headers, &Row) -> bool,
{
pub fn new(
iter: I,
f: F,
) -> FilterRow<I, F> {
let headers = iter.headers().clone();
FilterRow {
iter,
f,
headers,
}
}
}
pub struct IntoIter<I, F> {
iter: I,
f: F,
headers: Headers,
}
impl<I, F> Iterator for IntoIter<I, F>
where
I: Iterator<Item = RowResult>,
F: Fn(&Headers, &Row) -> bool,
{
type Item = RowResult;
fn next(&mut self) -> Option<Self::Item> {
for rs in self.iter.by_ref() {
match rs {
Ok(row) => if (self.f)(&self.headers, &row) {
return Some(Ok(row));
}
Err(e) => return Some(Err(e)),
}
}
None
}
}
impl<I, F> IntoIterator for FilterRow<I, F>
where
I: RowStream,
F: Fn(&Headers, &Row) -> bool,
{
type Item = RowResult;
type IntoIter = IntoIter<I::IntoIter, F>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter {
iter: self.iter.into_iter(),
f: self.f,
headers: self.headers,
}
}
}
impl<I, F> RowStream for FilterRow<I, F>
where
I: RowStream,
F: Fn(&Headers, &Row) -> bool,
{
fn headers(&self) -> &Headers {
&self.headers
}
}
#[cfg(test)]
mod tests {
use super::FilterRow;
use crate::{Row, MockStream, error};
#[test]
fn test_filter() {
let iter = MockStream::from_rows(
vec![
Ok(Row::from(vec!["a", "b"])),
Ok(Row::from(vec!["1", "2"])),
Ok(Row::from(vec!["2", "7"])),
Err(error::Error::InconsistentHeaders),
Ok(Row::from(vec!["1", "1"])),
Ok(Row::from(vec!["2", "9"])),
]
.into_iter(),
)
.unwrap();
let mut r = FilterRow::new(iter, |headers, row| {
headers.get_field(row, "b").unwrap().parse::<i32>().unwrap() > 2
})
.into_iter();
assert!(r.next().unwrap().is_ok());
assert!(r.next().unwrap().is_err());
assert!(r.next().unwrap().is_ok());
assert!(r.next().is_none());
}
}