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