fs_err/tokio/
read_dir.rs

1use crate::errors::{Error, ErrorKind};
2use std::ffi::OsString;
3use std::fs::{FileType, Metadata};
4use std::io;
5use std::path::{Path, PathBuf};
6use std::task::{ready, Context, Poll};
7use tokio::fs;
8
9/// Returns a stream over the entries within a directory.
10///
11/// Wrapper for [`tokio::fs::read_dir`].
12#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
13pub async fn read_dir(path: impl AsRef<Path>) -> io::Result<ReadDir> {
14    let path = path.as_ref();
15    let tokio = fs::read_dir(path)
16        .await
17        .map_err(|err| Error::build(err, ErrorKind::ReadDir, path))?;
18    Ok(ReadDir {
19        tokio,
20        path: path.to_owned(),
21    })
22}
23
24/// Reads the entries in a directory.
25///
26/// This is a wrapper around [`tokio::fs::ReadDir`].
27#[derive(Debug)]
28#[must_use = "streams do nothing unless polled"]
29#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
30pub struct ReadDir {
31    tokio: fs::ReadDir,
32    path: PathBuf,
33}
34
35impl ReadDir {
36    /// Returns the next entry in the directory stream.
37    ///
38    /// Wrapper around [`tokio::fs::ReadDir::next_entry`].
39    pub async fn next_entry(&mut self) -> io::Result<Option<DirEntry>> {
40        match self.tokio.next_entry().await {
41            Ok(entry) => Ok(entry.map(|e| DirEntry { tokio: e })),
42            Err(err) => Err(Error::build(err, ErrorKind::ReadDir, &self.path)),
43        }
44    }
45
46    /// Polls for the next directory entry in the stream.
47    ///
48    /// Wrapper around [`tokio::fs::ReadDir::poll_next_entry`].
49    pub fn poll_next_entry(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>> {
50        Poll::Ready(match ready!(self.tokio.poll_next_entry(cx)) {
51            Ok(entry) => Ok(entry.map(|e| DirEntry { tokio: e })),
52            Err(err) => Err(Error::build(err, ErrorKind::ReadDir, &self.path)),
53        })
54    }
55}
56
57/// Entries returned by the [`ReadDir`] stream.
58///
59/// This is a wrapper around [`tokio::fs::DirEntry`].
60#[derive(Debug)]
61#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
62pub struct DirEntry {
63    tokio: fs::DirEntry,
64}
65
66impl DirEntry {
67    /// Returns the full path to the file that this entry represents.
68    ///
69    /// Wrapper around [`tokio::fs::DirEntry::path`].
70    pub fn path(&self) -> PathBuf {
71        self.tokio.path()
72    }
73
74    /// Returns the bare file name of this directory entry without any other
75    /// leading path component.
76    ///
77    /// Wrapper around [`tokio::fs::DirEntry::file_name`].
78    pub fn file_name(&self) -> OsString {
79        self.tokio.file_name()
80    }
81
82    /// Returns the metadata for the file that this entry points at.
83    ///
84    /// Wrapper around [`tokio::fs::DirEntry::metadata`].
85    pub async fn metadata(&self) -> io::Result<Metadata> {
86        self.tokio
87            .metadata()
88            .await
89            .map_err(|err| Error::build(err, ErrorKind::Metadata, self.path()))
90    }
91
92    /// Returns the file type for the file that this entry points at.
93    ///
94    /// Wrapper around [`tokio::fs::DirEntry::file_type`].
95    pub async fn file_type(&self) -> io::Result<FileType> {
96        self.tokio
97            .file_type()
98            .await
99            .map_err(|err| Error::build(err, ErrorKind::Metadata, self.path()))
100    }
101}
102
103#[cfg(unix)]
104impl DirEntry {
105    /// Returns the underlying `d_ino` field in the contained `dirent` structure.
106    ///
107    /// Wrapper around [`tokio::fs::DirEntry::ino`].
108    pub fn ino(&self) -> u64 {
109        self.tokio.ino()
110    }
111}