use crate::{MapOk, MapOkIter};
pub trait BoxOk<T, E>: Sized {
type Iter: Iterator<Item = Result<Box<T>, E>>;
fn box_ok(self) -> Self::Iter;
}
pub type BoxingFn<T> = fn(T) -> Box<T>;
impl<I, T, E> BoxOk<T, E> for I
where
I: Iterator<Item = Result<T, E>>,
{
type Iter = MapOkIter<Self, T, E, Box<T>, BoxingFn<T>>;
fn box_ok(self) -> Self::Iter {
self.map_ok(Box::new)
}
}
#[cfg(test)]
mod tests {
use std::num::ParseIntError;
use std::str::FromStr;
use super::*;
struct Person {
age: u8,
}
impl Person {
fn new(age: u8) -> Self {
Person { age }
}
}
impl FromStr for Person {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let age = u8::from_str(s)?;
Ok(Person::new(age))
}
}
#[test]
fn map_ok_works() {
let input = ["10", "20", "x", "30"];
let mut iterator = input
.iter()
.map(|s| s.parse::<Person>())
.map_ok(|p| p.age)
.box_ok();
assert_eq!(iterator.next(), Some(Ok(Box::new(10))));
assert_eq!(iterator.next(), Some(Ok(Box::new(20))));
assert!(iterator.next().unwrap().is_err());
assert_eq!(iterator.next(), Some(Ok(Box::new(30))));
assert_eq!(iterator.next(), None);
}
#[test]
fn naive() {
let input = ["10", "20", "x", "30"];
let results: Vec<Result<Box<u32>, ParseIntError>> = input
.into_iter()
.map(u32::from_str)
.map_ok(|x| x * 100)
.box_ok()
.collect();
assert_eq!(results.len(), 4);
}
#[test]
fn naive2() {
let input = ["10", "20", "x", "30"];
let results: Vec<Result<Box<u32>, ParseIntError>> = input
.into_iter()
.map(u32::from_str)
.map_ok(|x| x * 100)
.map_ok(Box::new)
.collect();
assert_eq!(results.len(), 4);
}
}