Skip to content

Commit a4d49f5

Browse files
authored
Merge pull request #71 from yoshuawuyts/box-errs
Remove ErrorKind
2 parents 6f3706c + 01a2b2b commit a4d49f5

File tree

12 files changed

+174
-274
lines changed

12 files changed

+174
-274
lines changed

src/error.rs

Lines changed: 31 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use std::error::Error as StdError;
44
use std::fmt::{self, Debug, Display};
5-
use std::io;
65

76
use crate::StatusCode;
87

@@ -12,146 +11,9 @@ use crate::StatusCode;
1211
/// produce an error.
1312
pub type Result<T> = std::result::Result<T, Error>;
1413

15-
/// A list specifying general categories of HTTP errors.
16-
///
17-
/// This list is intended to grow over time and it is not recommended to
18-
/// exhaustively match against it.
19-
///
20-
/// It is used with the [`http_types::Error`] type.
21-
///
22-
/// [`http_types::Error`]: struct.Error.html
23-
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
24-
#[non_exhaustive]
25-
pub enum ErrorKind {
26-
/// An entity was not found, often a file.
27-
NotFound,
28-
/// The operation lacked the necessary privileges to complete.
29-
PermissionDenied,
30-
/// The connection was refused by the remote server.
31-
ConnectionRefused,
32-
/// The connection was reset by the remote server.
33-
ConnectionReset,
34-
/// The connection was aborted (terminated) by the remote server.
35-
ConnectionAborted,
36-
/// The network operation failed because it was not connected yet.
37-
NotConnected,
38-
/// A socket address could not be bound because the address is already in
39-
/// use elsewhere.
40-
AddrInUse,
41-
/// A nonexistent interface was requested or the requested address was not
42-
/// local.
43-
AddrNotAvailable,
44-
/// The operation failed because a pipe was closed.
45-
BrokenPipe,
46-
/// An entity already exists, often a file.
47-
AlreadyExists,
48-
/// The operation needs to block to complete, but the blocking operation was
49-
/// requested to not occur.
50-
WouldBlock,
51-
/// A parameter was incorrect.
52-
InvalidInput,
53-
/// Data not valid for the operation were encountered.
54-
///
55-
/// Unlike [`InvalidInput`], this typically means that the operation
56-
/// parameters were valid, however the error was caused by malformed
57-
/// input data.
58-
///
59-
/// For example, a function that reads a file into a string will error with
60-
/// `InvalidData` if the file's contents are not valid UTF-8.
61-
///
62-
/// [`InvalidInput`]: #variant.InvalidInput
63-
InvalidData,
64-
/// The I/O operation's timeout expired, causing it to be canceled.
65-
TimedOut,
66-
/// An error returned when an operation could not be completed because a
67-
/// call to [`write`] returned [`Ok(0)`].
68-
///
69-
/// This typically means that an operation could only succeed if it wrote a
70-
/// particular number of bytes but only a smaller number of bytes could be
71-
/// written.
72-
///
73-
/// [`write`]: ../../std/io/trait.Write.html#tymethod.write
74-
/// [`Ok(0)`]: ../../std/io/type.Result.html
75-
WriteZero,
76-
/// This operation was interrupted.
77-
///
78-
/// Interrupted operations can typically be retried.
79-
Interrupted,
80-
/// Any I/O error not part of this list.
81-
Other,
82-
83-
/// An error returned when an operation could not be completed because an
84-
/// "end of file" was reached prematurely.
85-
///
86-
/// This typically means that an operation could only succeed if it read a
87-
/// particular number of bytes but only a smaller number of bytes could be
88-
/// read.
89-
UnexpectedEof,
90-
}
91-
92-
impl From<io::ErrorKind> for ErrorKind {
93-
fn from(kind: io::ErrorKind) -> Self {
94-
match kind {
95-
io::ErrorKind::NotFound => ErrorKind::NotFound,
96-
io::ErrorKind::PermissionDenied => ErrorKind::PermissionDenied,
97-
io::ErrorKind::ConnectionRefused => ErrorKind::ConnectionRefused,
98-
io::ErrorKind::ConnectionReset => ErrorKind::ConnectionReset,
99-
io::ErrorKind::ConnectionAborted => ErrorKind::ConnectionAborted,
100-
io::ErrorKind::NotConnected => ErrorKind::NotConnected,
101-
io::ErrorKind::AddrInUse => ErrorKind::AddrInUse,
102-
io::ErrorKind::AddrNotAvailable => ErrorKind::AddrNotAvailable,
103-
io::ErrorKind::BrokenPipe => ErrorKind::BrokenPipe,
104-
io::ErrorKind::AlreadyExists => ErrorKind::AlreadyExists,
105-
io::ErrorKind::WouldBlock => ErrorKind::WouldBlock,
106-
io::ErrorKind::InvalidInput => ErrorKind::InvalidInput,
107-
io::ErrorKind::InvalidData => ErrorKind::InvalidData,
108-
io::ErrorKind::TimedOut => ErrorKind::TimedOut,
109-
io::ErrorKind::WriteZero => ErrorKind::WriteZero,
110-
io::ErrorKind::Interrupted => ErrorKind::Interrupted,
111-
io::ErrorKind::UnexpectedEof => ErrorKind::UnexpectedEof,
112-
io::ErrorKind::Other => ErrorKind::Other,
113-
_ => ErrorKind::Other,
114-
}
115-
}
116-
}
117-
118-
impl From<ErrorKind> for io::Error {
119-
fn from(kind: ErrorKind) -> Self {
120-
let kind = match kind {
121-
ErrorKind::NotFound => io::ErrorKind::NotFound,
122-
ErrorKind::PermissionDenied => io::ErrorKind::PermissionDenied,
123-
ErrorKind::ConnectionRefused => io::ErrorKind::ConnectionRefused,
124-
ErrorKind::ConnectionReset => io::ErrorKind::ConnectionReset,
125-
ErrorKind::ConnectionAborted => io::ErrorKind::ConnectionAborted,
126-
ErrorKind::NotConnected => io::ErrorKind::NotConnected,
127-
ErrorKind::AddrInUse => io::ErrorKind::AddrInUse,
128-
ErrorKind::AddrNotAvailable => io::ErrorKind::AddrNotAvailable,
129-
ErrorKind::BrokenPipe => io::ErrorKind::BrokenPipe,
130-
ErrorKind::AlreadyExists => io::ErrorKind::AlreadyExists,
131-
ErrorKind::WouldBlock => io::ErrorKind::WouldBlock,
132-
ErrorKind::InvalidInput => io::ErrorKind::InvalidInput,
133-
ErrorKind::InvalidData => io::ErrorKind::InvalidData,
134-
ErrorKind::TimedOut => io::ErrorKind::TimedOut,
135-
ErrorKind::WriteZero => io::ErrorKind::WriteZero,
136-
ErrorKind::Interrupted => io::ErrorKind::Interrupted,
137-
ErrorKind::UnexpectedEof => io::ErrorKind::UnexpectedEof,
138-
ErrorKind::Other => io::ErrorKind::Other,
139-
};
140-
io::Error::from(kind)
141-
}
142-
}
143-
144-
/// Internal representation of the error state.
145-
#[derive(Debug)]
146-
enum Repr {
147-
Io(io::Error),
148-
Custom(anyhow::Error),
149-
}
150-
15114
/// The error type for HTTP operations.
15215
pub struct Error {
153-
repr: Repr,
154-
kind: ErrorKind,
16+
error: anyhow::Error,
15517
status: crate::StatusCode,
15618
}
15719

@@ -161,27 +23,24 @@ impl Error {
16123
/// The error type must be threadsafe and 'static, so that the Error will be
16224
/// as well. If the error type does not provide a backtrace, a backtrace will
16325
/// be created here to ensure that a backtrace exists.
164-
pub fn new<E>(kind: ErrorKind, error: E, status: StatusCode) -> Self
26+
pub fn new<E>(status: StatusCode, error: E) -> Self
16527
where
16628
E: StdError + Send + Sync + 'static,
16729
{
168-
let error = anyhow::Error::new(error);
16930
Self {
170-
kind,
171-
repr: Repr::Custom(error),
17231
status,
32+
error: anyhow::Error::new(error),
17333
}
17434
}
17535

17636
/// Create a new error object from static string.
177-
pub fn from_str<M>(kind: ErrorKind, msg: M, status: StatusCode) -> Self
37+
pub fn from_str<M>(status: StatusCode, msg: M) -> Self
17838
where
17939
M: Display + Debug + Send + Sync + 'static,
18040
{
18141
Self {
182-
kind,
183-
repr: Repr::Custom(anyhow::format_err!(msg)),
18442
status,
43+
error: anyhow::Error::msg(msg),
18544
}
18645
}
18746

@@ -190,16 +49,7 @@ impl Error {
19049
where
19150
M: Display + Debug + Send + Sync + 'static,
19251
{
193-
Self::from_str(ErrorKind::Other, message, StatusCode::InternalServerError)
194-
}
195-
196-
/// Create a new error object from an I/O error.
197-
pub fn from_io(error: std::io::Error, status: StatusCode) -> Self {
198-
Self {
199-
kind: error.kind().into(),
200-
repr: Repr::Io(error),
201-
status,
202-
}
52+
Self::from_str(StatusCode::InternalServerError, message)
20353
}
20454

20555
/// Get the status code associated with this error.
@@ -212,11 +62,6 @@ impl Error {
21262
self.status = status;
21363
}
21464

215-
/// Returns the corresponding ErrorKind for this error.
216-
pub fn kind(&self) -> ErrorKind {
217-
self.kind.clone()
218-
}
219-
22065
/// Get the backtrace for this Error.
22166
///
22267
/// Backtraces are only available on the nightly channel. Tracking issue:
@@ -230,21 +75,18 @@ impl Error {
23075
/// [tracking]: https://github.com/rust-lang/rust/issues/53487
23176
#[cfg(backtrace)]
23277
pub fn backtrace(&self) -> &std::backtrace::Backtrace {
233-
match self {
234-
Repr::Io => std::backtrace::Backtrace::capture(),
235-
Repr::Custom(err) => err.backtrace(),
236-
}
78+
self.error.downcast_ref::<E>()
23779
}
23880

23981
/// Attempt to downcast the error object to a concrete type.
24082
pub fn downcast<E>(self) -> std::result::Result<E, Self>
24183
where
24284
E: Display + Debug + Send + Sync + 'static,
24385
{
244-
match self.repr {
245-
Repr::Io(err) => Ok(anyhow::Error::new(err).downcast().unwrap()),
246-
Repr::Custom(err) if err.downcast_ref::<E>().is_some() => Ok(err.downcast().unwrap()),
247-
_ => Err(self),
86+
if self.error.downcast_ref::<E>().is_some() {
87+
Ok(self.error.downcast().unwrap())
88+
} else {
89+
Err(self)
24890
}
24991
}
25092

@@ -253,39 +95,27 @@ impl Error {
25395
where
25496
E: Display + Debug + Send + Sync + 'static,
25597
{
256-
match self.repr {
257-
Repr::Custom(ref err) => err.downcast_ref::<E>(),
258-
_ => None,
259-
}
98+
self.error.downcast_ref::<E>()
26099
}
261100

262101
/// Downcast this error object by mutable reference.
263102
pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
264103
where
265104
E: Display + Debug + Send + Sync + 'static,
266105
{
267-
match self.repr {
268-
Repr::Custom(ref mut err) => err.downcast_mut::<E>(),
269-
_ => None,
270-
}
106+
self.error.downcast_mut::<E>()
271107
}
272108
}
273109

274110
impl Display for Error {
275111
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
276-
match &self.repr {
277-
Repr::Io(io) => write!(formatter, "{}", io),
278-
Repr::Custom(err) => write!(formatter, "{}", err),
279-
}
112+
write!(formatter, "{}", self.error)
280113
}
281114
}
282115

283116
impl Debug for Error {
284117
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
285-
match &self.repr {
286-
Repr::Io(io) => write!(formatter, "{}", io),
287-
Repr::Custom(err) => write!(formatter, "{}", err),
288-
}
118+
write!(formatter, "{}", self.error)
289119
}
290120
}
291121

@@ -295,52 +125,44 @@ where
295125
{
296126
fn from(error: E) -> Self {
297127
Self {
298-
kind: ErrorKind::Other,
299-
repr: Repr::Custom(anyhow::Error::new(error)),
128+
error: anyhow::Error::new(error),
300129
status: StatusCode::InternalServerError,
301130
}
302131
}
303132
}
304133

305-
impl From<ErrorKind> for Error {
306-
fn from(kind: ErrorKind) -> Self {
307-
Self {
308-
kind: kind.clone(),
309-
repr: Repr::Io(kind.into()),
310-
status: StatusCode::InternalServerError,
311-
}
134+
impl AsRef<dyn StdError + Send + Sync> for Error {
135+
fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
136+
self.error.as_ref()
312137
}
313138
}
314139

315-
impl AsRef<dyn StdError + Send + Sync> for Error {
316-
fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
317-
match &self.repr {
318-
Repr::Io(ref io) => io,
319-
Repr::Custom(ref err) => err.as_ref(),
320-
}
140+
impl AsRef<StatusCode> for Error {
141+
fn as_ref(&self) -> &StatusCode {
142+
&self.status
143+
}
144+
}
145+
146+
impl AsMut<StatusCode> for Error {
147+
fn as_mut(&mut self) -> &mut StatusCode {
148+
&mut self.status
321149
}
322150
}
323151

324152
impl AsRef<dyn StdError> for Error {
325153
fn as_ref(&self) -> &(dyn StdError + 'static) {
326-
match &self.repr {
327-
Repr::Io(ref io) => io,
328-
Repr::Custom(ref err) => err.as_ref(),
329-
}
154+
self.error.as_ref()
330155
}
331156
}
332157

333158
impl From<Error> for Box<dyn StdError + Send + Sync + 'static> {
334159
fn from(error: Error) -> Self {
335-
match error.repr {
336-
Repr::Io(io) => io.into(),
337-
Repr::Custom(err) => err.into(),
338-
}
160+
error.error.into()
339161
}
340162
}
341163

342164
impl From<Error> for Box<dyn StdError + 'static> {
343165
fn from(error: Error) -> Self {
344-
Box::<dyn StdError + Send + Sync>::from(error)
166+
Box::<dyn StdError + Send + Sync>::from(error.error)
345167
}
346168
}

src/headers/header_name.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::borrow::Cow;
22
use std::fmt::{self, Debug, Display};
33
use std::str::FromStr;
44

5-
use crate::{Error, ErrorKind};
5+
use crate::Error;
66

77
/// A header name.
88
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
@@ -11,11 +11,11 @@ pub struct HeaderName(Cow<'static, str>);
1111
impl HeaderName {
1212
/// Create a new `HeaderName`.
1313
pub fn from_ascii(mut bytes: Vec<u8>) -> Result<Self, Error> {
14-
if !bytes.is_ascii() {
15-
return Err(Error::from(ErrorKind::InvalidData));
16-
}
14+
crate::ensure!(bytes.is_ascii(), "Bytes should be valid ASCII");
1715
bytes.make_ascii_lowercase();
18-
let string = String::from_utf8(bytes).map_err(|_| Error::from(ErrorKind::InvalidData))?;
16+
17+
// This is permitted because ASCII is valid UTF-8, and we just checked that.
18+
let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) };
1919
Ok(HeaderName(Cow::Owned(string)))
2020
}
2121

@@ -58,9 +58,7 @@ impl FromStr for HeaderName {
5858
///
5959
/// This checks it's valid ASCII, and lowercases it.
6060
fn from_str(s: &str) -> Result<Self, Self::Err> {
61-
if !s.is_ascii() {
62-
return Err(Error::from(ErrorKind::InvalidData));
63-
}
61+
crate::ensure!(s.is_ascii(), "String slice should be valid ASCII");
6462
Ok(HeaderName(Cow::Owned(s.to_ascii_lowercase())))
6563
}
6664
}

0 commit comments

Comments
 (0)