fatfs/io.rs
1use crate::error::IoError;
2
3/// Provides IO error as an associated type.
4///
5/// Must be implemented for all types that also implement at least one of the following traits: `Read`, `Write`,
6/// `Seek`.
7pub trait IoBase {
8 /// Type of errors returned by input/output operations.
9 type Error: IoError;
10}
11
12/// The `Read` trait allows for reading bytes from a source.
13///
14/// It is based on the `std::io::Read` trait.
15pub trait Read: IoBase {
16 /// Pull some bytes from this source into the specified buffer, returning how many bytes were read.
17 ///
18 /// This function does not provide any guarantees about whether it blocks waiting for data, but if an object needs
19 /// to block for a read and cannot, it will typically signal this via an Err return value.
20 ///
21 /// If the return value of this method is `Ok(n)`, then it must be guaranteed that `0 <= n <= buf.len()`. A nonzero
22 /// `n` value indicates that the buffer buf has been filled in with n bytes of data from this source. If `n` is
23 /// `0`, then it can indicate one of two scenarios:
24 ///
25 /// 1. This reader has reached its "end of file" and will likely no longer be able to produce bytes. Note that this
26 /// does not mean that the reader will always no longer be able to produce bytes.
27 /// 2. The buffer specified was 0 bytes in length.
28 ///
29 /// It is not an error if the returned value `n` is smaller than the buffer size, even when the reader is not at
30 /// the end of the stream yet. This may happen for example because fewer bytes are actually available right now
31 /// (e. g. being close to end-of-file) or because `read()` was interrupted by a signal.
32 ///
33 /// # Errors
34 ///
35 /// If this function encounters any form of I/O or other error, an error will be returned. If an error is returned
36 /// then it must be guaranteed that no bytes were read.
37 /// An error for which `IoError::is_interrupted` returns true is non-fatal and the read operation should be retried
38 /// if there is nothing else to do.
39 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
40
41 /// Read the exact number of bytes required to fill `buf`.
42 ///
43 /// This function reads as many bytes as necessary to completely fill the specified buffer `buf`.
44 ///
45 /// # Errors
46 ///
47 /// If this function encounters an error for which `IoError::is_interrupted` returns true then the error is ignored
48 /// and the operation will continue.
49 ///
50 /// If this function encounters an end of file before completely filling the buffer, it returns an error
51 /// instantiated by a call to `IoError::new_unexpected_eof_error`. The contents of `buf` are unspecified in this
52 /// case.
53 ///
54 /// If this function returns an error, it is unspecified how many bytes it has read, but it will never read more
55 /// than would be necessary to completely fill the buffer.
56 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
77/// The `Write` trait allows for writing bytes into the sink.
78///
79/// It is based on the `std::io::Write` trait.
80pub trait Write: IoBase {
81 /// Write a buffer into this writer, returning how many bytes were written.
82 ///
83 /// # Errors
84 ///
85 /// Each call to write may generate an I/O error indicating that the operation could not be completed. If an error
86 /// is returned then no bytes in the buffer were written to this writer.
87 /// It is not considered an error if the entire buffer could not be written to this writer.
88 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error>;
89
90 /// Attempts to write an entire buffer into this writer.
91 ///
92 /// This method will continuously call `write` until there is no more data to be written or an error is returned.
93 /// Errors for which `IoError::is_interrupted` method returns true are being skipped. This method will not return
94 /// until the entire buffer has been successfully written or such an error occurs.
95 /// If `write` returns 0 before the entire buffer has been written this method will return an error instantiated by
96 /// a call to `IoError::new_write_zero_error`.
97 ///
98 /// # Errors
99 ///
100 /// This function will return the first error for which `IoError::is_interrupted` method returns false that `write`
101 /// returns.
102 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 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
118 ///
119 /// # Errors
120 ///
121 /// It is considered an error if not all bytes could be written due to I/O errors or EOF being reached.
122 fn flush(&mut self) -> Result<(), Self::Error>;
123}
124
125/// Enumeration of possible methods to seek within an I/O object.
126///
127/// It is based on the `std::io::SeekFrom` enum.
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129pub enum SeekFrom {
130 /// Sets the offset to the provided number of bytes.
131 Start(u64),
132 /// Sets the offset to the size of this object plus the specified number of bytes.
133 End(i64),
134 /// Sets the offset to the current position plus the specified number of bytes.
135 Current(i64),
136}
137
138/// The `Seek` trait provides a cursor which can be moved within a stream of bytes.
139///
140/// It is based on the `std::io::Seek` trait.
141pub trait Seek: IoBase {
142 /// Seek to an offset, in bytes, in a stream.
143 ///
144 /// A seek beyond the end of a stream or to a negative position is not allowed.
145 ///
146 /// If the seek operation completed successfully, this method returns the new position from the start of the
147 /// stream. That position can be used later with `SeekFrom::Start`.
148 ///
149 /// # Errors
150 /// Seeking to a negative offset is considered an error.
151 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/// A wrapper struct for types that have implementations for `std::io` traits.
177///
178/// `Read`, `Write`, `Seek` traits from this crate are implemented for this type if
179/// corresponding types from `std::io` are implemented by the inner instance.
180#[cfg(feature = "std")]
181pub struct StdIoWrapper<T> {
182 inner: T,
183}
184
185#[cfg(feature = "std")]
186impl<T> StdIoWrapper<T> {
187 /// Creates a new `StdIoWrapper` instance that wraps the provided `inner` instance.
188 pub fn new(inner: T) -> Self {
189 Self { inner }
190 }
191
192 /// Returns inner struct
193 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}