use super::{DirEntryInfo, Transport, TransportError};
#[derive(Debug, Clone)]
pub struct WalkedDir {
pub relpath: Vec<u8>,
pub abspath: Vec<u8>,
pub entries: Vec<DirEntryInfo>,
}
#[derive(Debug)]
pub struct WalkDirsUtf8 {
pub pending: Vec<(Vec<u8>, Vec<u8>)>,
pub pending_subdirs: Vec<(Vec<u8>, Vec<u8>)>,
}
impl WalkDirsUtf8 {
pub fn new(root_abspath: &[u8], prefix: &[u8]) -> Self {
Self {
pending: vec![(prefix.to_vec(), root_abspath.to_vec())],
pending_subdirs: Vec::new(),
}
}
pub fn next_dir<F>(
&mut self,
transport: &dyn Transport,
mut callback: F,
) -> Result<bool, TransportError>
where
F: FnMut(&[u8], &[u8], &mut Vec<DirEntryInfo>),
{
for entry in self.pending_subdirs.drain(..).rev() {
self.pending.push(entry);
}
let (relpath, abspath) = match self.pending.pop() {
Some(v) => v,
None => return Ok(false),
};
let mut entries = transport.list_dir(&abspath)?;
entries.sort_by(|a, b| a.basename.cmp(&b.basename));
callback(&relpath, &abspath, &mut entries);
self.pending_subdirs = entries
.iter()
.filter(|e| e.kind == Some(crate::osutils::Kind::Directory))
.map(|e| {
let mut child_relpath = relpath.clone();
if !child_relpath.is_empty() {
child_relpath.push(b'/');
}
child_relpath.extend_from_slice(&e.basename);
(child_relpath, e.abspath.clone())
})
.collect();
Ok(true)
}
}