use crate::errors::{Error, ErrorKind}; use std::ffi::OsString; use std::fs::{FileType, Metadata}; use std::io; use std::path::{Path, PathBuf}; use std::task::{ready, Context, Poll}; use tokio::fs; /// Wrapper for [`tokio::fs::read_dir`]. #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] pub async fn read_dir(path: impl AsRef) -> io::Result { let path = path.as_ref(); let tokio = fs::read_dir(path) .await .map_err(|err| Error::build(err, ErrorKind::ReadDir, path))?; Ok(ReadDir { tokio, path: path.to_owned(), }) } /// Reads the entries in a directory. /// /// This is a wrapper around [`tokio::fs::ReadDir`]. #[derive(Debug)] #[must_use = "streams do nothing unless polled"] #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] pub struct ReadDir { tokio: fs::ReadDir, path: PathBuf, } impl ReadDir { /// Wrapper around [`tokio::fs::ReadDir::next_entry`]. pub async fn next_entry(&mut self) -> io::Result> { match self.tokio.next_entry().await { Ok(entry) => Ok(entry.map(|e| DirEntry { tokio: e })), Err(err) => Err(Error::build(err, ErrorKind::ReadDir, &self.path)), } } /// Wrapper around [`tokio::fs::ReadDir::poll_next_entry`]. pub fn poll_next_entry(&mut self, cx: &mut Context<'_>) -> Poll>> { Poll::Ready(match ready!(self.tokio.poll_next_entry(cx)) { Ok(entry) => Ok(entry.map(|e| DirEntry { tokio: e })), Err(err) => Err(Error::build(err, ErrorKind::ReadDir, &self.path)), }) } } /// Entries returned by the [`ReadDir`] stream. /// /// This is a wrapper around [`tokio::fs::DirEntry`]. #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))] pub struct DirEntry { tokio: fs::DirEntry, } impl DirEntry { /// Wrapper around [`tokio::fs::DirEntry::path`]. pub fn path(&self) -> PathBuf { self.tokio.path() } /// Wrapper around [`tokio::fs::DirEntry::file_name`]. pub fn file_name(&self) -> OsString { self.tokio.file_name() } /// Wrapper around [`tokio::fs::DirEntry::metadata`]. pub async fn metadata(&self) -> io::Result { self.tokio .metadata() .await .map_err(|err| Error::build(err, ErrorKind::Metadata, self.path())) } /// Wrapper around [`tokio::fs::DirEntry::file_type`]. pub async fn file_type(&self) -> io::Result { self.tokio .file_type() .await .map_err(|err| Error::build(err, ErrorKind::Metadata, self.path())) } } #[cfg(unix)] impl DirEntry { /// Wrapper around [`tokio::fs::DirEntry::ino`]. pub fn ino(&self) -> u64 { self.tokio.ino() } }