1 2 3 4 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
use crate::{MapOk, MapOkIter};
/// Represents an iterator that boxes the Ok values.
///
/// This trait is implemented for iterators over `Result<T, E>`, allowing them to box
/// the Ok values using the `Box<T>` type.
///
/// # Implementations
///
/// Implementations of this trait must provide an implementation for the `box_ok` function, which
/// returns a `MapOk` iterator that boxes each Ok value encountered during iteration.
///
/// # Examples
///
/// ```
/// use std::num::ParseIntError;
/// use std::str::FromStr;
/// use map_ok::{BoxOk, MapOk};
///
/// 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))
/// }
/// }
///
/// let input = vec!["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);
/// ```
pub trait BoxOk<T, E>: Sized {
type Iter: Iterator<Item = Result<Box<T>, E>>;
fn box_ok(self) -> Self::Iter;
}
/// A function that boxes its argument.
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 super::*;
use std::num::ParseIntError;
use std::str::FromStr;
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);
}
}