/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.48.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.check_and_init()? { |
41 | | return write_uring(path, contents).await; |
42 | | } |
43 | | } |
44 | | |
45 | 0 | write_spawn_blocking(path, contents).await |
46 | 0 | } |
47 | | |
48 | | #[cfg(all( |
49 | | tokio_unstable, |
50 | | feature = "io-uring", |
51 | | feature = "rt", |
52 | | feature = "fs", |
53 | | target_os = "linux" |
54 | | ))] |
55 | | async fn write_uring(path: &Path, mut buf: OwnedBuf) -> io::Result<()> { |
56 | | use crate::{fs::OpenOptions, runtime::driver::op::Op}; |
57 | | use std::os::fd::OwnedFd; |
58 | | |
59 | | let file = OpenOptions::new() |
60 | | .write(true) |
61 | | .create(true) |
62 | | .truncate(true) |
63 | | .open(path) |
64 | | .await?; |
65 | | |
66 | | let mut fd: OwnedFd = file |
67 | | .try_into_std() |
68 | | .expect("unexpected in-flight operation detected") |
69 | | .into(); |
70 | | |
71 | | let total: usize = buf.as_ref().len(); |
72 | | let mut buf_offset: usize = 0; |
73 | | let mut file_offset: u64 = 0; |
74 | | while buf_offset < total { |
75 | | let (n, _buf, _fd) = Op::write_at(fd, buf, buf_offset, file_offset)?.await?; |
76 | | if n == 0 { |
77 | | return Err(io::ErrorKind::WriteZero.into()); |
78 | | } |
79 | | |
80 | | buf = _buf; |
81 | | fd = _fd; |
82 | | buf_offset += n as usize; |
83 | | file_offset += n as u64; |
84 | | } |
85 | | |
86 | | Ok(()) |
87 | | } |
88 | | |
89 | 0 | async fn write_spawn_blocking(path: &Path, contents: OwnedBuf) -> io::Result<()> { |
90 | 0 | let path = path.to_owned(); |
91 | 0 | asyncify(move || std::fs::write(path, contents)).await |
92 | 0 | } |