1use super::VirtualFileSystem;
2use crate::{Error, ItemStatic, Result, SynchronousFile, poll};
3use alloc::{vec, vec::Vec};
4use core::mem::forget;
5use embedded_io_async::ErrorType;
6use exported_file_system::{AccessFlags, ControlCommand, CreateFlags, Permissions};
7use file_system::{Context, Flags, Path, Position, Size, StateFlags, Statistics};
8use task::TaskIdentifier;
9use task::block_on;
10use users::{GroupIdentifier, UserIdentifier};
11
12#[derive(Debug)]
17pub struct File<'a>(SynchronousFile<'a>);
18
19impl<'a> File<'a> {
20 pub fn as_synchronous_file_mut(&mut self) -> &mut SynchronousFile<'a> {
21 &mut self.0
22 }
23}
24
25impl ErrorType for File<'_> {
26 type Error = Error;
27}
28
29impl embedded_io_async::Write for File<'_> {
30 async fn write(&mut self, buf: &[u8]) -> core::result::Result<usize, Self::Error> {
31 File::write(self, buf).await
32 }
33
34 async fn flush(&mut self) -> core::result::Result<(), Self::Error> {
35 File::flush(self).await
36 }
37}
38
39impl core::fmt::Write for File<'_> {
40 fn write_str(&mut self, s: &str) -> core::fmt::Result {
41 if let Err(e) = block_on(self.write(s.as_bytes())) {
42 log::error!("Error writing string to file: {}", e);
43 return Err(core::fmt::Error);
44 }
45 Ok(())
46 }
47}
48
49impl<'a> File<'a> {
50 pub(crate) fn new(
51 virtual_file_system: &'a VirtualFileSystem,
52 item: ItemStatic,
53 flags: Flags,
54 context: Context,
55 ) -> Self {
56 Self(SynchronousFile::new(
57 virtual_file_system,
58 item,
59 0,
60 flags,
61 context,
62 ))
63 }
64
65 pub async fn open(
66 virtual_file_system: &'a VirtualFileSystem,
67 task: task::TaskIdentifier,
68 path: impl AsRef<Path>,
69 flags: Flags,
70 ) -> Result<Self> {
71 let file_identifier = virtual_file_system.open(&path, flags, task).await?;
72
73 Ok(file_identifier)
74 }
75
76 pub async fn create_unnamed_pipe(
77 file_system: &'a VirtualFileSystem,
78 size: usize,
79 status: StateFlags,
80 ) -> Result<(Self, Self)> {
81 file_system.create_unnamed_pipe(size, status).await
82 }
83
84 pub async fn set_position(&mut self, position: &Position) -> Result<Size> {
85 poll(|| self.0.set_position(position)).await
86 }
87
88 pub async fn write(&mut self, buffer: &[u8]) -> Result<usize> {
91 poll(|| self.0.write(buffer)).await
92 }
93
94 pub async fn read_slice_from_path(
95 virtual_file_system: &VirtualFileSystem,
96 task: TaskIdentifier,
97 path: impl AsRef<Path>,
98 buffer: &mut [u8],
99 ) -> Result<()> {
100 let mut file = File::open(
101 virtual_file_system,
102 task,
103 path,
104 Flags::new(AccessFlags::Read, None, None),
105 )
106 .await?;
107
108 file.read(buffer).await?;
109
110 file.close(virtual_file_system).await?;
111
112 Ok(())
113 }
114
115 pub async fn read_from_path(
116 virtual_file_system: &VirtualFileSystem,
117 task: TaskIdentifier,
118 path: impl AsRef<Path>,
119 buffer: &mut Vec<u8>,
120 ) -> Result<()> {
121 buffer.clear();
122
123 let mut file = File::open(
124 virtual_file_system,
125 task,
126 path,
127 Flags::new(AccessFlags::Read, None, None),
128 )
129 .await?;
130
131 file.read_to_end(buffer, 256).await?;
132
133 file.close(virtual_file_system).await?;
134
135 Ok(())
136 }
137
138 pub async fn write_to_path(
139 virtual_file_system: &VirtualFileSystem,
140 task: task::TaskIdentifier,
141 path: impl AsRef<Path>,
142 buffer: &[u8],
143 ) -> Result<()> {
144 let mut file = File::open(
145 virtual_file_system,
146 task,
147 path,
148 Flags::new(AccessFlags::Write, Some(CreateFlags::CREATE_TRUNCATE), None),
149 )
150 .await?;
151
152 file.write(buffer).await?;
153
154 file.close(virtual_file_system).await
155 }
156
157 pub async fn write_line(&mut self, buffer: &[u8]) -> Result<usize> {
158 poll(|| self.0.write_line(buffer)).await
159 }
160
161 pub async fn display_content<W: embedded_io_async::Write>(
162 &mut self,
163 w: &mut W,
164 buffer_size: usize,
165 ) -> Result<()> {
166 let mut buffer = vec![0u8; buffer_size];
167 loop {
168 let bytes_read = self.read(&mut buffer).await?;
169
170 if bytes_read == 0 {
171 break;
172 }
173
174 w.write(&buffer[..bytes_read])
175 .await
176 .map_err(|_| Error::FailedToWrite)?;
177 }
178
179 Ok(())
180 }
181
182 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
183 poll(|| self.0.read(buffer)).await
184 }
185
186 pub async fn read_until(&mut self, buffer: &mut [u8], delimiter: &[u8]) -> Result<usize> {
187 poll(|| self.0.read_until(buffer, delimiter)).await
188 }
189
190 pub async fn read_to_end(&mut self, buffer: &mut Vec<u8>, chunk_size: usize) -> Result<usize> {
191 poll(|| self.0.read_to_end(buffer, chunk_size)).await
192 }
193
194 pub async fn flush(&mut self) -> Result<()> {
195 poll(|| self.0.flush()).await
196 }
197
198 pub async fn duplicate(&self) -> Result<Self> {
199 Ok(Self(poll(|| self.0.duplicate()).await?))
200 }
201
202 pub async fn get_statistics(&mut self) -> Result<Statistics> {
203 poll(|| self.0.get_statistics()).await
204 }
205
206 pub async fn set_owner(
207 &mut self,
208 user: Option<UserIdentifier>,
209 group: Option<GroupIdentifier>,
210 ) -> Result<()> {
211 poll(|| self.0.set_owner(user, group)).await
212 }
213
214 pub async fn set_permissions(&mut self, permissions: Permissions) -> Result<()> {
215 poll(|| self.0.set_permissions(permissions)).await
216 }
217
218 pub async fn control<C>(&mut self, command: C, argument: &C::Input) -> Result<C::Output>
219 where
220 C: ControlCommand,
221 C::Output: Default,
222 {
223 poll(|| self.0.control(command, argument)).await
224 }
225
226 pub fn get_access(&self) -> Result<AccessFlags> {
227 Ok(self.0.flags.get_access())
228 }
229
230 pub async fn close(mut self, virtual_file_system: &VirtualFileSystem) -> crate::Result<()> {
231 let result = virtual_file_system
232 .close(&self.0.item, &mut self.0.context)
233 .await;
234 forget(self);
235
236 result
237 }
238
239 pub fn into_synchronous_file(self) -> SynchronousFile<'a> {
240 self.0
241 }
242}
243
244pub struct FileControlIterator<'a, C> {
245 file: &'a mut File<'a>,
246 get_command: C,
247 index: usize,
248 count: usize,
249}
250
251impl<'a, C> FileControlIterator<'a, C>
252where
253 C: ControlCommand<Input = usize>,
254 C::Output: Default,
255{
256 pub async fn new<Cc>(file: &'a mut File<'a>, count_command: Cc, get_command: C) -> Result<Self>
257 where
258 Cc: ControlCommand<Input = (), Output = usize>,
259 {
260 let count: usize = file.control(count_command, &()).await?;
261
262 Ok(Self {
263 file,
264 get_command,
265 index: 0,
266 count,
267 })
268 }
269
270 pub async fn next(&mut self) -> Result<Option<C::Output>> {
271 if self.index >= self.count {
272 return Ok(None);
273 }
274
275 let result = self.file.control(self.get_command, &self.index).await?;
276
277 self.index += 1;
278
279 Ok(Some(result))
280 }
281}