Skip to content

Commit c9f725e

Browse files
committed
io: require Fron<ErrorKind> for Error
1 parent 353483c commit c9f725e

File tree

5 files changed

+74
-69
lines changed

5 files changed

+74
-69
lines changed

embedded-io-async/src/impls/slice_mut.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::mem;
2-
use embedded_io::SliceWriteError;
2+
use embedded_io::ErrorKind;
33

44
use crate::Write;
55

@@ -17,7 +17,7 @@ impl Write for &mut [u8] {
1717
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1818
let amt = core::cmp::min(buf.len(), self.len());
1919
if !buf.is_empty() && amt == 0 {
20-
return Err(SliceWriteError::Full);
20+
return Err(ErrorKind::StorageFull);
2121
}
2222
let (a, b) = mem::take(self).split_at_mut(amt);
2323
a.copy_from_slice(&buf[..amt]);

embedded-io-async/src/lib.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ extern crate alloc;
99

1010
mod impls;
1111

12-
pub use embedded_io::{
13-
Error, ErrorKind, ErrorType, ReadExactError, ReadReady, SeekFrom, WriteReady,
14-
};
12+
pub use embedded_io::{Error, ErrorKind, ErrorType, ReadReady, SeekFrom, WriteReady};
1513

1614
/// Async reader.
1715
///
@@ -54,6 +52,15 @@ pub trait Read: ErrorType {
5452
/// the hardware with e.g. DMA.
5553
///
5654
/// Implementations should document whether they're actually side-effect-free on cancel or not.
55+
///
56+
/// # Errors
57+
///
58+
/// If this function encounters any form of I/O or other error, an error
59+
/// variant will be returned. If an error is returned then it must be
60+
/// guaranteed that no bytes were read.
61+
///
62+
/// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read
63+
/// operation should be retried if there is nothing else to do.
5764
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
5865

5966
/// Read the exact number of bytes required to fill `buf`.
@@ -63,18 +70,31 @@ pub trait Read: ErrorType {
6370
///
6471
/// This function is not side-effect-free on cancel (AKA "cancel-safe"), i.e. if you cancel (drop) a returned
6572
/// future that hasn't completed yet, some bytes might have already been read, which will get lost.
66-
async fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
73+
////
74+
/// /// # Errors
75+
///
76+
/// If this function encounters an "end of file" before completely filling
77+
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
78+
/// The contents of `buf` are unspecified in this case.
79+
///
80+
/// If any other read error is encountered then this function immediately
81+
/// returns. The contents of `buf` are unspecified in this case.
82+
///
83+
/// If this function returns an error, it is unspecified how many bytes it
84+
/// has read, but it will never read more than would be necessary to
85+
/// completely fill the buffer.
86+
async fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Self::Error> {
6787
while !buf.is_empty() {
6888
match self.read(buf).await {
6989
Ok(0) => break,
7090
Ok(n) => buf = &mut buf[n..],
71-
Err(e) => return Err(ReadExactError::Other(e)),
91+
Err(e) => return Err(e),
7292
}
7393
}
7494
if buf.is_empty() {
7595
Ok(())
7696
} else {
77-
Err(ReadExactError::UnexpectedEof)
97+
Err(ErrorKind::UnexpectedEof.into())
7898
}
7999
}
80100
}

embedded-io/src/impls/slice_mut.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
1-
use crate::{Error, ErrorKind, ErrorType, SliceWriteError, Write, WriteReady};
1+
use crate::{ErrorKind, ErrorType, SliceWriteError, Write, WriteReady};
22
use core::mem;
33

4-
impl Error for SliceWriteError {
5-
fn kind(&self) -> ErrorKind {
6-
match self {
7-
SliceWriteError::Full => ErrorKind::WriteZero,
8-
}
9-
}
10-
}
11-
124
impl ErrorType for &mut [u8] {
13-
type Error = SliceWriteError;
5+
type Error = ErrorKind;
146
}
157

168
impl core::fmt::Display for SliceWriteError {
@@ -34,7 +26,7 @@ impl Write for &mut [u8] {
3426
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
3527
let amt = core::cmp::min(buf.len(), self.len());
3628
if !buf.is_empty() && amt == 0 {
37-
return Err(SliceWriteError::Full);
29+
return Err(ErrorKind::StorageFull);
3830
}
3931
let (a, b) = mem::take(self).split_at_mut(amt);
4032
a.copy_from_slice(&buf[..amt]);

embedded-io/src/impls/slice_ref.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::{BufRead, ErrorType, Read, ReadReady};
1+
use crate::{BufRead, ErrorKind, ErrorType, Read, ReadReady};
22

33
impl ErrorType for &[u8] {
4-
type Error = core::convert::Infallible;
4+
type Error = ErrorKind;
55
}
66

77
/// Read is implemented for `&[u8]` by copying from the slice.

embedded-io/src/lib.rs

Lines changed: 41 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ pub enum ErrorKind {
9999
///
100100
/// [`InvalidInput`]: ErrorKind::InvalidInput
101101
InvalidData,
102+
/// The underlying storage (typically, a filesystem) is full.
103+
///
104+
/// This does not include out of quota errors.
105+
StorageFull,
102106
/// The I/O operation's timeout expired, causing it to be canceled.
103107
TimedOut,
104108
/// This operation was interrupted.
@@ -109,6 +113,13 @@ pub enum ErrorKind {
109113
///
110114
/// This means that the operation can never succeed.
111115
Unsupported,
116+
/// An error returned when an operation could not be completed because an
117+
/// "end of file" was reached prematurely.
118+
///
119+
/// This typically means that an operation could only succeed if it read a
120+
/// particular number of bytes but only a smaller number of bytes could be
121+
/// read.
122+
UnexpectedEof,
112123
/// An operation could not be completed, because it failed
113124
/// to allocate enough memory.
114125
OutOfMemory,
@@ -133,9 +144,11 @@ impl From<ErrorKind> for std::io::ErrorKind {
133144
ErrorKind::AlreadyExists => std::io::ErrorKind::AlreadyExists,
134145
ErrorKind::InvalidInput => std::io::ErrorKind::InvalidInput,
135146
ErrorKind::InvalidData => std::io::ErrorKind::InvalidData,
147+
ErrorKind::StorageFull => std::io::ErrorKind::StorageFull,
136148
ErrorKind::TimedOut => std::io::ErrorKind::TimedOut,
137149
ErrorKind::Interrupted => std::io::ErrorKind::Interrupted,
138150
ErrorKind::Unsupported => std::io::ErrorKind::Unsupported,
151+
ErrorKind::UnexpectedEof => std::io::ErrorKind::UnexpectedEof,
139152
ErrorKind::OutOfMemory => std::io::ErrorKind::OutOfMemory,
140153
_ => std::io::ErrorKind::Other,
141154
}
@@ -159,9 +172,11 @@ impl From<std::io::ErrorKind> for ErrorKind {
159172
std::io::ErrorKind::AlreadyExists => ErrorKind::AlreadyExists,
160173
std::io::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
161174
std::io::ErrorKind::InvalidData => ErrorKind::InvalidData,
175+
std::io::ErrorKind::StorageFull => ErrorKind::StorageFull,
162176
std::io::ErrorKind::TimedOut => ErrorKind::TimedOut,
163177
std::io::ErrorKind::Interrupted => ErrorKind::Interrupted,
164178
std::io::ErrorKind::Unsupported => ErrorKind::Unsupported,
179+
std::io::ErrorKind::UnexpectedEof => ErrorKind::UnexpectedEof,
165180
std::io::ErrorKind::OutOfMemory => ErrorKind::OutOfMemory,
166181
_ => ErrorKind::Other,
167182
}
@@ -172,17 +187,11 @@ impl From<std::io::ErrorKind> for ErrorKind {
172187
///
173188
/// This trait allows generic code to do limited inspecting of errors,
174189
/// to react differently to different kinds.
175-
pub trait Error: core::error::Error {
190+
pub trait Error: core::error::Error + From<ErrorKind> {
176191
/// Get the kind of this error.
177192
fn kind(&self) -> ErrorKind;
178193
}
179194

180-
impl Error for core::convert::Infallible {
181-
fn kind(&self) -> ErrorKind {
182-
match *self {}
183-
}
184-
}
185-
186195
impl Error for ErrorKind {
187196
fn kind(&self) -> ErrorKind {
188197
*self
@@ -223,44 +232,6 @@ impl<T: ?Sized + ErrorType> ErrorType for &mut T {
223232
type Error = T::Error;
224233
}
225234

226-
/// Error returned by [`Read::read_exact`]
227-
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
228-
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
229-
pub enum ReadExactError<E> {
230-
/// An EOF error was encountered before reading the exact amount of requested bytes.
231-
UnexpectedEof,
232-
/// Error returned by the inner Read.
233-
Other(E),
234-
}
235-
236-
impl<E> From<E> for ReadExactError<E> {
237-
fn from(err: E) -> Self {
238-
Self::Other(err)
239-
}
240-
}
241-
242-
#[cfg(feature = "std")]
243-
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
244-
impl From<ReadExactError<std::io::Error>> for std::io::Error {
245-
fn from(err: ReadExactError<std::io::Error>) -> Self {
246-
match err {
247-
ReadExactError::UnexpectedEof => std::io::Error::new(
248-
std::io::ErrorKind::UnexpectedEof,
249-
"UnexpectedEof".to_owned(),
250-
),
251-
ReadExactError::Other(e) => std::io::Error::new(e.kind(), format!("{e:?}")),
252-
}
253-
}
254-
}
255-
256-
impl<E: fmt::Debug> fmt::Display for ReadExactError<E> {
257-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
258-
write!(f, "{self:?}")
259-
}
260-
}
261-
262-
impl<E: fmt::Debug> core::error::Error for ReadExactError<E> {}
263-
264235
/// Errors that could be returned by `Write` on `&mut [u8]`.
265236
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
266237
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -326,6 +297,15 @@ pub trait Read: ErrorType {
326297
///
327298
/// If `buf.len() == 0`, `read` returns without blocking, with either `Ok(0)` or an error.
328299
/// The `Ok(0)` doesn't indicate EOF, unlike when called with a non-empty buffer.
300+
///
301+
/// # Errors
302+
///
303+
/// If this function encounters any form of I/O or other error, an error
304+
/// variant will be returned. If an error is returned then it must be
305+
/// guaranteed that no bytes were read.
306+
///
307+
/// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read
308+
/// operation should be retried if there is nothing else to do.
329309
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
330310

331311
/// Read the exact number of bytes required to fill `buf`.
@@ -336,18 +316,31 @@ pub trait Read: ErrorType {
336316
/// If you are using [`ReadReady`] to avoid blocking, you should not use this function.
337317
/// `ReadReady::read_ready()` returning true only guarantees the first call to `read()` will
338318
/// not block, so this function may still block in subsequent calls.
339-
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), ReadExactError<Self::Error>> {
319+
////
320+
/// /// # Errors
321+
///
322+
/// If this function encounters an "end of file" before completely filling
323+
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
324+
/// The contents of `buf` are unspecified in this case.
325+
///
326+
/// If any other read error is encountered then this function immediately
327+
/// returns. The contents of `buf` are unspecified in this case.
328+
///
329+
/// If this function returns an error, it is unspecified how many bytes it
330+
/// has read, but it will never read more than would be necessary to
331+
/// completely fill the buffer.
332+
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Self::Error> {
340333
while !buf.is_empty() {
341334
match self.read(buf) {
342335
Ok(0) => break,
343336
Ok(n) => buf = &mut buf[n..],
344-
Err(e) => return Err(ReadExactError::Other(e)),
337+
Err(e) => return Err(e),
345338
}
346339
}
347340
if buf.is_empty() {
348341
Ok(())
349342
} else {
350-
Err(ReadExactError::UnexpectedEof)
343+
Err(ErrorKind::UnexpectedEof.into())
351344
}
352345
}
353346
}

0 commit comments

Comments
 (0)