fs_err/tokio/
mod.rs

1//! Tokio-specific wrappers that use `fs_err` error messages.
2
3use crate::errors::{Error, ErrorKind, SourceDestError, SourceDestErrorKind};
4use std::fs::{Metadata, Permissions};
5use std::path::{Path, PathBuf};
6use tokio::io;
7mod dir_builder;
8mod file;
9mod open_options;
10mod read_dir;
11
12pub use self::open_options::OpenOptions;
13pub use self::read_dir::{read_dir, DirEntry, ReadDir};
14pub use dir_builder::DirBuilder;
15pub use file::File;
16
17/// Returns the canonical, absolute form of a path with all intermediate
18/// components normalized and symbolic links resolved.
19///
20/// Wrapper for [`tokio::fs::canonicalize`].
21#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
22pub async fn canonicalize(path: impl AsRef<Path>) -> io::Result<PathBuf> {
23    let path = path.as_ref();
24    tokio::fs::canonicalize(path)
25        .await
26        .map_err(|err| Error::build(err, ErrorKind::Canonicalize, path))
27}
28
29/// Copies the contents of one file to another. This function will also copy the permission bits
30/// of the original file to the destination file.
31/// This function will overwrite the contents of to.
32///
33/// Wrapper for [`tokio::fs::copy`].
34#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
35pub async fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64, io::Error> {
36    let (from, to) = (from.as_ref(), to.as_ref());
37    tokio::fs::copy(from, to)
38        .await
39        .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::Copy, from, to))
40}
41
42/// Creates a new, empty directory at the provided path.
43///
44/// Wrapper for [`tokio::fs::create_dir`].
45#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
46pub async fn create_dir(path: impl AsRef<Path>) -> io::Result<()> {
47    let path = path.as_ref();
48    tokio::fs::create_dir(path)
49        .await
50        .map_err(|err| Error::build(err, ErrorKind::CreateDir, path))
51}
52
53/// Recursively creates a directory and all of its parent components if they
54/// are missing.
55///
56/// Wrapper for [`tokio::fs::create_dir_all`].
57#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
58pub async fn create_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
59    let path = path.as_ref();
60    tokio::fs::create_dir_all(path)
61        .await
62        .map_err(|err| Error::build(err, ErrorKind::CreateDir, path))
63}
64
65/// Creates a new hard link on the filesystem.
66///
67/// Wrapper for [`tokio::fs::hard_link`].
68#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
69pub async fn hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
70    let (src, dst) = (src.as_ref(), dst.as_ref());
71    tokio::fs::hard_link(src, dst)
72        .await
73        .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::HardLink, src, dst))
74}
75
76/// Given a path, queries the file system to get information about a file,
77/// directory, etc.
78///
79/// Wrapper for [`tokio::fs::metadata`].
80#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
81pub async fn metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
82    let path = path.as_ref();
83    tokio::fs::metadata(path)
84        .await
85        .map_err(|err| Error::build(err, ErrorKind::Metadata, path))
86}
87
88/// Reads the entire contents of a file into a bytes vector.
89///
90/// Wrapper for [`tokio::fs::read`].
91#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
92pub async fn read(path: impl AsRef<Path>) -> io::Result<Vec<u8>> {
93    let path = path.as_ref();
94    tokio::fs::read(path)
95        .await
96        .map_err(|err| Error::build(err, ErrorKind::Read, path))
97}
98
99/// Reads a symbolic link, returning the file that the link points to.
100///
101/// Wrapper for [`tokio::fs::read_link`].
102#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
103pub async fn read_link(path: impl AsRef<Path>) -> io::Result<PathBuf> {
104    let path = path.as_ref();
105    tokio::fs::read_link(path)
106        .await
107        .map_err(|err| Error::build(err, ErrorKind::ReadLink, path))
108}
109
110/// Creates a future which will open a file for reading and read the entire
111/// contents into a string and return said string.
112///
113/// Wrapper for [`tokio::fs::read_to_string`].
114#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
115pub async fn read_to_string(path: impl AsRef<Path>) -> io::Result<String> {
116    let path = path.as_ref();
117    tokio::fs::read_to_string(path)
118        .await
119        .map_err(|err| Error::build(err, ErrorKind::Read, path))
120}
121
122/// Removes an existing, empty directory.
123///
124/// Wrapper for [`tokio::fs::remove_dir`].
125#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
126pub async fn remove_dir(path: impl AsRef<Path>) -> io::Result<()> {
127    let path = path.as_ref();
128    tokio::fs::remove_dir(path)
129        .await
130        .map_err(|err| Error::build(err, ErrorKind::RemoveDir, path))
131}
132
133/// Removes a directory at this path, after removing all its contents. Use carefully!
134///
135/// Wrapper for [`tokio::fs::remove_dir_all`].
136#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
137pub async fn remove_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
138    let path = path.as_ref();
139    tokio::fs::remove_dir_all(path)
140        .await
141        .map_err(|err| Error::build(err, ErrorKind::RemoveDir, path))
142}
143
144/// Removes a file from the filesystem.
145///
146/// Wrapper for [`tokio::fs::remove_file`].
147#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
148pub async fn remove_file(path: impl AsRef<Path>) -> io::Result<()> {
149    let path = path.as_ref();
150    tokio::fs::remove_file(path)
151        .await
152        .map_err(|err| Error::build(err, ErrorKind::RemoveFile, path))
153}
154
155/// Renames a file or directory to a new name, replacing the original file if
156/// `to` already exists.
157///
158/// Wrapper for [`tokio::fs::rename`].
159#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
160pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
161    let (from, to) = (from.as_ref(), to.as_ref());
162    tokio::fs::rename(from, to)
163        .await
164        .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::Rename, from, to))
165}
166
167/// Changes the permissions found on a file or a directory.
168///
169/// Wrapper for [`tokio::fs::set_permissions`].
170#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
171pub async fn set_permissions(path: impl AsRef<Path>, perm: Permissions) -> io::Result<()> {
172    let path = path.as_ref();
173    tokio::fs::set_permissions(path, perm)
174        .await
175        .map_err(|err| Error::build(err, ErrorKind::SetPermissions, path))
176}
177
178/// Queries the file system metadata for a path.
179///
180/// Wrapper for [`tokio::fs::symlink_metadata`].
181#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
182pub async fn symlink_metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
183    let path = path.as_ref();
184    tokio::fs::symlink_metadata(path)
185        .await
186        .map_err(|err| Error::build(err, ErrorKind::SymlinkMetadata, path))
187}
188
189/// Creates a new symbolic link on the filesystem.
190///
191/// Wrapper for [`tokio::fs::symlink`].
192#[cfg(unix)]
193#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
194pub async fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
195    let (src, dst) = (src.as_ref(), dst.as_ref());
196    tokio::fs::symlink(src, dst)
197        .await
198        .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::Symlink, src, dst))
199}
200
201/// Creates a new directory symlink on the filesystem.
202///
203/// Wrapper for [`tokio::fs::symlink_dir`].
204#[cfg(windows)]
205#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
206#[deprecated = "use fs_err::tokio::symlink_dir instead"]
207pub async fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
208    symlink_dir(src, dst).await
209}
210
211/// Creates a new directory symlink on the filesystem.
212///
213/// Wrapper for [`tokio::fs::symlink_dir`].
214#[cfg(windows)]
215#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
216pub async fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
217    let (src, dst) = (src.as_ref(), dst.as_ref());
218    tokio::fs::symlink_dir(src, dst)
219        .await
220        .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::SymlinkDir, src, dst))
221}
222
223/// Creates a new file symbolic link on the filesystem.
224///
225/// Wrapper for [`tokio::fs::symlink_file`].
226#[cfg(windows)]
227#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
228pub async fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
229    let (src, dst) = (src.as_ref(), dst.as_ref());
230    tokio::fs::symlink_file(src, dst)
231        .await
232        .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::SymlinkFile, src, dst))
233}
234
235/// Creates a future that will open a file for writing and write the entire
236/// contents of `contents` to it.
237///
238/// Wrapper for [`tokio::fs::write`].
239#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
240pub async fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> io::Result<()> {
241    let (path, contents) = (path.as_ref(), contents.as_ref());
242    tokio::fs::write(path, contents)
243        .await
244        .map_err(|err| Error::build(err, ErrorKind::Write, path))
245}