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