tokio_fs_ext/fs/native/
file.rs1use std::{
2 fs::Metadata,
3 io,
4 path::Path,
5 pin::Pin,
6 task::{Context, Poll, ready},
7};
8
9use pin_project_lite::pin_project;
10use tokio::{fs::OpenOptions, io::AsyncSeek};
11
12pin_project! {
13 #[derive(Debug)]
14 pub struct File {
15 #[pin]
16 pub(crate) inner: tokio::fs::File,
17 pub(crate) seek_pos: Option<io::SeekFrom>,
18 }
19}
20
21impl File {
22 pub async fn create(path: impl AsRef<Path>) -> io::Result<File> {
23 Ok(File {
24 inner: tokio::fs::File::create(path).await?,
25 seek_pos: None,
26 })
27 }
28
29 pub async fn create_new<P: AsRef<Path>>(path: P) -> std::io::Result<File> {
30 Ok(File {
31 inner: tokio::fs::File::create_new(path).await?,
32 seek_pos: None,
33 })
34 }
35
36 pub async fn metadata(&self) -> io::Result<Metadata> {
37 self.inner.metadata().await
38 }
39
40 pub async fn open(path: impl AsRef<Path>) -> io::Result<File> {
41 Ok(File {
42 inner: tokio::fs::File::open(path).await?,
43 seek_pos: None,
44 })
45 }
46
47 #[must_use]
48 pub fn options() -> OpenOptions {
49 OpenOptions::new()
50 }
51
52 pub async fn sync_all(&self) -> io::Result<()> {
53 self.inner.sync_all().await
54 }
55
56 pub async fn sync_data(&self) -> io::Result<()> {
57 self.inner.sync_data().await
58 }
59
60 pub async fn set_len(&self, size: u64) -> io::Result<()> {
69 self.inner.set_len(size).await
70 }
71}
72
73impl futures::io::AsyncRead for File {
74 fn poll_read(
75 self: Pin<&mut Self>,
76 cx: &mut Context<'_>,
77 buf: &mut [u8],
78 ) -> Poll<io::Result<usize>> {
79 let mut buf = tokio::io::ReadBuf::new(buf);
80 ready!(tokio::io::AsyncRead::poll_read(
81 self.project().inner,
82 cx,
83 &mut buf
84 ))?;
85 Poll::Ready(Ok(buf.filled().len()))
86 }
87}
88
89impl futures::io::AsyncWrite for File {
90 fn poll_write(
91 self: Pin<&mut Self>,
92 cx: &mut Context<'_>,
93 buf: &[u8],
94 ) -> Poll<io::Result<usize>> {
95 tokio::io::AsyncWrite::poll_write(self.project().inner, cx, buf)
96 }
97
98 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
99 tokio::io::AsyncWrite::poll_flush(self.project().inner, cx)
100 }
101
102 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
103 tokio::io::AsyncWrite::poll_shutdown(self.project().inner, cx)
104 }
105}
106
107impl futures::io::AsyncSeek for File {
108 fn poll_seek(
109 mut self: Pin<&mut Self>,
110 cx: &mut Context<'_>,
111 pos: io::SeekFrom,
112 ) -> Poll<io::Result<u64>> {
113 if self.seek_pos != Some(pos) {
114 ready!(self.as_mut().project().inner.poll_complete(cx))?;
115 self.as_mut().project().inner.start_seek(pos)?;
116 *self.as_mut().project().seek_pos = Some(pos);
117 }
118 let res = ready!(self.as_mut().project().inner.poll_complete(cx));
119 *self.as_mut().project().seek_pos = None;
120 Poll::Ready(res)
121 }
122}