use crate::{Headers, Row, RowStream, RowResult, error};
pub struct MapRow<I, F> {
iter: I,
f: F,
old_headers: Headers,
headers: Headers,
}
impl<I, F, R> MapRow<I, F>
where
I: RowStream,
F: Fn(&Headers, &Row) -> error::Result<R>,
R: Iterator<Item = RowResult>,
{
pub fn new(
iter: I,
f: F,
headers: Headers,
) -> MapRow<I, F> {
let old_headers = iter.headers().clone();
MapRow {
iter,
f,
old_headers,
headers,
}
}
}
pub struct IntoIter<I, F, R>
where
I: Iterator<Item = RowResult>,
F: Fn(&Headers, &Row) -> error::Result<R>,
R: Iterator<Item = RowResult>,
{
iter: I,
f: F,
old_headers: Headers,
cur_item: Option<R>,
}
impl<I, F, R> Iterator for IntoIter<I, F, R>
where
I: Iterator<Item = RowResult>,
F: Fn(&Headers, &Row) -> error::Result<R>,
R: Iterator<Item = RowResult>,
{
type Item = RowResult;
fn next(&mut self) -> Option<Self::Item> {
match self.cur_item.as_mut() {
Some(iter) => match iter.next() {
Some(res) => Some(res),
None => {
self.cur_item = None;
self.next()
},
},
None => match self.iter.next() {
Some(row) => match row {
Ok(row) => match (self.f)(&self.old_headers, &row) {
Ok(stream) => {
self.cur_item = Some(stream.into_iter());
self.next()
},
Err(e) => {
Some(Err(e))
},
}
Err(e) => Some(Err(e)),
},
None => None,
},
}
}
}
impl<I, F, R> IntoIterator for MapRow<I, F>
where
I: RowStream,
F: Fn(&Headers, &Row) -> error::Result<R>,
R: Iterator<Item = RowResult>,
{
type Item = RowResult;
type IntoIter = IntoIter<I::IntoIter, F, R>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter {
iter: self.iter.into_iter(),
f: self.f,
old_headers: self.old_headers,
cur_item: None,
}
}
}
impl<I, F, R> RowStream for MapRow<I, F>
where
I: RowStream,
F: Fn(&Headers, &Row) -> error::Result<R>,
R: Iterator<Item = RowResult>,
{
fn headers(&self) -> &Headers {
&self.headers
}
}
#[cfg(test)]
mod tests {
use super::MapRow;
use crate::{Row, mock::MockStream, error, RowStream};
#[test]
fn test_row_transpose() {
let iter = MockStream::from_rows(
vec![
Ok(Row::from(vec!["a1", "a2"])),
Ok(Row::from(vec!["1", "2"])),
Err(error::Error::InconsistentHeaders),
Ok(Row::from(vec!["3", "4"])),
].into_iter(),
)
.unwrap();
let map_row = MapRow::new(iter, |headers, row| {
Ok(vec![
Ok(Row::from(vec![headers.get_field(row, "a1").unwrap()])),
Ok(Row::from(vec![headers.get_field(row, "a2").unwrap()])),
].into_iter())
}, Row::from(vec!["a"]).into());
assert_eq!(map_row.headers(), &Row::from(vec!["a"]).into());
let mut r = map_row.into_iter();
assert_eq!(r.next().unwrap().unwrap(), Row::from(vec!["1"]));
assert_eq!(r.next().unwrap().unwrap(), Row::from(vec!["2"]));
assert_eq!(r.next().unwrap().unwrap_err(), error::Error::InconsistentHeaders);
assert_eq!(r.next().unwrap().unwrap(), Row::from(vec!["3"]));
assert_eq!(r.next().unwrap().unwrap(), Row::from(vec!["4"]));
assert!(r.next().is_none());
}
}