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:
		@ -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),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user