1use moirai_pal::fs::AsyncFile;
2use std::io::{self, SeekFrom};
3use std::path::{Path, PathBuf};
4use std::pin::Pin;
5use std::task::{Context, Poll};
6
7use crate::fs::options::FileOpenOptions;
8use crate::fs::stats::FileStats;
9use crate::io::{AsyncRead, AsyncWrite};
10
11pub struct File {
13 inner: AsyncFile,
14 path: PathBuf,
15 stats: FileStats,
16}
17
18impl File {
19 pub async fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
21 Self::open_with_options(path, FileOpenOptions::read_only()).await
22 }
23
24 pub async fn create<P: AsRef<Path>>(path: P) -> io::Result<Self> {
26 Self::open_with_options(path, FileOpenOptions::write_only()).await
27 }
28
29 pub async fn open_with_options<P: AsRef<Path>>(
31 path: P,
32 options: FileOpenOptions,
33 ) -> io::Result<Self> {
34 let path_buf = path.as_ref().to_path_buf();
35 let inner = AsyncFile::open_with_options(
36 &path_buf,
37 options.read,
38 options.write,
39 options.create,
40 options.append,
41 options.truncate,
42 )
43 .await?;
44
45 Ok(Self {
46 inner,
47 path: path_buf,
48 stats: FileStats::default(),
49 })
50 }
51
52 pub async fn read_to_string(&mut self) -> io::Result<String> {
54 let mut contents = String::new();
55 self.inner.read_to_string(&mut contents).await?;
56 self.stats.bytes_read += contents.len() as u64;
57 self.stats.read_operations += 1;
58 Ok(contents)
59 }
60
61 pub async fn read_to_end(&mut self) -> io::Result<Vec<u8>> {
63 let mut contents = Vec::new();
64 self.inner.read_to_end(&mut contents).await?;
65 self.stats.bytes_read += contents.len() as u64;
66 self.stats.read_operations += 1;
67 Ok(contents)
68 }
69
70 pub async fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
72 let bytes_read = self.inner.read(buf).await?;
73 self.stats.bytes_read += bytes_read as u64;
74 self.stats.read_operations += 1;
75 Ok(bytes_read)
76 }
77
78 pub async fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
80 let bytes_written = self.inner.write(buf).await?;
81 self.stats.bytes_written += bytes_written as u64;
82 self.stats.write_operations += 1;
83 Ok(bytes_written)
84 }
85
86 pub async fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
88 let mut written = 0;
89 while written < buf.len() {
90 let n = self.write(&buf[written..]).await?;
91 if n == 0 {
92 return Err(io::Error::new(
93 io::ErrorKind::WriteZero,
94 "failed to write whole buffer",
95 ));
96 }
97 written += n;
98 }
99 Ok(())
100 }
101
102 pub async fn write_str(&mut self, s: &str) -> io::Result<()> {
104 self.write_all(s.as_bytes()).await
105 }
106
107 pub async fn flush(&mut self) -> io::Result<()> {
109 self.inner.flush().await?;
110 Ok(())
111 }
112
113 pub async fn sync_all(&mut self) -> io::Result<()> {
115 self.inner.sync_all().await?;
116 Ok(())
117 }
118
119 pub async fn sync_data(&mut self) -> io::Result<()> {
121 self.inner.sync_data().await?;
122 Ok(())
123 }
124
125 pub async fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
127 let new_pos = self.inner.seek(pos).await?;
128 self.stats.seek_operations += 1;
129 Ok(new_pos)
130 }
131
132 pub async fn stream_position(&mut self) -> io::Result<u64> {
134 self.inner.seek(SeekFrom::Current(0)).await
135 }
136
137 pub async fn metadata(&self) -> io::Result<std::fs::Metadata> {
139 self.inner.metadata().await
140 }
141
142 pub fn path(&self) -> &Path {
144 &self.path
145 }
146
147 pub fn stats(&self) -> &FileStats {
149 &self.stats
150 }
151}
152
153impl AsyncRead for File {
154 fn poll_read(
155 mut self: Pin<&mut Self>,
156 cx: &mut Context<'_>,
157 buf: &mut [u8],
158 ) -> Poll<io::Result<usize>> {
159 match Pin::new(&mut self.inner).poll_read(cx, buf) {
160 Poll::Ready(Ok(n)) => {
161 self.stats.bytes_read += n as u64;
162 self.stats.read_operations += 1;
163 Poll::Ready(Ok(n))
164 }
165 res => res,
166 }
167 }
168}
169
170impl AsyncWrite for File {
171 fn poll_write(
172 mut self: Pin<&mut Self>,
173 cx: &mut Context<'_>,
174 buf: &[u8],
175 ) -> Poll<io::Result<usize>> {
176 match Pin::new(&mut self.inner).poll_write(cx, buf) {
177 Poll::Ready(Ok(n)) => {
178 self.stats.bytes_written += n as u64;
179 self.stats.write_operations += 1;
180 Poll::Ready(Ok(n))
181 }
182 res => res,
183 }
184 }
185
186 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
187 Pin::new(&mut self.inner).poll_flush(cx)
188 }
189
190 fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
191 Poll::Ready(Ok(()))
192 }
193}