Skip to content

Commit 2bf3e0e

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

File tree

6 files changed

+84
-71
lines changed

6 files changed

+84
-71
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/impls/vec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use crate::{ErrorType, Write};
1+
use crate::{ErrorKind, ErrorType, Write};
22
use alloc::vec::Vec;
33

44
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]
55
impl ErrorType for Vec<u8> {
6-
type Error = core::convert::Infallible;
6+
type Error = ErrorKind;
77
}
88

99
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "alloc"))))]

embedded-io/src/lib.rs

Lines changed: 49 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
@@ -205,6 +214,14 @@ impl Error for std::io::Error {
205214
}
206215
}
207216

217+
#[cfg(feature = "std")]
218+
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
219+
impl From<ErrorKimd> for std::io::Error {
220+
fn from(value: ErrorKimd) -> Self {
221+
std::io::ErrorKind::from(value).into()
222+
}
223+
}
224+
208225
/// Base trait for all IO traits, defining the error type.
209226
///
210227
/// All IO operations of all traits return the error defined in this trait.
@@ -223,44 +240,6 @@ impl<T: ?Sized + ErrorType> ErrorType for &mut T {
223240
type Error = T::Error;
224241
}
225242

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-
264243
/// Errors that could be returned by `Write` on `&mut [u8]`.
265244
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
266245
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -326,6 +305,15 @@ pub trait Read: ErrorType {
326305
///
327306
/// If `buf.len() == 0`, `read` returns without blocking, with either `Ok(0)` or an error.
328307
/// The `Ok(0)` doesn't indicate EOF, unlike when called with a non-empty buffer.
308+
///
309+
/// # Errors
310+
///
311+
/// If this function encounters any form of I/O or other error, an error
312+
/// variant will be returned. If an error is returned then it must be
313+
/// guaranteed that no bytes were read.
314+
///
315+
/// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read
316+
/// operation should be retried if there is nothing else to do.
329317
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
330318

331319
/// Read the exact number of bytes required to fill `buf`.
@@ -336,18 +324,31 @@ pub trait Read: ErrorType {
336324
/// If you are using [`ReadReady`] to avoid blocking, you should not use this function.
337325
/// `ReadReady::read_ready()` returning true only guarantees the first call to `read()` will
338326
/// 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>> {
327+
////
328+
/// /// # Errors
329+
///
330+
/// If this function encounters an "end of file" before completely filling
331+
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
332+
/// The contents of `buf` are unspecified in this case.
333+
///
334+
/// If any other read error is encountered then this function immediately
335+
/// returns. The contents of `buf` are unspecified in this case.
336+
///
337+
/// If this function returns an error, it is unspecified how many bytes it
338+
/// has read, but it will never read more than would be necessary to
339+
/// completely fill the buffer.
340+
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Self::Error> {
340341
while !buf.is_empty() {
341342
match self.read(buf) {
342343
Ok(0) => break,
343344
Ok(n) => buf = &mut buf[n..],
344-
Err(e) => return Err(ReadExactError::Other(e)),
345+
Err(e) => return Err(e),
345346
}
346347
}
347348
if buf.is_empty() {
348349
Ok(())
349350
} else {
350-
Err(ReadExactError::UnexpectedEof)
351+
Err(ErrorKind::UnexpectedEof.into())
351352
}
352353
}
353354
}

0 commit comments

Comments
 (0)