1use crate::error::IoError;
2
3pub trait IoBase {
8 type Error: IoError;
10}
11
12pub trait Read: IoBase {
16 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
40
41 fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Self::Error> {
57 while !buf.is_empty() {
58 match self.read(buf) {
59 Ok(0) => break,
60 Ok(n) => {
61 let tmp = buf;
62 buf = &mut tmp[n..];
63 }
64 Err(ref e) if e.is_interrupted() => {}
65 Err(e) => return Err(e),
66 }
67 }
68 if buf.is_empty() {
69 Ok(())
70 } else {
71 debug!("failed to fill whole buffer in read_exact");
72 Err(Self::Error::new_unexpected_eof_error())
73 }
74 }
75}
76
77pub trait Write: IoBase {
81 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error>;
89
90 fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Self::Error> {
103 while !buf.is_empty() {
104 match self.write(buf) {
105 Ok(0) => {
106 debug!("failed to write whole buffer in write_all");
107 return Err(Self::Error::new_write_zero_error());
108 }
109 Ok(n) => buf = &buf[n..],
110 Err(ref e) if e.is_interrupted() => {}
111 Err(e) => return Err(e),
112 }
113 }
114 Ok(())
115 }
116
117 fn flush(&mut self) -> Result<(), Self::Error>;
123}
124
125#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub enum SeekFrom {
130 Start(u64),
132 End(i64),
134 Current(i64),
136}
137
138pub trait Seek: IoBase {
142 fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error>;
152}
153
154#[cfg(feature = "std")]
155impl From<SeekFrom> for std::io::SeekFrom {
156 fn from(from: SeekFrom) -> Self {
157 match from {
158 SeekFrom::Start(n) => std::io::SeekFrom::Start(n),
159 SeekFrom::End(n) => std::io::SeekFrom::End(n),
160 SeekFrom::Current(n) => std::io::SeekFrom::Current(n),
161 }
162 }
163}
164
165#[cfg(feature = "std")]
166impl From<std::io::SeekFrom> for SeekFrom {
167 fn from(from: std::io::SeekFrom) -> Self {
168 match from {
169 std::io::SeekFrom::Start(n) => SeekFrom::Start(n),
170 std::io::SeekFrom::End(n) => SeekFrom::End(n),
171 std::io::SeekFrom::Current(n) => SeekFrom::Current(n),
172 }
173 }
174}
175
176#[cfg(feature = "std")]
181pub struct StdIoWrapper<T> {
182 inner: T,
183}
184
185#[cfg(feature = "std")]
186impl<T> StdIoWrapper<T> {
187 pub fn new(inner: T) -> Self {
189 Self { inner }
190 }
191
192 pub fn into_inner(self) -> T {
194 self.inner
195 }
196}
197
198#[cfg(feature = "std")]
199impl<T> IoBase for StdIoWrapper<T> {
200 type Error = std::io::Error;
201}
202
203#[cfg(feature = "std")]
204impl<T: std::io::Read> Read for StdIoWrapper<T> {
205 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
206 self.inner.read(buf)
207 }
208 fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
209 self.inner.read_exact(buf)
210 }
211}
212
213#[cfg(feature = "std")]
214impl<T: std::io::Write> Write for StdIoWrapper<T> {
215 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
216 self.inner.write(buf)
217 }
218
219 fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
220 self.inner.write_all(buf)
221 }
222
223 fn flush(&mut self) -> Result<(), Self::Error> {
224 self.inner.flush()
225 }
226}
227
228#[cfg(feature = "std")]
229impl<T: std::io::Seek> Seek for StdIoWrapper<T> {
230 fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
231 self.inner.seek(pos.into())
232 }
233}
234
235#[cfg(feature = "std")]
236impl<T> From<T> for StdIoWrapper<T> {
237 fn from(from: T) -> Self {
238 Self::new(from)
239 }
240}
241
242pub(crate) trait ReadLeExt {
243 type Error;
244 fn read_u8(&mut self) -> Result<u8, Self::Error>;
245 fn read_u16_le(&mut self) -> Result<u16, Self::Error>;
246 fn read_u32_le(&mut self) -> Result<u32, Self::Error>;
247}
248
249impl<T: Read> ReadLeExt for T {
250 type Error = <Self as IoBase>::Error;
251
252 fn read_u8(&mut self) -> Result<u8, Self::Error> {
253 let mut buf = [0_u8; 1];
254 self.read_exact(&mut buf)?;
255 Ok(buf[0])
256 }
257
258 fn read_u16_le(&mut self) -> Result<u16, Self::Error> {
259 let mut buf = [0_u8; 2];
260 self.read_exact(&mut buf)?;
261 Ok(u16::from_le_bytes(buf))
262 }
263
264 fn read_u32_le(&mut self) -> Result<u32, Self::Error> {
265 let mut buf = [0_u8; 4];
266 self.read_exact(&mut buf)?;
267 Ok(u32::from_le_bytes(buf))
268 }
269}
270
271pub(crate) trait WriteLeExt {
272 type Error;
273 fn write_u8(&mut self, n: u8) -> Result<(), Self::Error>;
274 fn write_u16_le(&mut self, n: u16) -> Result<(), Self::Error>;
275 fn write_u32_le(&mut self, n: u32) -> Result<(), Self::Error>;
276}
277
278impl<T: Write> WriteLeExt for T {
279 type Error = <Self as IoBase>::Error;
280
281 fn write_u8(&mut self, n: u8) -> Result<(), Self::Error> {
282 self.write_all(&[n])
283 }
284
285 fn write_u16_le(&mut self, n: u16) -> Result<(), Self::Error> {
286 self.write_all(&n.to_le_bytes())
287 }
288
289 fn write_u32_le(&mut self, n: u32) -> Result<(), Self::Error> {
290 self.write_all(&n.to_le_bytes())
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297
298 #[test]
299 fn test_seek_from_variants() {
300 let start = SeekFrom::Start(100);
301 assert_eq!(start, SeekFrom::Start(100));
302 assert_ne!(start, SeekFrom::End(-10));
303
304 let end = SeekFrom::End(-50);
305 assert_eq!(end, SeekFrom::End(-50));
306 assert_ne!(end, SeekFrom::Current(10));
307
308 let current = SeekFrom::Current(20);
309 assert_eq!(current, SeekFrom::Current(20));
310 assert_ne!(current, SeekFrom::Start(20));
311 }
312
313 #[test]
314 fn test_seek_from_debug() {
315 assert_eq!(format!("{:?}", SeekFrom::Start(42)), "Start(42)");
316 assert_eq!(format!("{:?}", SeekFrom::End(-10)), "End(-10)");
317 assert_eq!(format!("{:?}", SeekFrom::Current(5)), "Current(5)");
318 }
319
320 #[test]
321 fn test_seek_from_clone_copy() {
322 let start = SeekFrom::Start(100);
323 let cloned = start.clone();
324 assert_eq!(start, cloned);
325
326 let copied = start;
327 assert_eq!(start, copied);
328 }
329
330 #[cfg(feature = "std")]
331 #[test]
332 fn test_seek_from_std_conversion() {
333 let fatfs_seek = SeekFrom::Start(100);
334 let std_seek: std::io::SeekFrom = fatfs_seek.into();
335 assert_eq!(std_seek, std::io::SeekFrom::Start(100));
336
337 let std_seek = std::io::SeekFrom::End(-50);
338 let fatfs_seek: SeekFrom = std_seek.into();
339 assert_eq!(fatfs_seek, SeekFrom::End(-50));
340
341 let fatfs_seek = SeekFrom::Current(20);
342 let std_seek: std::io::SeekFrom = fatfs_seek.into();
343 assert_eq!(std_seek, std::io::SeekFrom::Current(20));
344 }
345
346 #[cfg(feature = "std")]
347 #[test]
348 fn test_std_io_wrapper() {
349 let mut cursor = std::io::Cursor::new(vec![0u8; 100]);
350 let wrapper = StdIoWrapper::new(&mut cursor);
351
352 let inner = wrapper.into_inner();
354 let wrapper2 = StdIoWrapper::new(inner);
355 let _inner = wrapper2.into_inner();
356 }
357
358 #[cfg(feature = "std")]
359 #[test]
360 fn test_std_io_wrapper_from() {
361 let cursor = std::io::Cursor::new(vec![0u8; 100]);
362 let wrapper: StdIoWrapper<_> = StdIoWrapper::from(cursor);
363 assert_eq!(wrapper.into_inner().into_inner().len(), 100);
364 }
365}