/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.50.0/src/fs/write.rs
Line | Count | Source |
1 | | use crate::{fs::asyncify, util::as_ref::OwnedBuf}; |
2 | | |
3 | | use std::{io, path::Path}; |
4 | | |
5 | | /// Creates a future that will open a file for writing and write the entire |
6 | | /// contents of `contents` to it. |
7 | | /// |
8 | | /// This is the async equivalent of [`std::fs::write`][std]. |
9 | | /// |
10 | | /// This operation is implemented by running the equivalent blocking operation |
11 | | /// on a separate thread pool using [`spawn_blocking`]. |
12 | | /// |
13 | | /// [`spawn_blocking`]: crate::task::spawn_blocking |
14 | | /// [std]: fn@std::fs::write |
15 | | /// |
16 | | /// # Examples |
17 | | /// |
18 | | /// ```no_run |
19 | | /// use tokio::fs; |
20 | | /// |
21 | | /// # async fn dox() -> std::io::Result<()> { |
22 | | /// fs::write("foo.txt", b"Hello world!").await?; |
23 | | /// # Ok(()) |
24 | | /// # } |
25 | | /// ``` |
26 | 0 | pub async fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> io::Result<()> { |
27 | 0 | let path = path.as_ref(); |
28 | 0 | let contents = crate::util::as_ref::upgrade(contents); |
29 | | |
30 | | #[cfg(all( |
31 | | tokio_unstable, |
32 | | feature = "io-uring", |
33 | | feature = "rt", |
34 | | feature = "fs", |
35 | | target_os = "linux" |
36 | | ))] |
37 | | { |
38 | | let handle = crate::runtime::Handle::current(); |
39 | | let driver_handle = handle.inner.driver().io(); |
40 | | if driver_handle |
41 | | .check_and_init(io_uring::opcode::Write::CODE) |
42 | | .await? |
43 | | { |
44 | | return write_uring(path, contents).await; |
45 | | } |
46 | | } |
47 | | |
48 | 0 | write_spawn_blocking(path, contents).await |
49 | 0 | } |
50 | | |
51 | | #[cfg(all( |
52 | | tokio_unstable, |
53 | | feature = "io-uring", |
54 | | feature = "rt", |
55 | | feature = "fs", |
56 | | target_os = "linux" |
57 | | ))] |
58 | | async fn write_uring(path: &Path, mut buf: OwnedBuf) -> io::Result<()> { |
59 | | use crate::{fs::OpenOptions, runtime::driver::op::Op}; |
60 | | use std::os::fd::OwnedFd; |
61 | | |
62 | | let file = OpenOptions::new() |
63 | | .write(true) |
64 | | .create(true) |
65 | | .truncate(true) |
66 | | .open(path) |
67 | | .await?; |
68 | | |
69 | | let mut fd: OwnedFd = file |
70 | | .try_into_std() |
71 | | .expect("unexpected in-flight operation detected") |
72 | | .into(); |
73 | | |
74 | | let total: usize = buf.as_ref().len(); |
75 | | let mut buf_offset: usize = 0; |
76 | | let mut file_offset: u64 = 0; |
77 | | while buf_offset < total { |
78 | | let (res, _buf, _fd) = Op::write_at(fd, buf, buf_offset, file_offset)?.await; |
79 | | |
80 | | let n = match res { |
81 | | Ok(0) => return Err(io::ErrorKind::WriteZero.into()), |
82 | | Ok(n) => n, |
83 | | Err(e) if e.kind() == io::ErrorKind::Interrupted => 0, |
84 | | Err(e) => return Err(e), |
85 | | }; |
86 | | |
87 | | buf = _buf; |
88 | | fd = _fd; |
89 | | buf_offset += n as usize; |
90 | | file_offset += n as u64; |
91 | | } |
92 | | |
93 | | Ok(()) |
94 | | } |
95 | | |
96 | 0 | async fn write_spawn_blocking(path: &Path, contents: OwnedBuf) -> io::Result<()> { |
97 | 0 | let path = path.to_owned(); |
98 | 0 | asyncify(move || std::fs::write(path, contents)).await |
99 | 0 | } |