async_fs_io/
async_file.rs1use std::io::SeekFrom;
4use std::path::{Path, PathBuf};
5use std::pin::Pin;
6use std::task::{Context, Poll};
7
8use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeekExt, AsyncWrite, AsyncWriteExt, ReadBuf};
9
10use crate::{FsError, Operation};
11
12pub struct AsyncFile {
15 inner: tokio::fs::File,
16 path: PathBuf,
17}
18
19impl AsyncFile {
20 pub async fn open(path: impl AsRef<Path>) -> Result<Self, FsError> {
22 let path = path.as_ref().to_owned();
23 let inner = tokio::fs::File::open(&path)
24 .await
25 .map_err(|error| FsError::io(Operation::Read, &path, error))?;
26 Ok(Self { inner, path })
27 }
28
29 pub async fn open_if_exists(path: impl AsRef<Path>) -> Result<Option<Self>, FsError> {
31 let path = path.as_ref().to_owned();
32 match tokio::fs::File::open(&path).await {
33 Ok(inner) => Ok(Some(Self { inner, path })),
34 Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(None),
35 Err(error) => Err(FsError::io(Operation::Read, &path, error)),
36 }
37 }
38
39 pub async fn create(path: impl AsRef<Path>) -> Result<Self, FsError> {
41 let path = path.as_ref().to_owned();
42 let inner = tokio::fs::File::create(&path)
43 .await
44 .map_err(|error| FsError::io(Operation::Write, &path, error))?;
45 Ok(Self { inner, path })
46 }
47
48 pub async fn create_new(path: impl AsRef<Path>) -> Result<Self, FsError> {
50 let path = path.as_ref().to_owned();
51 let inner = tokio::fs::OpenOptions::new()
52 .write(true)
53 .create_new(true)
54 .open(&path)
55 .await
56 .map_err(|error| FsError::io(Operation::Write, &path, error))?;
57 Ok(Self { inner, path })
58 }
59
60 pub async fn open_append(path: impl AsRef<Path>) -> Result<Self, FsError> {
62 let path = path.as_ref().to_owned();
63 let inner = tokio::fs::OpenOptions::new()
64 .create(true)
65 .append(true)
66 .read(true)
67 .open(&path)
68 .await
69 .map_err(|error| FsError::io(Operation::Write, &path, error))?;
70 Ok(Self { inner, path })
71 }
72
73 pub async fn open_write_at_end(path: impl AsRef<Path>) -> Result<Self, FsError> {
75 let path = path.as_ref().to_owned();
76 let mut inner = tokio::fs::OpenOptions::new()
77 .create(true)
78 .read(true)
79 .write(true)
80 .truncate(false)
81 .open(&path)
82 .await
83 .map_err(|error| FsError::io(Operation::Write, &path, error))?;
84 inner
85 .seek(SeekFrom::End(0))
86 .await
87 .map_err(|error| FsError::io(Operation::Write, &path, error))?;
88 Ok(Self { inner, path })
89 }
90
91 pub async fn read_exact(&mut self, buffer: &mut [u8]) -> Result<(), FsError> {
93 self.inner
94 .read_exact(buffer)
95 .await
96 .map(|_| ())
97 .map_err(|error| FsError::io(Operation::Read, &self.path, error))
98 }
99
100 pub async fn write_all(&mut self, buffer: &[u8]) -> Result<(), FsError> {
102 self.inner
103 .write_all(buffer)
104 .await
105 .map_err(|error| FsError::io(Operation::Write, &self.path, error))
106 }
107
108 pub async fn flush(&mut self) -> Result<(), FsError> {
110 self.inner
111 .flush()
112 .await
113 .map_err(|error| FsError::io(Operation::Write, &self.path, error))
114 }
115
116 pub async fn sync_all(&self) -> Result<(), FsError> {
118 self.inner
119 .sync_all()
120 .await
121 .map_err(|error| FsError::io(Operation::Write, &self.path, error))
122 }
123
124 pub async fn sync_data(&self) -> Result<(), FsError> {
127 self.inner
128 .sync_data()
129 .await
130 .map_err(|error| FsError::io(Operation::Write, &self.path, error))
131 }
132
133 pub async fn seek(&mut self, position: SeekFrom) -> Result<u64, FsError> {
135 self.inner
136 .seek(position)
137 .await
138 .map_err(|error| FsError::io(Operation::Read, &self.path, error))
139 }
140
141 pub async fn stream_position(&mut self) -> Result<u64, FsError> {
143 self.seek(SeekFrom::Current(0)).await
144 }
145
146 pub async fn metadata(&self) -> Result<std::fs::Metadata, FsError> {
148 self.inner
149 .metadata()
150 .await
151 .map_err(|error| FsError::io(Operation::Read, &self.path, error))
152 }
153
154 pub async fn set_len(&self, length: u64) -> Result<(), FsError> {
156 self.inner
157 .set_len(length)
158 .await
159 .map_err(|error| FsError::io(Operation::Write, &self.path, error))
160 }
161
162 #[must_use]
164 pub fn path(&self) -> &Path {
165 &self.path
166 }
167}
168
169impl AsyncRead for AsyncFile {
170 fn poll_read(
171 mut self: Pin<&mut Self>,
172 context: &mut Context<'_>,
173 buffer: &mut ReadBuf<'_>,
174 ) -> Poll<std::io::Result<()>> {
175 Pin::new(&mut self.inner).poll_read(context, buffer)
176 }
177}
178
179impl AsyncWrite for AsyncFile {
180 fn poll_write(
181 mut self: Pin<&mut Self>,
182 context: &mut Context<'_>,
183 buffer: &[u8],
184 ) -> Poll<std::io::Result<usize>> {
185 Pin::new(&mut self.inner).poll_write(context, buffer)
186 }
187
188 fn poll_flush(
189 mut self: Pin<&mut Self>,
190 context: &mut Context<'_>,
191 ) -> Poll<std::io::Result<()>> {
192 Pin::new(&mut self.inner).poll_flush(context)
193 }
194
195 fn poll_shutdown(
196 mut self: Pin<&mut Self>,
197 context: &mut Context<'_>,
198 ) -> Poll<std::io::Result<()>> {
199 Pin::new(&mut self.inner).poll_shutdown(context)
200 }
201}