use crate::{ Headers, RowStream, Row, error };
#[derive(Debug)]
pub enum BuildError {
DuplicatedHeader(String),
}
pub struct AddWith<I, F> {
iter: I,
f: F,
headers: Headers,
}
impl<I, F> AddWith<I, F>
where
I: RowStream,
F: FnMut(&Headers, &Row) -> error::Result<String>,
{
pub fn new(iter: I, colname: &str, f: F) -> Result<AddWith<I, F>, BuildError> {
let mut headers = iter.headers().clone();
if !headers.add(colname) {
return Err(BuildError::DuplicatedHeader(colname.to_string()));
}
Ok(AddWith{
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 = error::RowResult>,
F: FnMut(&Headers, &Row) -> error::Result<String>,
{
type Item = error::RowResult;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|result| {
result.and_then(|mut val| {
match (self.f)(&self.headers, &val) {
Ok(s) => val.push_field(&s),
Err(e) => return Err(e),
}
Ok(val)
})
})
}
}
impl<I, F> IntoIterator for AddWith<I, F>
where
I: RowStream,
F: FnMut(&Headers, &Row) -> error::Result<String>,
{
type Item = error::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 AddWith<I, F>
where
I: RowStream,
F: FnMut(&Headers, &Row) -> error::Result<String>,
{
fn headers(&self) -> &Headers {
&self.headers
}
}
#[cfg(test)]
mod tests {
use super::{AddWith, Row, RowStream};
use crate::mock::MockStream;
#[test]
fn test_add() {
let iter = MockStream::from_rows(
vec![
Ok(Row::from(vec!["id"])),
Ok(Row::from(vec!["1"])),
Ok(Row::from(vec!["2"])),
Ok(Row::from(vec!["3"])),
Ok(Row::from(vec!["4"])),
]
.into_iter(),
)
.unwrap();
let add= AddWith::new(
iter,
"col",
|headers, row| {
let v: i32 = headers.get_field(row, "id").unwrap().parse().unwrap();
Ok((v*v).to_string())
}
).unwrap();
assert_eq!(
*add.headers(),
Row::from(vec!["id", "col"]).into(),
);
let mut add= add.into_iter();
assert_eq!(
add.next().unwrap().unwrap(),
Row::from(vec!["1", "1"])
);
assert_eq!(
add.next().unwrap().unwrap(),
Row::from(vec!["2", "4"])
);
assert_eq!(
add.next().unwrap().unwrap(),
Row::from(vec!["3", "9"])
);
assert_eq!(
add.next().unwrap().unwrap(),
Row::from(vec!["4", "16"])
);
}
}