1#![cfg(not(loom))]
2
3//! Asynchronous file and standard stream adaptation.
4//!
5//! This module contains utility methods and adapter types for input/output to
6//! files or standard streams (`Stdin`, `Stdout`, `Stderr`), and
7//! filesystem manipulation, for use within (and only within) a Tokio runtime.
8//!
9//! Tasks run by *worker* threads should not block, as this could delay
10//! servicing reactor events. Portable filesystem operations are blocking,
11//! however. This module offers adapters which use a `blocking` annotation
12//! to inform the runtime that a blocking operation is required. When
13//! necessary, this allows the runtime to convert the current thread from a
14//! *worker* to a *backup* thread, where blocking is acceptable.
15//!
16//! ## Usage
17//!
18//! Where possible, users should prefer the provided asynchronous-specific
19//! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll`
20//! type. Adaptions also extend to traits like `std::io::Read` where methods
21//! return `std::io::Result`. Be warned that these adapted methods may return
22//! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted
23//! to a *backup* thread immediately.
24//!
25//! **Warning**: These adapters may create a large number of temporary tasks,
26//! especially when reading large files. When performing a lot of operations
27//! in one batch, it may be significantly faster to use [`spawn_blocking`]
28//! directly:
29//!
30//! ```
31//! use tokio::fs::File;
32//! use std::io::{BufReader, BufRead};
33//! async fn count_lines(file: File) -> Result<usize, std::io::Error> {
34//! let file = file.into_std().await;
35//! tokio::task::spawn_blocking(move || {
36//! let line_count = BufReader::new(file).lines().count();
37//! Ok(line_count)
38//! }).await?
39//! }
40//! ```
41//!
42//! [`spawn_blocking`]: fn@crate::task::spawn_blocking
43//! [`AsyncRead`]: trait@crate::io::AsyncRead
44
45mod canonicalize;
46pub use self::canonicalize::canonicalize;
47
48mod create_dir;
49pub use self::create_dir::create_dir;
50
51mod create_dir_all;
52pub use self::create_dir_all::create_dir_all;
53
54mod dir_builder;
55pub use self::dir_builder::DirBuilder;
56
57mod file;
58pub use self::file::File;
59
60mod hard_link;
61pub use self::hard_link::hard_link;
62
63mod metadata;
64pub use self::metadata::metadata;
65
66mod open_options;
67pub use self::open_options::OpenOptions;
68
69mod read;
70pub use self::read::read;
71
72mod read_dir;
73pub use self::read_dir::{read_dir, DirEntry, ReadDir};
74
75mod read_link;
76pub use self::read_link::read_link;
77
78mod read_to_string;
79pub use self::read_to_string::read_to_string;
80
81mod remove_dir;
82pub use self::remove_dir::remove_dir;
83
84mod remove_dir_all;
85pub use self::remove_dir_all::remove_dir_all;
86
87mod remove_file;
88pub use self::remove_file::remove_file;
89
90mod rename;
91pub use self::rename::rename;
92
93mod set_permissions;
94pub use self::set_permissions::set_permissions;
95
96mod symlink_metadata;
97pub use self::symlink_metadata::symlink_metadata;
98
99mod write;
100pub use self::write::write;
101
102mod copy;
103pub use self::copy::copy;
104
105mod try_exists;
106pub use self::try_exists::try_exists;
107
108#[cfg(test)]
109mod mocks;
110
111feature! {
112 #![unix]
113
114 mod symlink;
115 pub use self::symlink::symlink;
116}
117
118cfg_windows! {
119 mod symlink_dir;
120 pub use self::symlink_dir::symlink_dir;
121
122 mod symlink_file;
123 pub use self::symlink_file::symlink_file;
124}
125
126use std::io;
127
128#[cfg(not(test))]
129use crate::blocking::spawn_blocking;
130#[cfg(test)]
131use mocks::spawn_blocking;
132
133pub(crate) async fn asyncify<F, T>(f: F) -> io::Result<T>
134where
135 F: FnOnce() -> io::Result<T> + Send + 'static,
136 T: Send + 'static,
137{
138 match spawn_blocking(func:f).await {
139 Ok(res: Result) => res,
140 Err(_) => Err(io::Error::new(
141 kind:io::ErrorKind::Other,
142 error:"background task failed",
143 )),
144 }
145}
146