1use crate::{Body, InMemoryResponse, InMemoryResponseExt, Response};
2use http::StatusCode;
3use std::fmt::{Debug, Display, Formatter};
4use std::str::Utf8Error;
5use std::string::FromUtf8Error;
6
7pub type Result<T = Response, E = Error> = std::result::Result<T, E>;
8pub type InMemoryError = Error<InMemoryResponse>;
9pub type InMemoryResult<T> = Result<T, InMemoryError>;
10pub type ProtocolResult<T> = Result<T, ProtocolError>;
11
12#[derive(Debug)]
13pub enum ProtocolError {
14 ConnectionError(hyper::Error),
15 Utf8Error(Utf8Error),
16 JsonError(serde_json::Error),
17 IoError(std::io::Error),
18 TooManyRedirects,
19 TooManyRetries,
20}
21
22impl std::error::Error for ProtocolError {}
23
24impl Display for ProtocolError {
25 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
26 match self {
27 ProtocolError::ConnectionError(e) => write!(f, "ConnectionError: {e}"),
28 ProtocolError::Utf8Error(e) => write!(f, "Utf8Error: {e}"),
29 ProtocolError::JsonError(e) => write!(f, "JsonError: {e}"),
30 ProtocolError::IoError(e) => write!(f, "IoError: {e}"),
31 ProtocolError::TooManyRedirects => write!(f, "TooManyRedirects"),
32 ProtocolError::TooManyRetries => write!(f, "TooManyRetries"),
33 }
34 }
35}
36
37#[derive(Debug)]
38pub enum Error<T = Response> {
39 Protocol(ProtocolError),
40 HttpError(T),
41}
42
43impl Error<InMemoryResponse> {
44 #[must_use]
45 pub fn status(&self) -> Option<StatusCode> {
46 match self {
47 Error::HttpError(r) => Some(r.status()),
48 Error::Protocol(_) => None,
49 }
50 }
51}
52
53impl Error {
54 pub fn status(&self) -> Option<StatusCode> {
56 match self {
57 Error::HttpError(r) => Some(r.status()),
58 Error::Protocol(_) => None,
59 }
60 }
61
62 pub async fn into_content(self) -> InMemoryError {
63 match self {
64 Error::HttpError(r) => {
65 let (parts, body) = r.into_parts();
66 let content_type = parts.headers.get(http::header::CONTENT_TYPE);
67 let body = match body.into_content_type(content_type).await {
68 Ok(body) => body,
69 Err(e) => return e.into(),
70 };
71 Error::HttpError(InMemoryResponse::from_parts(parts, body))
72 }
73 Error::Protocol(e) => Error::Protocol(e),
74 }
75 }
76}
77
78impl InMemoryError {
79 #[must_use]
80 pub fn transform_error<T>(self) -> Error<T>
81 where
82 T: TryFrom<InMemoryResponse>,
83 T::Error: Into<Error<T>>,
84 {
85 match self {
86 InMemoryError::Protocol(e) => Error::Protocol(e),
87 InMemoryError::HttpError(e) => match e.try_into() {
88 Ok(r) => Error::HttpError(r),
89 Err(e) => e.into(),
90 },
91 }
92 }
93
94 #[must_use]
95 pub fn into_text(self) -> String {
96 match self {
97 InMemoryError::Protocol(e) => e.to_string(),
98 InMemoryError::HttpError(r) => r.text().unwrap_or_else(|e| format!("Error reading body as text: {e}")),
99 }
100 }
101}
102
103impl From<InMemoryError> for Error {
104 fn from(value: InMemoryError) -> Self {
105 match value {
106 Error::HttpError(r) => {
107 let (parts, body) = r.into_parts();
108 let body: Body = body.into();
109 let r = crate::Response::from_parts(parts, body);
110 Error::HttpError(r)
111 }
112 Error::Protocol(e) => Error::Protocol(e),
113 }
114 }
115}
116
117impl Display for InMemoryError {
118 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
119 match self {
120 Error::HttpError(r) => {
121 let body = r.body().text().ok().unwrap_or_else(|| format!("{:?}", r).into());
122 write!(f, "HttpError: {body}")
123 }
124 Error::Protocol(p) => write!(f, "ProtocolError: {p}"),
125 }
126 }
127}
128
129impl std::error::Error for InMemoryError {}
130
131impl serde::de::Error for InMemoryError {
132 fn custom<T: Display>(msg: T) -> Self {
133 Error::Protocol(ProtocolError::JsonError(serde_json::Error::custom(msg.to_string())))
134 }
135}
136
137impl<T> From<serde_json::Error> for Error<T> {
138 fn from(value: serde_json::Error) -> Self {
139 Error::Protocol(ProtocolError::JsonError(value))
140 }
141}
142
143impl From<std::io::Error> for ProtocolError {
144 fn from(value: std::io::Error) -> Self {
145 ProtocolError::IoError(value)
146 }
147}
148
149impl<T> From<hyper::Error> for Error<T> {
150 fn from(value: hyper::Error) -> Self {
151 Error::Protocol(ProtocolError::ConnectionError(value))
152 }
153}
154
155impl<T> From<hyper_util::client::legacy::Error> for Error<T> {
156 fn from(value: hyper_util::client::legacy::Error) -> Self {
157 Error::Protocol(ProtocolError::IoError(std::io::Error::new(std::io::ErrorKind::Other, value.to_string())))
158 }
159}
160
161impl<T> From<FromUtf8Error> for Error<T> {
162 fn from(value: FromUtf8Error) -> Self {
163 Error::Protocol(ProtocolError::Utf8Error(value.utf8_error()))
164 }
165}
166impl<T> From<ProtocolError> for Error<T> {
167 fn from(value: ProtocolError) -> Self {
168 Error::Protocol(value)
169 }
170}
171impl<T> From<Utf8Error> for Error<T> {
172 fn from(value: Utf8Error) -> Self {
173 Error::Protocol(ProtocolError::Utf8Error(value))
174 }
175}
176
177impl From<hyper::Error> for ProtocolError {
178 fn from(value: hyper::Error) -> Self {
179 Self::ConnectionError(value)
180 }
181}
182
183impl From<hyper_util::client::legacy::Error> for ProtocolError {
184 fn from(value: hyper_util::client::legacy::Error) -> Self {
185 Self::IoError(std::io::Error::new(std::io::ErrorKind::Other, value.to_string()))
186 }
187}
188
189impl From<serde_json::Error> for ProtocolError {
190 fn from(value: serde_json::Error) -> Self {
191 Self::JsonError(value)
192 }
193}
194
195impl From<FromUtf8Error> for ProtocolError {
196 fn from(value: FromUtf8Error) -> Self {
197 Self::Utf8Error(value.utf8_error())
198 }
199}
200
201impl From<Utf8Error> for ProtocolError {
202 fn from(value: Utf8Error) -> Self {
203 Self::Utf8Error(value)
204 }
205}