1use async_trait::async_trait;
7use std::io;
8use std::io::SeekFrom;
9use std::pin::Pin;
10use std::task::{Context, Poll};
11use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite, ReadBuf};
12
13#[derive(Debug, Clone, Default)]
18pub struct OpenOptions {
19 pub read: bool,
21 pub write: bool,
23 pub create: bool,
25 pub create_new: bool,
27 pub truncate: bool,
29 pub append: bool,
31}
32
33impl OpenOptions {
34 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn read(mut self, read: bool) -> Self {
41 self.read = read;
42 self
43 }
44
45 pub fn write(mut self, write: bool) -> Self {
47 self.write = write;
48 self
49 }
50
51 pub fn create(mut self, create: bool) -> Self {
53 self.create = create;
54 self
55 }
56
57 pub fn create_new(mut self, create_new: bool) -> Self {
59 self.create_new = create_new;
60 self
61 }
62
63 pub fn truncate(mut self, truncate: bool) -> Self {
65 self.truncate = truncate;
66 self
67 }
68
69 pub fn append(mut self, append: bool) -> Self {
71 self.append = append;
72 self
73 }
74
75 pub fn read_only() -> Self {
77 Self::new().read(true)
78 }
79
80 pub fn create_write() -> Self {
82 Self::new().write(true).create(true).truncate(true)
83 }
84
85 pub fn read_write() -> Self {
87 Self::new().read(true).write(true)
88 }
89
90 pub fn create_new_write() -> Self {
92 Self::new().write(true).create_new(true)
93 }
94}
95
96#[async_trait(?Send)]
101pub trait StorageProvider: Clone {
102 type File: StorageFile + 'static;
104
105 async fn open(&self, path: &str, options: OpenOptions) -> io::Result<Self::File>;
107
108 async fn exists(&self, path: &str) -> io::Result<bool>;
110
111 async fn delete(&self, path: &str) -> io::Result<()>;
113
114 async fn rename(&self, from: &str, to: &str) -> io::Result<()>;
116}
117
118#[async_trait(?Send)]
120pub trait StorageFile: AsyncRead + AsyncWrite + AsyncSeek + Unpin {
121 async fn sync_all(&self) -> io::Result<()>;
123
124 async fn sync_data(&self) -> io::Result<()>;
126
127 async fn size(&self) -> io::Result<u64>;
129
130 async fn set_len(&self, size: u64) -> io::Result<()>;
132}
133
134#[derive(Debug, Clone)]
136pub struct TokioStorageProvider;
137
138impl TokioStorageProvider {
139 pub fn new() -> Self {
141 Self
142 }
143}
144
145impl Default for TokioStorageProvider {
146 fn default() -> Self {
147 Self::new()
148 }
149}
150
151#[async_trait(?Send)]
152impl StorageProvider for TokioStorageProvider {
153 type File = TokioStorageFile;
154
155 async fn open(&self, path: &str, options: OpenOptions) -> io::Result<Self::File> {
156 let file = tokio::fs::OpenOptions::new()
157 .read(options.read)
158 .write(options.write)
159 .create(options.create)
160 .create_new(options.create_new)
161 .truncate(options.truncate)
162 .append(options.append)
163 .open(path)
164 .await?;
165 Ok(TokioStorageFile { inner: file })
166 }
167
168 async fn exists(&self, path: &str) -> io::Result<bool> {
169 match tokio::fs::metadata(path).await {
170 Ok(_) => Ok(true),
171 Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false),
172 Err(e) => Err(e),
173 }
174 }
175
176 async fn delete(&self, path: &str) -> io::Result<()> {
177 tokio::fs::remove_file(path).await
178 }
179
180 async fn rename(&self, from: &str, to: &str) -> io::Result<()> {
181 tokio::fs::rename(from, to).await
182 }
183}
184
185#[derive(Debug)]
187pub struct TokioStorageFile {
188 inner: tokio::fs::File,
189}
190
191#[async_trait(?Send)]
192impl StorageFile for TokioStorageFile {
193 async fn sync_all(&self) -> io::Result<()> {
194 self.inner.sync_all().await
195 }
196
197 async fn sync_data(&self) -> io::Result<()> {
198 self.inner.sync_data().await
199 }
200
201 async fn size(&self) -> io::Result<u64> {
202 let metadata = self.inner.metadata().await?;
203 Ok(metadata.len())
204 }
205
206 async fn set_len(&self, size: u64) -> io::Result<()> {
207 self.inner.set_len(size).await
208 }
209}
210
211impl AsyncRead for TokioStorageFile {
212 fn poll_read(
213 mut self: Pin<&mut Self>,
214 cx: &mut Context<'_>,
215 buf: &mut ReadBuf<'_>,
216 ) -> Poll<io::Result<()>> {
217 Pin::new(&mut self.inner).poll_read(cx, buf)
218 }
219}
220
221impl AsyncWrite for TokioStorageFile {
222 fn poll_write(
223 mut self: Pin<&mut Self>,
224 cx: &mut Context<'_>,
225 buf: &[u8],
226 ) -> Poll<io::Result<usize>> {
227 Pin::new(&mut self.inner).poll_write(cx, buf)
228 }
229
230 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
231 Pin::new(&mut self.inner).poll_flush(cx)
232 }
233
234 fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
235 Pin::new(&mut self.inner).poll_shutdown(cx)
236 }
237}
238
239impl AsyncSeek for TokioStorageFile {
240 fn start_seek(mut self: Pin<&mut Self>, position: SeekFrom) -> io::Result<()> {
241 Pin::new(&mut self.inner).start_seek(position)
242 }
243
244 fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
245 Pin::new(&mut self.inner).poll_complete(cx)
246 }
247}