blob: 03d98cf7efc4f5feec08587284dd8223259c062c [file] [log] [blame]
Allen George8b96bfb2016-11-02 08:01:08 -04001// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
Allen George55c3e4c2021-03-01 23:19:52 -050018use std::convert::TryFrom;
Allen George8b96bfb2016-11-02 08:01:08 -040019use std::convert::{From, Into};
20use std::error::Error as StdError;
21use std::fmt::{Debug, Display, Formatter};
22use std::{error, fmt, io, string};
Allen George8b96bfb2016-11-02 08:01:08 -040023
Allen George55c3e4c2021-03-01 23:19:52 -050024use crate::protocol::{
25 TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentifier, TType,
26};
Allen George8b96bfb2016-11-02 08:01:08 -040027
28// FIXME: should all my error structs impl error::Error as well?
29// FIXME: should all fields in TransportError, ProtocolError and ApplicationError be optional?
30
31/// Error type returned by all runtime library functions.
32///
33/// `thrift::Error` is used throughout this crate as well as in auto-generated
34/// Rust code. It consists of four variants defined by convention across Thrift
35/// implementations:
36///
37/// 1. `Transport`: errors encountered while operating on I/O channels
38/// 2. `Protocol`: errors encountered during runtime-library processing
39/// 3. `Application`: errors encountered within auto-generated code
40/// 4. `User`: IDL-defined exception structs
41///
42/// The `Application` variant also functions as a catch-all: all handler errors
43/// are automatically turned into application errors.
44///
45/// All error variants except `Error::User` take an eponymous struct with two
46/// required fields:
47///
48/// 1. `kind`: variant-specific enum identifying the error sub-type
49/// 2. `message`: human-readable error info string
50///
51/// `kind` is defined by convention while `message` is freeform. If none of the
52/// enumerated kinds are suitable use `Unknown`.
53///
54/// To simplify error creation convenience constructors are defined for all
55/// variants, and conversions from their structs (`thrift::TransportError`,
56/// `thrift::ProtocolError` and `thrift::ApplicationError` into `thrift::Error`.
57///
58/// # Examples
59///
60/// Create a `TransportError`.
61///
62/// ```
Allen George8b96bfb2016-11-02 08:01:08 -040063/// use thrift::{TransportError, TransportErrorKind};
64///
65/// // explicit
66/// let err0: thrift::Result<()> = Err(
67/// thrift::Error::Transport(
68/// TransportError {
69/// kind: TransportErrorKind::TimedOut,
70/// message: format!("connection to server timed out")
71/// }
72/// )
73/// );
74///
75/// // use conversion
76/// let err1: thrift::Result<()> = Err(
77/// thrift::Error::from(
78/// TransportError {
79/// kind: TransportErrorKind::TimedOut,
80/// message: format!("connection to server timed out")
81/// }
82/// )
83/// );
84///
85/// // use struct constructor
86/// let err2: thrift::Result<()> = Err(
87/// thrift::Error::Transport(
88/// TransportError::new(
89/// TransportErrorKind::TimedOut,
90/// "connection to server timed out"
91/// )
92/// )
93/// );
94///
95///
96/// // use error variant constructor
97/// let err3: thrift::Result<()> = Err(
98/// thrift::new_transport_error(
99/// TransportErrorKind::TimedOut,
100/// "connection to server timed out"
101/// )
102/// );
103/// ```
104///
105/// Create an error from a string.
106///
107/// ```
Allen George8b96bfb2016-11-02 08:01:08 -0400108/// use thrift::{ApplicationError, ApplicationErrorKind};
109///
110/// // we just use `From::from` to convert a `String` into a `thrift::Error`
111/// let err0: thrift::Result<()> = Err(
112/// thrift::Error::from("This is an error")
113/// );
114///
115/// // err0 is equivalent to...
116/// let err1: thrift::Result<()> = Err(
117/// thrift::Error::Application(
118/// ApplicationError {
119/// kind: ApplicationErrorKind::Unknown,
120/// message: format!("This is an error")
121/// }
122/// )
123/// );
124/// ```
125///
126/// Return an IDL-defined exception.
127///
128/// ```text
129/// // Thrift IDL exception definition.
130/// exception Xception {
131/// 1: i32 errorCode,
132/// 2: string message
133/// }
134/// ```
135///
136/// ```
Allen George8b96bfb2016-11-02 08:01:08 -0400137/// use std::error::Error;
138/// use std::fmt;
139/// use std::fmt::{Display, Formatter};
140///
141/// // auto-generated by the Thrift compiler
142/// #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
143/// pub struct Xception {
144/// pub error_code: Option<i32>,
145/// pub message: Option<String>,
146/// }
147///
148/// // auto-generated by the Thrift compiler
149/// impl Error for Xception {
150/// fn description(&self) -> &str {
151/// "remote service threw Xception"
152/// }
153/// }
154///
155/// // auto-generated by the Thrift compiler
156/// impl From<Xception> for thrift::Error {
157/// fn from(e: Xception) -> Self {
158/// thrift::Error::User(Box::new(e))
159/// }
160/// }
161///
162/// // auto-generated by the Thrift compiler
163/// impl Display for Xception {
164/// fn fmt(&self, f: &mut Formatter) -> fmt::Result {
165/// self.description().fmt(f)
166/// }
167/// }
168///
169/// // in user code...
170/// let err: thrift::Result<()> = Err(
171/// thrift::Error::from(Xception { error_code: Some(1), message: None })
172/// );
173/// ```
174pub enum Error {
175 /// Errors encountered while operating on I/O channels.
176 ///
177 /// These include *connection closed* and *bind failure*.
178 Transport(TransportError),
179 /// Errors encountered during runtime-library processing.
180 ///
181 /// These include *message too large* and *unsupported protocol version*.
182 Protocol(ProtocolError),
183 /// Errors encountered within auto-generated code, or when incoming
184 /// or outgoing messages violate the Thrift spec.
185 ///
186 /// These include *out-of-order messages* and *missing required struct
187 /// fields*.
188 ///
189 /// This variant also functions as a catch-all: errors from handler
190 /// functions are automatically returned as an `ApplicationError`.
191 Application(ApplicationError),
192 /// IDL-defined exception structs.
Danny Browning77d96c12019-08-21 13:41:07 -0600193 User(Box<dyn error::Error + Sync + Send>),
Allen George8b96bfb2016-11-02 08:01:08 -0400194}
195
196impl Error {
197 /// Create an `ApplicationError` from its wire representation.
198 ///
199 /// Application code **should never** call this method directly.
Allen Georgeef7a1892018-12-16 18:01:37 -0500200 pub fn read_application_error_from_in_protocol(
Danny Browning77d96c12019-08-21 13:41:07 -0600201 i: &mut dyn TInputProtocol,
Allen Georgeb0d14132020-03-29 11:48:55 -0400202 ) -> crate::Result<ApplicationError> {
Allen George8b96bfb2016-11-02 08:01:08 -0400203 let mut message = "general remote error".to_owned();
204 let mut kind = ApplicationErrorKind::Unknown;
205
206 i.read_struct_begin()?;
207
208 loop {
209 let field_ident = i.read_field_begin()?;
210
211 if field_ident.field_type == TType::Stop {
212 break;
213 }
214
Allen George0e22c362017-01-30 07:15:00 -0500215 let id = field_ident
216 .id
217 .expect("sender should always specify id for non-STOP field");
Allen George8b96bfb2016-11-02 08:01:08 -0400218
219 match id {
220 1 => {
221 let remote_message = i.read_string()?;
222 i.read_field_end()?;
223 message = remote_message;
224 }
225 2 => {
226 let remote_type_as_int = i.read_i32()?;
Allen Georgeef7a1892018-12-16 18:01:37 -0500227 let remote_kind: ApplicationErrorKind = TryFrom::try_from(remote_type_as_int)
228 .unwrap_or(ApplicationErrorKind::Unknown);
Allen George8b96bfb2016-11-02 08:01:08 -0400229 i.read_field_end()?;
230 kind = remote_kind;
231 }
232 _ => {
233 i.skip(field_ident.field_type)?;
234 }
235 }
236 }
237
238 i.read_struct_end()?;
239
Allen George55c3e4c2021-03-01 23:19:52 -0500240 Ok(ApplicationError { kind, message })
Allen George8b96bfb2016-11-02 08:01:08 -0400241 }
242
243 /// Convert an `ApplicationError` into its wire representation and write
244 /// it to the remote.
245 ///
246 /// Application code **should never** call this method directly.
Allen George0e22c362017-01-30 07:15:00 -0500247 pub fn write_application_error_to_out_protocol(
248 e: &ApplicationError,
Danny Browning77d96c12019-08-21 13:41:07 -0600249 o: &mut dyn TOutputProtocol,
Allen Georgeb0d14132020-03-29 11:48:55 -0400250 ) -> crate::Result<()> {
Allen Georgeef7a1892018-12-16 18:01:37 -0500251 o.write_struct_begin(&TStructIdentifier {
252 name: "TApplicationException".to_owned(),
253 })?;
Allen George8b96bfb2016-11-02 08:01:08 -0400254
255 let message_field = TFieldIdentifier::new("message", TType::String, 1);
256 let type_field = TFieldIdentifier::new("type", TType::I32, 2);
257
258 o.write_field_begin(&message_field)?;
259 o.write_string(&e.message)?;
260 o.write_field_end()?;
261
262 o.write_field_begin(&type_field)?;
263 o.write_i32(e.kind as i32)?;
264 o.write_field_end()?;
265
266 o.write_field_stop()?;
267 o.write_struct_end()?;
268
269 o.flush()
270 }
271}
272
273impl error::Error for Error {
274 fn description(&self) -> &str {
275 match *self {
276 Error::Transport(ref e) => TransportError::description(e),
277 Error::Protocol(ref e) => ProtocolError::description(e),
278 Error::Application(ref e) => ApplicationError::description(e),
279 Error::User(ref e) => e.description(),
280 }
281 }
282}
283
284impl Debug for Error {
Allen George7ddbcc02020-11-08 09:51:19 -0500285 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Allen George8b96bfb2016-11-02 08:01:08 -0400286 match *self {
287 Error::Transport(ref e) => Debug::fmt(e, f),
288 Error::Protocol(ref e) => Debug::fmt(e, f),
289 Error::Application(ref e) => Debug::fmt(e, f),
290 Error::User(ref e) => Debug::fmt(e, f),
291 }
292 }
293}
294
295impl Display for Error {
Allen George7ddbcc02020-11-08 09:51:19 -0500296 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Allen George8b96bfb2016-11-02 08:01:08 -0400297 match *self {
298 Error::Transport(ref e) => Display::fmt(e, f),
299 Error::Protocol(ref e) => Display::fmt(e, f),
300 Error::Application(ref e) => Display::fmt(e, f),
301 Error::User(ref e) => Display::fmt(e, f),
302 }
303 }
304}
305
306impl From<String> for Error {
307 fn from(s: String) -> Self {
Allen Georgeef7a1892018-12-16 18:01:37 -0500308 Error::Application(ApplicationError {
309 kind: ApplicationErrorKind::Unknown,
310 message: s,
311 })
Allen George8b96bfb2016-11-02 08:01:08 -0400312 }
313}
314
315impl<'a> From<&'a str> for Error {
316 fn from(s: &'a str) -> Self {
Allen Georgeef7a1892018-12-16 18:01:37 -0500317 Error::Application(ApplicationError {
318 kind: ApplicationErrorKind::Unknown,
319 message: String::from(s),
320 })
Allen George8b96bfb2016-11-02 08:01:08 -0400321 }
322}
323
324impl From<TransportError> for Error {
325 fn from(e: TransportError) -> Self {
326 Error::Transport(e)
327 }
328}
329
330impl From<ProtocolError> for Error {
331 fn from(e: ProtocolError) -> Self {
332 Error::Protocol(e)
333 }
334}
335
336impl From<ApplicationError> for Error {
337 fn from(e: ApplicationError) -> Self {
338 Error::Application(e)
339 }
340}
341
342/// Create a new `Error` instance of type `Transport` that wraps a
343/// `TransportError`.
344pub fn new_transport_error<S: Into<String>>(kind: TransportErrorKind, message: S) -> Error {
345 Error::Transport(TransportError::new(kind, message))
346}
347
348/// Information about I/O errors.
Allen Georgebc1344d2017-04-28 10:22:03 -0400349#[derive(Debug, Eq, PartialEq)]
Allen George8b96bfb2016-11-02 08:01:08 -0400350pub struct TransportError {
351 /// I/O error variant.
352 ///
353 /// If a specific `TransportErrorKind` does not apply use
354 /// `TransportErrorKind::Unknown`.
355 pub kind: TransportErrorKind,
356 /// Human-readable error message.
357 pub message: String,
358}
359
360impl TransportError {
361 /// Create a new `TransportError`.
362 pub fn new<S: Into<String>>(kind: TransportErrorKind, message: S) -> TransportError {
363 TransportError {
Allen George7ddbcc02020-11-08 09:51:19 -0500364 kind,
Allen George8b96bfb2016-11-02 08:01:08 -0400365 message: message.into(),
366 }
367 }
368}
369
370/// I/O error categories.
371///
372/// This list may grow, and it is not recommended to match against it.
373#[derive(Clone, Copy, Eq, Debug, PartialEq)]
374pub enum TransportErrorKind {
375 /// Catch-all I/O error.
376 Unknown = 0,
377 /// An I/O operation was attempted when the transport channel was not open.
378 NotOpen = 1,
379 /// The transport channel cannot be opened because it was opened previously.
380 AlreadyOpen = 2,
381 /// An I/O operation timed out.
382 TimedOut = 3,
383 /// A read could not complete because no bytes were available.
384 EndOfFile = 4,
385 /// An invalid (buffer/message) size was requested or received.
386 NegativeSize = 5,
387 /// Too large a buffer or message size was requested or received.
388 SizeLimit = 6,
389}
390
391impl TransportError {
392 fn description(&self) -> &str {
393 match self.kind {
394 TransportErrorKind::Unknown => "transport error",
395 TransportErrorKind::NotOpen => "not open",
396 TransportErrorKind::AlreadyOpen => "already open",
397 TransportErrorKind::TimedOut => "timed out",
398 TransportErrorKind::EndOfFile => "end of file",
399 TransportErrorKind::NegativeSize => "negative size message",
400 TransportErrorKind::SizeLimit => "message too long",
401 }
402 }
403}
404
405impl Display for TransportError {
Allen George7ddbcc02020-11-08 09:51:19 -0500406 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Allen George8b96bfb2016-11-02 08:01:08 -0400407 write!(f, "{}", self.description())
408 }
409}
410
411impl TryFrom<i32> for TransportErrorKind {
Danny Browningddec4312019-03-08 14:20:41 -0700412 type Error = Error;
413 fn try_from(from: i32) -> Result<Self, Self::Error> {
Allen George8b96bfb2016-11-02 08:01:08 -0400414 match from {
415 0 => Ok(TransportErrorKind::Unknown),
416 1 => Ok(TransportErrorKind::NotOpen),
417 2 => Ok(TransportErrorKind::AlreadyOpen),
418 3 => Ok(TransportErrorKind::TimedOut),
419 4 => Ok(TransportErrorKind::EndOfFile),
420 5 => Ok(TransportErrorKind::NegativeSize),
421 6 => Ok(TransportErrorKind::SizeLimit),
Allen Georgeef7a1892018-12-16 18:01:37 -0500422 _ => Err(Error::Protocol(ProtocolError {
423 kind: ProtocolErrorKind::Unknown,
424 message: format!("cannot convert {} to TransportErrorKind", from),
425 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400426 }
427 }
428}
429
430impl From<io::Error> for Error {
431 fn from(err: io::Error) -> Self {
432 match err.kind() {
Allen Georgeef7a1892018-12-16 18:01:37 -0500433 io::ErrorKind::ConnectionReset
434 | io::ErrorKind::ConnectionRefused
435 | io::ErrorKind::NotConnected => Error::Transport(TransportError {
436 kind: TransportErrorKind::NotOpen,
437 message: err.description().to_owned(),
438 }),
439 io::ErrorKind::AlreadyExists => Error::Transport(TransportError {
440 kind: TransportErrorKind::AlreadyOpen,
441 message: err.description().to_owned(),
442 }),
443 io::ErrorKind::TimedOut => Error::Transport(TransportError {
444 kind: TransportErrorKind::TimedOut,
445 message: err.description().to_owned(),
446 }),
447 io::ErrorKind::UnexpectedEof => Error::Transport(TransportError {
448 kind: TransportErrorKind::EndOfFile,
449 message: err.description().to_owned(),
450 }),
Allen George8b96bfb2016-11-02 08:01:08 -0400451 _ => {
Allen Georgeef7a1892018-12-16 18:01:37 -0500452 Error::Transport(TransportError {
453 kind: TransportErrorKind::Unknown,
454 message: err.description().to_owned(), // FIXME: use io error's debug string
455 })
Allen George8b96bfb2016-11-02 08:01:08 -0400456 }
457 }
458 }
459}
460
461impl From<string::FromUtf8Error> for Error {
462 fn from(err: string::FromUtf8Error) -> Self {
Allen Georgeef7a1892018-12-16 18:01:37 -0500463 Error::Protocol(ProtocolError {
464 kind: ProtocolErrorKind::InvalidData,
465 message: err.description().to_owned(), // FIXME: use fmt::Error's debug string
466 })
Allen George8b96bfb2016-11-02 08:01:08 -0400467 }
468}
469
470/// Create a new `Error` instance of type `Protocol` that wraps a
471/// `ProtocolError`.
472pub fn new_protocol_error<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> Error {
473 Error::Protocol(ProtocolError::new(kind, message))
474}
475
476/// Information about errors that occur in the runtime library.
Allen Georgebc1344d2017-04-28 10:22:03 -0400477#[derive(Debug, Eq, PartialEq)]
Allen George8b96bfb2016-11-02 08:01:08 -0400478pub struct ProtocolError {
479 /// Protocol error variant.
480 ///
481 /// If a specific `ProtocolErrorKind` does not apply use
482 /// `ProtocolErrorKind::Unknown`.
483 pub kind: ProtocolErrorKind,
484 /// Human-readable error message.
485 pub message: String,
486}
487
488impl ProtocolError {
489 /// Create a new `ProtocolError`.
490 pub fn new<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> ProtocolError {
491 ProtocolError {
Allen George7ddbcc02020-11-08 09:51:19 -0500492 kind,
Allen George8b96bfb2016-11-02 08:01:08 -0400493 message: message.into(),
494 }
495 }
496}
497
498/// Runtime library error categories.
499///
500/// This list may grow, and it is not recommended to match against it.
501#[derive(Clone, Copy, Eq, Debug, PartialEq)]
502pub enum ProtocolErrorKind {
503 /// Catch-all runtime-library error.
504 Unknown = 0,
505 /// An invalid argument was supplied to a library function, or invalid data
506 /// was received from a Thrift endpoint.
507 InvalidData = 1,
508 /// An invalid size was received in an encoded field.
509 NegativeSize = 2,
510 /// Thrift message or field was too long.
511 SizeLimit = 3,
512 /// Unsupported or unknown Thrift protocol version.
513 BadVersion = 4,
514 /// Unsupported Thrift protocol, server or field type.
515 NotImplemented = 5,
516 /// Reached the maximum nested depth to which an encoded Thrift field could
517 /// be skipped.
518 DepthLimit = 6,
519}
520
521impl ProtocolError {
522 fn description(&self) -> &str {
523 match self.kind {
524 ProtocolErrorKind::Unknown => "protocol error",
525 ProtocolErrorKind::InvalidData => "bad data",
526 ProtocolErrorKind::NegativeSize => "negative message size",
527 ProtocolErrorKind::SizeLimit => "message too long",
528 ProtocolErrorKind::BadVersion => "invalid thrift version",
529 ProtocolErrorKind::NotImplemented => "not implemented",
530 ProtocolErrorKind::DepthLimit => "maximum skip depth reached",
531 }
532 }
533}
534
535impl Display for ProtocolError {
Allen George7ddbcc02020-11-08 09:51:19 -0500536 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Allen George8b96bfb2016-11-02 08:01:08 -0400537 write!(f, "{}", self.description())
538 }
539}
540
541impl TryFrom<i32> for ProtocolErrorKind {
Danny Browningddec4312019-03-08 14:20:41 -0700542 type Error = Error;
543 fn try_from(from: i32) -> Result<Self, Self::Error> {
Allen George8b96bfb2016-11-02 08:01:08 -0400544 match from {
545 0 => Ok(ProtocolErrorKind::Unknown),
546 1 => Ok(ProtocolErrorKind::InvalidData),
547 2 => Ok(ProtocolErrorKind::NegativeSize),
548 3 => Ok(ProtocolErrorKind::SizeLimit),
549 4 => Ok(ProtocolErrorKind::BadVersion),
550 5 => Ok(ProtocolErrorKind::NotImplemented),
551 6 => Ok(ProtocolErrorKind::DepthLimit),
Allen Georgeef7a1892018-12-16 18:01:37 -0500552 _ => Err(Error::Protocol(ProtocolError {
553 kind: ProtocolErrorKind::Unknown,
554 message: format!("cannot convert {} to ProtocolErrorKind", from),
555 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400556 }
557 }
558}
559
560/// Create a new `Error` instance of type `Application` that wraps an
561/// `ApplicationError`.
562pub fn new_application_error<S: Into<String>>(kind: ApplicationErrorKind, message: S) -> Error {
563 Error::Application(ApplicationError::new(kind, message))
564}
565
566/// Information about errors in auto-generated code or in user-implemented
567/// service handlers.
Allen Georgebc1344d2017-04-28 10:22:03 -0400568#[derive(Debug, Eq, PartialEq)]
Allen George8b96bfb2016-11-02 08:01:08 -0400569pub struct ApplicationError {
570 /// Application error variant.
571 ///
572 /// If a specific `ApplicationErrorKind` does not apply use
573 /// `ApplicationErrorKind::Unknown`.
574 pub kind: ApplicationErrorKind,
575 /// Human-readable error message.
576 pub message: String,
577}
578
579impl ApplicationError {
580 /// Create a new `ApplicationError`.
581 pub fn new<S: Into<String>>(kind: ApplicationErrorKind, message: S) -> ApplicationError {
582 ApplicationError {
Allen George7ddbcc02020-11-08 09:51:19 -0500583 kind,
Allen George8b96bfb2016-11-02 08:01:08 -0400584 message: message.into(),
585 }
586 }
587}
588
589/// Auto-generated or user-implemented code error categories.
590///
591/// This list may grow, and it is not recommended to match against it.
592#[derive(Clone, Copy, Debug, Eq, PartialEq)]
593pub enum ApplicationErrorKind {
594 /// Catch-all application error.
595 Unknown = 0,
596 /// Made service call to an unknown service method.
597 UnknownMethod = 1,
598 /// Received an unknown Thrift message type. That is, not one of the
599 /// `thrift::protocol::TMessageType` variants.
600 InvalidMessageType = 2,
601 /// Method name in a service reply does not match the name of the
602 /// receiving service method.
603 WrongMethodName = 3,
604 /// Received an out-of-order Thrift message.
605 BadSequenceId = 4,
606 /// Service reply is missing required fields.
607 MissingResult = 5,
608 /// Auto-generated code failed unexpectedly.
609 InternalError = 6,
610 /// Thrift protocol error. When possible use `Error::ProtocolError` with a
611 /// specific `ProtocolErrorKind` instead.
612 ProtocolError = 7,
613 /// *Unknown*. Included only for compatibility with existing Thrift implementations.
614 InvalidTransform = 8, // ??
615 /// Thrift endpoint requested, or is using, an unsupported encoding.
616 InvalidProtocol = 9, // ??
617 /// Thrift endpoint requested, or is using, an unsupported auto-generated client type.
618 UnsupportedClientType = 10, // ??
619}
620
621impl ApplicationError {
622 fn description(&self) -> &str {
623 match self.kind {
624 ApplicationErrorKind::Unknown => "service error",
625 ApplicationErrorKind::UnknownMethod => "unknown service method",
626 ApplicationErrorKind::InvalidMessageType => "wrong message type received",
627 ApplicationErrorKind::WrongMethodName => "unknown method reply received",
628 ApplicationErrorKind::BadSequenceId => "out of order sequence id",
629 ApplicationErrorKind::MissingResult => "missing method result",
630 ApplicationErrorKind::InternalError => "remote service threw exception",
631 ApplicationErrorKind::ProtocolError => "protocol error",
632 ApplicationErrorKind::InvalidTransform => "invalid transform",
633 ApplicationErrorKind::InvalidProtocol => "invalid protocol requested",
634 ApplicationErrorKind::UnsupportedClientType => "unsupported protocol client",
635 }
636 }
637}
638
639impl Display for ApplicationError {
Allen George7ddbcc02020-11-08 09:51:19 -0500640 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Allen George8b96bfb2016-11-02 08:01:08 -0400641 write!(f, "{}", self.description())
642 }
643}
644
645impl TryFrom<i32> for ApplicationErrorKind {
Danny Browningddec4312019-03-08 14:20:41 -0700646 type Error = Error;
647 fn try_from(from: i32) -> Result<Self, Self::Error> {
Allen George8b96bfb2016-11-02 08:01:08 -0400648 match from {
649 0 => Ok(ApplicationErrorKind::Unknown),
650 1 => Ok(ApplicationErrorKind::UnknownMethod),
651 2 => Ok(ApplicationErrorKind::InvalidMessageType),
652 3 => Ok(ApplicationErrorKind::WrongMethodName),
653 4 => Ok(ApplicationErrorKind::BadSequenceId),
654 5 => Ok(ApplicationErrorKind::MissingResult),
655 6 => Ok(ApplicationErrorKind::InternalError),
656 7 => Ok(ApplicationErrorKind::ProtocolError),
657 8 => Ok(ApplicationErrorKind::InvalidTransform),
658 9 => Ok(ApplicationErrorKind::InvalidProtocol),
659 10 => Ok(ApplicationErrorKind::UnsupportedClientType),
Allen Georgeef7a1892018-12-16 18:01:37 -0500660 _ => Err(Error::Application(ApplicationError {
661 kind: ApplicationErrorKind::Unknown,
662 message: format!("cannot convert {} to ApplicationErrorKind", from),
663 })),
Allen George8b96bfb2016-11-02 08:01:08 -0400664 }
665 }
666}