tools/fs: add FileIterOps trait and FileTypeFilter

FileIterOps will provide operations on file entry iterators.
For now this provides a file type filter.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-02-13 13:51:29 +01:00
parent 1db416150d
commit 23fba9d777
1 changed files with 63 additions and 1 deletions

View File

@ -4,7 +4,7 @@ use std::borrow::{Borrow, BorrowMut};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use failure::Error; use failure::*;
use nix::dir; use nix::dir;
use nix::dir::Dir; use nix::dir::Dir;
@ -125,3 +125,65 @@ pub fn scan_subdir<'a, P: ?Sized + nix::NixPath>(
} }
})) }))
} }
/// Helper trait to provide a combinators for directory entry iterators.
pub trait FileIterOps<T, E>
where
Self: Sized + Iterator<Item = Result<T, E>>,
T: Borrow<dir::Entry>,
E: Into<Error> + Send + Sync,
{
/// Filter by file type. This is more convenient than using the `filter` method alone as this
/// also includes error handling and handling of files without a type (via an error).
fn filter_file_type(self, ty: dir::Type) -> FileTypeFilter<Self, T, E> {
FileTypeFilter { inner: self, ty }
}
}
impl<I, T, E> FileIterOps<T, E> for I
where
I: Iterator<Item = Result<T, E>>,
T: Borrow<dir::Entry>,
E: Into<Error> + Send + Sync,
{
}
/// This filters files from its inner iterator by a file type. Files with no type produce an error.
pub struct FileTypeFilter<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
T: Borrow<dir::Entry>,
E: Into<Error> + Send + Sync,
{
inner: I,
ty: nix::dir::Type,
}
impl<I, T, E> Iterator for FileTypeFilter<I, T, E>
where
I: Iterator<Item = Result<T, E>>,
T: Borrow<dir::Entry>,
E: Into<Error> + Send + Sync,
{
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let item = self.inner.next()?.map_err(|e| e.into());
match item {
Ok(ref entry) => match entry.borrow().file_type() {
Some(ty) => {
if ty == self.ty {
return Some(item);
} else {
continue;
}
}
None => return Some(Err(format_err!("unable to detect file type"))),
},
Err(_) => return Some(item),
}
}
}
}