1 use crate::errors::{Error, ErrorKind};
2 use std::ffi::OsString;
3 use std::fs::{FileType, Metadata};
4 use std::io;
5 use std::path::{Path, PathBuf};
6 use std::task::{ready, Context, Poll};
7 use 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")))]
read_dir(path: impl AsRef<Path>) -> io::Result<ReadDir>13 pub 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")))]
30 pub struct ReadDir {
31 tokio: fs::ReadDir,
32 path: PathBuf,
33 }
34
35 impl ReadDir {
36 /// Returns the next entry in the directory stream.
37 ///
38 /// Wrapper around [`tokio::fs::ReadDir::next_entry`].
next_entry(&mut self) -> io::Result<Option<DirEntry>>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`].
poll_next_entry(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>>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")))]
62 pub struct DirEntry {
63 tokio: fs::DirEntry,
64 }
65
66 impl DirEntry {
67 /// Returns the full path to the file that this entry represents.
68 ///
69 /// Wrapper around [`tokio::fs::DirEntry::path`].
path(&self) -> PathBuf70 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`].
file_name(&self) -> OsString78 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`].
metadata(&self) -> io::Result<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`].
file_type(&self) -> io::Result<FileType>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)]
104 impl DirEntry {
105 /// Returns the underlying `d_ino` field in the contained `dirent` structure.
106 ///
107 /// Wrapper around [`tokio::fs::DirEntry::ino`].
ino(&self) -> u64108 pub fn ino(&self) -> u64 {
109 self.tokio.ino()
110 }
111 }
112