use core::marker::PhantomData;
use crate::{OrStash, StashedResult};
#[cfg_attr(
any(feature = "rust-v1.81", feature = "std"),
doc = r##"
[`prelude::Stashable`]: crate::prelude::Stashable
"##
)]
#[cfg_attr(
not(any(feature = "rust-v1.81", feature = "std")),
doc = r##"
[`prelude::Stashable`]: crate::surrogate_error_trait::prelude::Stashable
"##
)]
pub trait StashErr<T, E, S, I>: Iterator<Item = Result<T, E>>
where
E: Into<I>,
{
fn stash_err(self, stash: &mut S) -> StashErrIter<Self, T, E, S, I>
where
Self: Sized,
{
StashErrIter {
iter: self,
stash,
_unused: PhantomData,
}
}
}
impl<Iter, T, E, S, I> StashErr<T, E, S, I> for Iter
where
Iter: Iterator<Item = Result<T, E>>,
E: Into<I>,
{
}
pub struct StashErrIter<'a, Iter, T, E, S, I>
where
Iter: Iterator<Item = Result<T, E>>,
{
iter: Iter,
stash: &'a mut S,
_unused: PhantomData<I>,
}
impl<Iter, T, E, S, I> Iterator for StashErrIter<'_, Iter, T, E, S, I>
where
Iter: Iterator<Item = Result<T, E>>,
Iter::Item: OrStash<S, I, T>,
E: Into<I>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.iter.next() {
Some(result) => match result.or_stash(self.stash) {
StashedResult::Err(_) => continue,
StashedResult::Ok(t) => return Some(t),
},
None => return None,
};
}
}
}
#[cfg(test)]
mod tests {
use core::str::FromStr;
use alloc::vec::Vec;
#[cfg(any(feature = "rust-v1.81", feature = "std"))]
use crate::prelude::*;
#[cfg(not(any(feature = "rust-v1.81", feature = "std")))]
use crate::surrogate_error_trait::prelude::*;
#[test]
fn stash_err_has_correct_backtrace() {
let mut errs = ErrorStash::new(|| "There were one or more errors");
let _: Vec<u8> = vec!["not a number"]
.into_iter()
.map(u8::from_str)
.stash_err(&mut errs)
.collect();
let err: Error = errs.into_result().unwrap_err();
let msg = crate::doctest_line_num_helper(&format!("{err:#}"));
assert_eq!(&msg, indoc::indoc! {"
There were one or more errors
- invalid digit found in string
at src/stash_err.rs:1234:56"});
}
}