macro_rules! impl_result_iter {
($target:ident, $item:ident) => {
impl Iterator for $target {
type Item = Result<$item, Ext4Error>;
fn next(&mut self) -> Option<Result<$item, Ext4Error>> {
loop {
if self.is_done {
return None;
}
match self.next_impl() {
Ok(Some(entry)) => return Some(Ok(entry)),
Ok(None) => {
}
Err(err) => {
self.is_done = true;
return Some(Err(err));
}
}
}
}
}
};
}
pub(crate) mod extents;
pub(crate) mod file_blocks;
pub(crate) mod read_dir;
#[cfg(test)]
mod tests {
use crate::error::{CorruptKind, Ext4Error};
struct I {
items: Vec<Result<Option<u8>, Ext4Error>>,
is_done: bool,
}
impl I {
fn next_impl(&mut self) -> Result<Option<u8>, Ext4Error> {
self.items.remove(0)
}
}
impl_result_iter!(I, u8);
#[test]
fn test_iter_macro_none() {
let mut iter = I {
items: vec![Ok(Some(1)), Ok(None), Ok(Some(2))],
is_done: false,
};
assert_eq!(iter.next().unwrap().unwrap(), 1);
assert_eq!(iter.next().unwrap().unwrap(), 2);
}
#[test]
fn test_iter_macro_error() {
let mut iter = I {
items: vec![
Ok(Some(1)),
Err(CorruptKind::SuperblockMagic.into()),
Ok(Some(2)),
],
is_done: false,
};
assert_eq!(iter.next().unwrap().unwrap(), 1);
assert_eq!(
iter.next().unwrap().unwrap_err(),
CorruptKind::SuperblockMagic
);
assert!(iter.next().is_none());
}
#[test]
fn test_iter_macro_is_done() {
let mut iter = I {
items: vec![Ok(Some(1)), Ok(Some(2))],
is_done: false,
};
assert_eq!(iter.next().unwrap().unwrap(), 1);
iter.is_done = true;
assert!(iter.next().is_none());
}
}