1use http::StatusCode;
20use std::error::Error as StdError;
21use std::fmt::{Display, Formatter};
22
23pub type Result<T> = std::result::Result<T, Error>;
24
25#[derive(Debug, Clone, PartialEq)]
26pub struct Error {
27 inner: ErrorImpl,
28}
29
30impl Display for Error {
31 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
32 write!(f, "{}", self.inner.kind)
33 }
34}
35
36impl StdError for Error {}
37
38impl Error {
39 pub(crate) fn new_server_error(e: ServerError) -> Error {
40 Self {
41 inner: ErrorImpl {
42 kind: Box::new(ErrorKind::Server(e)),
43 },
44 }
45 }
46
47 pub(crate) fn new_message_error(
48 msg: impl Into<String>,
49 endpoint: impl Into<Option<String>>,
50 ) -> Error {
51 Self {
52 inner: ErrorImpl {
53 kind: Box::new(ErrorKind::Message {
54 msg: msg.into(),
55 endpoint: endpoint.into(),
56 }),
57 },
58 }
59 }
60
61 pub(crate) fn new_encoding_error(msg: impl Into<String>) -> Error {
62 Self {
63 inner: ErrorImpl {
64 kind: Box::new(ErrorKind::Encoding { msg: msg.into() }),
65 },
66 }
67 }
68
69 pub(crate) fn new_invalid_argument_error(
70 msg: impl Into<String>,
71 arg: impl Into<Option<String>>,
72 ) -> Self {
73 Self {
74 inner: ErrorImpl {
75 kind: Box::new(ErrorKind::InvalidArgument {
76 msg: msg.into(),
77 arg: arg.into(),
78 }),
79 },
80 }
81 }
82
83 pub(crate) fn new_http_error(endpoint: impl Into<String>) -> Self {
84 Self {
85 inner: ErrorImpl {
86 kind: Box::new(ErrorKind::Http {
87 endpoint: endpoint.into(),
88 }),
89 },
90 }
91 }
92
93 pub(crate) fn new_unsupported_feature_error(feature: String) -> Self {
94 Self {
95 inner: ErrorImpl {
96 kind: Box::new(ErrorKind::UnsupportedFeature { feature }),
97 },
98 }
99 }
100
101 pub fn kind(&self) -> &ErrorKind {
102 &self.inner.kind
103 }
104}
105
106#[derive(Debug, Clone)]
107struct ErrorImpl {
108 kind: Box<ErrorKind>,
109}
110
111impl PartialEq for ErrorImpl {
112 fn eq(&self, other: &Self) -> bool {
113 self.kind == other.kind
114 }
115}
116
117#[derive(Clone, Debug, PartialEq, Eq)]
118#[non_exhaustive]
119pub enum ErrorKind {
120 Server(ServerError),
121 #[non_exhaustive]
122 Http {
123 endpoint: String,
124 },
125 #[non_exhaustive]
126 Message {
127 msg: String,
128 endpoint: Option<String>,
129 },
130 #[non_exhaustive]
131 InvalidArgument {
132 msg: String,
133 arg: Option<String>,
134 },
135 #[non_exhaustive]
136 Encoding {
137 msg: String,
138 },
139 UnsupportedFeature {
140 feature: String,
141 },
142}
143
144impl Display for ErrorKind {
145 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
146 match self {
147 ErrorKind::Server(e) => write!(f, "{e}"),
148 ErrorKind::Http { endpoint } => write!(f, "http error for endpoint {endpoint}"),
149 ErrorKind::Message { msg, endpoint } => {
150 if let Some(endpoint) = endpoint {
151 write!(f, "message error for endpoint {endpoint}: {msg}")
152 } else {
153 write!(f, "message error: {msg}")
154 }
155 }
156 ErrorKind::InvalidArgument { msg, arg } => {
157 if let Some(arg) = arg {
158 write!(f, "invalid argument error for argument {arg}: {msg}")
159 } else {
160 write!(f, "invalid argument error: {msg}")
161 }
162 }
163 ErrorKind::Encoding { msg } => write!(f, "encoding error: {msg}"),
164 ErrorKind::UnsupportedFeature { feature } => {
165 write!(f, "unsupported feature: {feature}")
166 }
167 }
168 }
169}
170
171#[derive(Clone, Debug, PartialEq, Eq)]
172pub struct ServerError {
173 kind: ServerErrorKind,
174
175 index_name: String,
176
177 error_text: String,
178 endpoint: String,
179 status_code: StatusCode,
180}
181
182impl Display for ServerError {
183 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
184 write!(
185 f,
186 "server error for index {} at endpoint {}, status code: {}: {}, error text: {}",
187 self.index_name, self.endpoint, self.status_code, self.kind, self.error_text
188 )
189 }
190}
191
192impl ServerError {
193 pub(crate) fn new(
194 kind: ServerErrorKind,
195 index_name: impl Into<String>,
196 error_text: impl Into<String>,
197 endpoint: impl Into<String>,
198 status_code: StatusCode,
199 ) -> Self {
200 Self {
201 kind,
202 error_text: error_text.into(),
203 index_name: index_name.into(),
204 endpoint: endpoint.into(),
205 status_code,
206 }
207 }
208
209 pub fn kind(&self) -> &ServerErrorKind {
210 &self.kind
211 }
212
213 pub fn index_name(&self) -> &str {
214 &self.index_name
215 }
216
217 pub fn endpoint(&self) -> &str {
218 &self.endpoint
219 }
220
221 pub fn status_code(&self) -> StatusCode {
222 self.status_code
223 }
224
225 pub fn error_text(&self) -> &str {
226 &self.error_text
227 }
228}
229
230#[derive(Clone, Debug, PartialEq, Eq)]
231#[non_exhaustive]
232pub enum ServerErrorKind {
233 Internal,
234 AuthenticationFailure,
235 IndexExists,
236 IndexNotFound,
237 UnknownIndexType,
238 SourceTypeIncorrect,
239 SourceNotFound,
240 NoIndexPartitionsPlanned,
241 NoIndexPartitionsFound,
242 UnsupportedFeature,
243 RateLimitedFailure,
244 Unknown,
245}
246
247impl Display for ServerErrorKind {
248 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
249 match self {
250 ServerErrorKind::Internal => write!(f, "internal server error"),
251 ServerErrorKind::AuthenticationFailure => write!(f, "authentication failure"),
252 ServerErrorKind::IndexExists => write!(f, "index exists"),
253 ServerErrorKind::IndexNotFound => write!(f, "index not found"),
254 ServerErrorKind::UnknownIndexType => write!(f, "unknown index type"),
255 ServerErrorKind::SourceTypeIncorrect => write!(f, "source type incorrect"),
256 ServerErrorKind::SourceNotFound => write!(f, "source not found"),
257 ServerErrorKind::NoIndexPartitionsPlanned => write!(f, "no index partitions planned"),
258 ServerErrorKind::NoIndexPartitionsFound => write!(f, "no index partitions found"),
259 ServerErrorKind::UnsupportedFeature => write!(f, "unsupported feature"),
260 ServerErrorKind::RateLimitedFailure => write!(f, "rate limited failure"),
261 ServerErrorKind::Unknown => write!(f, "unknown error"),
262 }
263 }
264}