arta_async_std/fs/
file.rs

1use crate::AsyncStdGlobalRuntime;
2use arta::fs::RuntimeFile;
3use cfg_if::cfg_if;
4use futures::{prelude::Future, AsyncRead, AsyncSeek, AsyncWrite, TryFutureExt};
5use std::pin::Pin;
6
7cfg_if! {
8    if #[cfg(windows)] {
9        impl std::os::windows::io::AsRawHandle for TokioFile {
10            fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
11                self.inner.as_raw_handle()
12            }
13        }
14
15        impl std::os::windows::io::AsHandle for TokioFile {
16            fn as_handle(&self) -> std::os::windows::io::BorrowedHandle<'_> {
17                let raw_handle = std::os::windows::io::AsRawHandle::as_raw_handle(self);
18                unsafe { std::os::windows::io::BorrowedHandle::borrow_raw(raw_handle) }
19            }
20        }
21
22        impl From<std::os::windows::io::OwnedHandle> for TokioFile {
23            fn from(handle: std::os::windows::io::OwnedHandle) -> Self {
24                Self { inner: tokio::fs::File::from_std(std::fs::File::from(handle)).compat() }
25            }
26        }
27    } else if #[cfg(any(unix, target_os = "wasi"))] {
28        impl std::os::fd::AsRawFd for AsyncStdFile {
29            fn as_raw_fd(&self) -> std::os::unix::prelude::RawFd {
30                self.inner.as_raw_fd()
31            }
32        }
33
34        impl std::os::fd::AsFd for AsyncStdFile {
35            fn as_fd(&self) -> std::os::unix::prelude::BorrowedFd<'_> {
36                let raw_fd = std::os::fd::AsRawFd::as_raw_fd(self);
37                unsafe { std::os::fd::BorrowedFd::borrow_raw(raw_fd) }
38            }
39        }
40
41        impl From<std::os::fd::OwnedFd> for AsyncStdFile {
42            fn from(fd: std::os::fd::OwnedFd) -> Self {
43                Self { inner: async_std::fs::File::from(std::fs::File::from(fd)) }
44            }
45        }
46    }
47}
48
49/// Async-std specific [`RuntimeFile`] implementation.
50pub struct AsyncStdFile {
51    inner: async_std::fs::File,
52}
53
54impl AsyncWrite for AsyncStdFile {
55    fn poll_write(
56        mut self: std::pin::Pin<&mut Self>,
57        cx: &mut std::task::Context<'_>,
58        buf: &[u8],
59    ) -> std::task::Poll<std::io::Result<usize>> {
60        Pin::new(&mut self.inner).poll_write(cx, buf)
61    }
62
63    fn poll_flush(
64        mut self: Pin<&mut Self>,
65        cx: &mut std::task::Context<'_>,
66    ) -> std::task::Poll<std::io::Result<()>> {
67        Pin::new(&mut self.inner).poll_flush(cx)
68    }
69
70    fn poll_close(
71        mut self: Pin<&mut Self>,
72        cx: &mut std::task::Context<'_>,
73    ) -> std::task::Poll<std::io::Result<()>> {
74        Pin::new(&mut self.inner).poll_close(cx)
75    }
76
77    fn poll_write_vectored(
78        mut self: Pin<&mut Self>,
79        cx: &mut std::task::Context<'_>,
80        bufs: &[std::io::IoSlice<'_>],
81    ) -> std::task::Poll<std::io::Result<usize>> {
82        Pin::new(&mut self.inner).poll_write_vectored(cx, bufs)
83    }
84}
85
86impl AsyncRead for AsyncStdFile {
87    fn poll_read(
88        mut self: Pin<&mut Self>,
89        cx: &mut std::task::Context<'_>,
90        buf: &mut [u8],
91    ) -> std::task::Poll<std::io::Result<usize>> {
92        Pin::new(&mut self.inner).poll_read(cx, buf)
93    }
94
95    fn poll_read_vectored(
96        mut self: Pin<&mut Self>,
97        cx: &mut std::task::Context<'_>,
98        bufs: &mut [std::io::IoSliceMut<'_>],
99    ) -> std::task::Poll<std::io::Result<usize>> {
100        Pin::new(&mut self.inner).poll_read_vectored(cx, bufs)
101    }
102}
103
104impl AsyncSeek for AsyncStdFile {
105    fn poll_seek(
106        mut self: Pin<&mut Self>,
107        cx: &mut std::task::Context<'_>,
108        pos: std::io::SeekFrom,
109    ) -> std::task::Poll<std::io::Result<u64>> {
110        Pin::new(&mut self.inner).poll_seek(cx, pos)
111    }
112}
113
114impl RuntimeFile for AsyncStdFile {
115    type Runtime = AsyncStdGlobalRuntime;
116
117    fn open(
118        _runtime: &Self::Runtime,
119        open_options: &std::fs::OpenOptions,
120        path: impl AsRef<std::path::Path>,
121    ) -> impl Future<Output = std::io::Result<Self>> + Send
122    where
123        Self: Sized,
124    {
125        // async_std::fs::OpenOptions has no implementation to convert
126        // from std primitves so we need to transmute it.
127        let open_options: async_std::fs::OpenOptions =
128            unsafe { std::mem::transmute(open_options.clone()) };
129        let path: async_std::path::PathBuf = path.as_ref().to_owned().into();
130
131        open_options.open(path).map_ok(|file| Self { inner: file })
132    }
133
134    fn set_len(&self, size: u64) -> impl Future<Output = std::io::Result<()>> + Send {
135        self.inner.set_len(size)
136    }
137
138    fn metadata(&self) -> impl Future<Output = std::io::Result<std::fs::Metadata>> + Send {
139        self.inner.metadata()
140    }
141
142    fn sync_all(&self) -> impl Future<Output = std::io::Result<()>> + Send {
143        self.inner.sync_all()
144    }
145
146    fn sync_data(&self) -> impl Future<Output = std::io::Result<()>> + Send {
147        self.inner.sync_data()
148    }
149
150    fn set_permissions(
151        &self,
152        permissions: std::fs::Permissions,
153    ) -> impl Future<Output = std::io::Result<()>> + Send {
154        self.inner.set_permissions(permissions)
155    }
156}