use std::fs::ReadDir;
use std::path::Path;
use std::sync::Arc;
use super::core::CompfsCore;
use crate::raw::*;
use crate::*;
#[derive(Debug)]
pub struct CompfsLister {
core: Arc<CompfsCore>,
read_dir: Option<ReadDir>,
}
impl CompfsLister {
pub(super) fn new(core: Arc<CompfsCore>, read_dir: ReadDir) -> Self {
Self {
core,
read_dir: Some(read_dir),
}
}
}
fn next_entry(read_dir: &mut ReadDir, root: &Path) -> std::io::Result<Option<oio::Entry>> {
let Some(entry) = read_dir.next().transpose()? else {
return Ok(None);
};
let path = entry.path();
let rel_path = normalize_path(
&path
.strip_prefix(root)
.expect("cannot fail because the prefix is iterated")
.to_string_lossy()
.replace('\\', "/"),
);
let file_type = entry.file_type()?;
let entry = if file_type.is_file() {
oio::Entry::new(&rel_path, Metadata::new(EntryMode::FILE))
} else if file_type.is_dir() {
oio::Entry::new(&format!("{rel_path}/"), Metadata::new(EntryMode::DIR))
} else {
oio::Entry::new(&rel_path, Metadata::new(EntryMode::Unknown))
};
Ok(Some(entry))
}
impl oio::List for CompfsLister {
async fn next(&mut self) -> Result<Option<oio::Entry>> {
let Some(mut read_dir) = self.read_dir.take() else {
return Ok(None);
};
let root = self.core.root.clone();
let (entry, read_dir) = self
.core
.exec_blocking(move || {
let entry = next_entry(&mut read_dir, &root).map_err(new_std_io_error);
(entry, read_dir)
})
.await?;
self.read_dir = Some(read_dir);
entry
}
}