blob: cc0ac783ec40c536229966d53f53c733d9f93bfd [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
18use std::convert::{From, Into};
19use std::error::Error as StdError;
20use std::fmt::{Debug, Display, Formatter};
21use std::{error, fmt, io, string};
22use try_from::TryFrom;
23
Allen George0e22c362017-01-30 07:15:00 -050024use protocol::{TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentifier, TType};
Allen George8b96bfb2016-11-02 08:01:08 -040025
26// FIXME: should all my error structs impl error::Error as well?
27// FIXME: should all fields in TransportError, ProtocolError and ApplicationError be optional?
28
29/// Error type returned by all runtime library functions.
30///
31/// `thrift::Error` is used throughout this crate as well as in auto-generated
32/// Rust code. It consists of four variants defined by convention across Thrift
33/// implementations:
34///
35/// 1. `Transport`: errors encountered while operating on I/O channels
36/// 2. `Protocol`: errors encountered during runtime-library processing
37/// 3. `Application`: errors encountered within auto-generated code
38/// 4. `User`: IDL-defined exception structs
39///
40/// The `Application` variant also functions as a catch-all: all handler errors
41/// are automatically turned into application errors.
42///
43/// All error variants except `Error::User` take an eponymous struct with two
44/// required fields:
45///
46/// 1. `kind`: variant-specific enum identifying the error sub-type
47/// 2. `message`: human-readable error info string
48///
49/// `kind` is defined by convention while `message` is freeform. If none of the
50/// enumerated kinds are suitable use `Unknown`.
51///
52/// To simplify error creation convenience constructors are defined for all
53/// variants, and conversions from their structs (`thrift::TransportError`,
54/// `thrift::ProtocolError` and `thrift::ApplicationError` into `thrift::Error`.
55///
56/// # Examples
57///
58/// Create a `TransportError`.
59///
60/// ```
61/// use thrift;
62/// use thrift::{TransportError, TransportErrorKind};
63///
64/// // explicit
65/// let err0: thrift::Result<()> = Err(
66/// thrift::Error::Transport(
67/// TransportError {
68/// kind: TransportErrorKind::TimedOut,
69/// message: format!("connection to server timed out")
70/// }
71/// )
72/// );
73///
74/// // use conversion
75/// let err1: thrift::Result<()> = Err(
76/// thrift::Error::from(
77/// TransportError {
78/// kind: TransportErrorKind::TimedOut,
79/// message: format!("connection to server timed out")
80/// }
81/// )
82/// );
83///
84/// // use struct constructor
85/// let err2: thrift::Result<()> = Err(
86/// thrift::Error::Transport(
87/// TransportError::new(
88/// TransportErrorKind::TimedOut,
89/// "connection to server timed out"
90/// )
91/// )
92/// );
93///
94///
95/// // use error variant constructor
96/// let err3: thrift::Result<()> = Err(
97/// thrift::new_transport_error(
98/// TransportErrorKind::TimedOut,
99/// "connection to server timed out"
100/// )
101/// );
102/// ```
103///
104/// Create an error from a string.
105///
106/// ```
107/// use thrift;
108/// 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/// ```
137/// use std::convert::From;
138/// use std::error::Error;
139/// use std::fmt;
140/// use std::fmt::{Display, Formatter};
141///
142/// // auto-generated by the Thrift compiler
143/// #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
144/// pub struct Xception {
145/// pub error_code: Option<i32>,
146/// pub message: Option<String>,
147/// }
148///
149/// // auto-generated by the Thrift compiler
150/// impl Error for Xception {
151/// fn description(&self) -> &str {
152/// "remote service threw Xception"
153/// }
154/// }
155///
156/// // auto-generated by the Thrift compiler
157/// impl From<Xception> for thrift::Error {
158/// fn from(e: Xception) -> Self {
159/// thrift::Error::User(Box::new(e))
160/// }
161/// }
162///
163/// // auto-generated by the Thrift compiler
164/// impl Display for Xception {
165/// fn fmt(&self, f: &mut Formatter) -> fmt::Result {
166/// self.description().fmt(f)
167/// }
168/// }
169///
170/// // in user code...
171/// let err: thrift::Result<()> = Err(
172/// thrift::Error::from(Xception { error_code: Some(1), message: None })
173/// );
174/// ```
175pub enum Error {
176 /// Errors encountered while operating on I/O channels.
177 ///
178 /// These include *connection closed* and *bind failure*.
179 Transport(TransportError),
180 /// Errors encountered during runtime-library processing.
181 ///
182 /// These include *message too large* and *unsupported protocol version*.
183 Protocol(ProtocolError),
184 /// Errors encountered within auto-generated code, or when incoming
185 /// or outgoing messages violate the Thrift spec.
186 ///
187 /// These include *out-of-order messages* and *missing required struct
188 /// fields*.
189 ///
190 /// This variant also functions as a catch-all: errors from handler
191 /// functions are automatically returned as an `ApplicationError`.
192 Application(ApplicationError),
193 /// IDL-defined exception structs.
194 User(Box<error::Error + Sync + Send>),
195}
196
197impl Error {
198 /// Create an `ApplicationError` from its wire representation.
199 ///
200 /// Application code **should never** call this method directly.
Allen George0e22c362017-01-30 07:15:00 -0500201 pub fn read_application_error_from_in_protocol(i: &mut TInputProtocol,)
202 -> ::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 George0e22c362017-01-30 07:15:00 -0500227 let remote_kind: ApplicationErrorKind =
228 TryFrom::try_from(remote_type_as_int)
229 .unwrap_or(ApplicationErrorKind::Unknown);
Allen George8b96bfb2016-11-02 08:01:08 -0400230 i.read_field_end()?;
231 kind = remote_kind;
232 }
233 _ => {
234 i.skip(field_ident.field_type)?;
235 }
236 }
237 }
238
239 i.read_struct_end()?;
240
Allen George0e22c362017-01-30 07:15:00 -0500241 Ok(
242 ApplicationError {
243 kind: kind,
244 message: message,
245 },
246 )
Allen George8b96bfb2016-11-02 08:01:08 -0400247 }
248
249 /// Convert an `ApplicationError` into its wire representation and write
250 /// it to the remote.
251 ///
252 /// Application code **should never** call this method directly.
Allen George0e22c362017-01-30 07:15:00 -0500253 pub fn write_application_error_to_out_protocol(
254 e: &ApplicationError,
255 o: &mut TOutputProtocol,
256 ) -> ::Result<()> {
257 o.write_struct_begin(&TStructIdentifier { name: "TApplicationException".to_owned() },)?;
Allen George8b96bfb2016-11-02 08:01:08 -0400258
259 let message_field = TFieldIdentifier::new("message", TType::String, 1);
260 let type_field = TFieldIdentifier::new("type", TType::I32, 2);
261
262 o.write_field_begin(&message_field)?;
263 o.write_string(&e.message)?;
264 o.write_field_end()?;
265
266 o.write_field_begin(&type_field)?;
267 o.write_i32(e.kind as i32)?;
268 o.write_field_end()?;
269
270 o.write_field_stop()?;
271 o.write_struct_end()?;
272
273 o.flush()
274 }
275}
276
277impl error::Error for Error {
278 fn description(&self) -> &str {
279 match *self {
280 Error::Transport(ref e) => TransportError::description(e),
281 Error::Protocol(ref e) => ProtocolError::description(e),
282 Error::Application(ref e) => ApplicationError::description(e),
283 Error::User(ref e) => e.description(),
284 }
285 }
286}
287
288impl Debug for Error {
289 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
290 match *self {
291 Error::Transport(ref e) => Debug::fmt(e, f),
292 Error::Protocol(ref e) => Debug::fmt(e, f),
293 Error::Application(ref e) => Debug::fmt(e, f),
294 Error::User(ref e) => Debug::fmt(e, f),
295 }
296 }
297}
298
299impl Display for Error {
300 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
301 match *self {
302 Error::Transport(ref e) => Display::fmt(e, f),
303 Error::Protocol(ref e) => Display::fmt(e, f),
304 Error::Application(ref e) => Display::fmt(e, f),
305 Error::User(ref e) => Display::fmt(e, f),
306 }
307 }
308}
309
310impl From<String> for Error {
311 fn from(s: String) -> Self {
Allen George0e22c362017-01-30 07:15:00 -0500312 Error::Application(
313 ApplicationError {
314 kind: ApplicationErrorKind::Unknown,
315 message: s,
316 },
317 )
Allen George8b96bfb2016-11-02 08:01:08 -0400318 }
319}
320
321impl<'a> From<&'a str> for Error {
322 fn from(s: &'a str) -> Self {
Allen George0e22c362017-01-30 07:15:00 -0500323 Error::Application(
324 ApplicationError {
325 kind: ApplicationErrorKind::Unknown,
326 message: String::from(s),
327 },
328 )
Allen George8b96bfb2016-11-02 08:01:08 -0400329 }
330}
331
332impl From<TransportError> for Error {
333 fn from(e: TransportError) -> Self {
334 Error::Transport(e)
335 }
336}
337
338impl From<ProtocolError> for Error {
339 fn from(e: ProtocolError) -> Self {
340 Error::Protocol(e)
341 }
342}
343
344impl From<ApplicationError> for Error {
345 fn from(e: ApplicationError) -> Self {
346 Error::Application(e)
347 }
348}
349
350/// Create a new `Error` instance of type `Transport` that wraps a
351/// `TransportError`.
352pub fn new_transport_error<S: Into<String>>(kind: TransportErrorKind, message: S) -> Error {
353 Error::Transport(TransportError::new(kind, message))
354}
355
356/// Information about I/O errors.
Allen Georgebc1344d2017-04-28 10:22:03 -0400357#[derive(Debug, Eq, PartialEq)]
Allen George8b96bfb2016-11-02 08:01:08 -0400358pub struct TransportError {
359 /// I/O error variant.
360 ///
361 /// If a specific `TransportErrorKind` does not apply use
362 /// `TransportErrorKind::Unknown`.
363 pub kind: TransportErrorKind,
364 /// Human-readable error message.
365 pub message: String,
366}
367
368impl TransportError {
369 /// Create a new `TransportError`.
370 pub fn new<S: Into<String>>(kind: TransportErrorKind, message: S) -> TransportError {
371 TransportError {
372 kind: kind,
373 message: message.into(),
374 }
375 }
376}
377
378/// I/O error categories.
379///
380/// This list may grow, and it is not recommended to match against it.
381#[derive(Clone, Copy, Eq, Debug, PartialEq)]
382pub enum TransportErrorKind {
383 /// Catch-all I/O error.
384 Unknown = 0,
385 /// An I/O operation was attempted when the transport channel was not open.
386 NotOpen = 1,
387 /// The transport channel cannot be opened because it was opened previously.
388 AlreadyOpen = 2,
389 /// An I/O operation timed out.
390 TimedOut = 3,
391 /// A read could not complete because no bytes were available.
392 EndOfFile = 4,
393 /// An invalid (buffer/message) size was requested or received.
394 NegativeSize = 5,
395 /// Too large a buffer or message size was requested or received.
396 SizeLimit = 6,
397}
398
399impl TransportError {
400 fn description(&self) -> &str {
401 match self.kind {
402 TransportErrorKind::Unknown => "transport error",
403 TransportErrorKind::NotOpen => "not open",
404 TransportErrorKind::AlreadyOpen => "already open",
405 TransportErrorKind::TimedOut => "timed out",
406 TransportErrorKind::EndOfFile => "end of file",
407 TransportErrorKind::NegativeSize => "negative size message",
408 TransportErrorKind::SizeLimit => "message too long",
409 }
410 }
411}
412
413impl Display for TransportError {
414 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
415 write!(f, "{}", self.description())
416 }
417}
418
419impl TryFrom<i32> for TransportErrorKind {
420 type Err = Error;
421 fn try_from(from: i32) -> Result<Self, Self::Err> {
422 match from {
423 0 => Ok(TransportErrorKind::Unknown),
424 1 => Ok(TransportErrorKind::NotOpen),
425 2 => Ok(TransportErrorKind::AlreadyOpen),
426 3 => Ok(TransportErrorKind::TimedOut),
427 4 => Ok(TransportErrorKind::EndOfFile),
428 5 => Ok(TransportErrorKind::NegativeSize),
429 6 => Ok(TransportErrorKind::SizeLimit),
430 _ => {
Allen George0e22c362017-01-30 07:15:00 -0500431 Err(
432 Error::Protocol(
433 ProtocolError {
434 kind: ProtocolErrorKind::Unknown,
435 message: format!("cannot convert {} to TransportErrorKind", from),
436 },
437 ),
438 )
Allen George8b96bfb2016-11-02 08:01:08 -0400439 }
440 }
441 }
442}
443
444impl From<io::Error> for Error {
445 fn from(err: io::Error) -> Self {
446 match err.kind() {
447 io::ErrorKind::ConnectionReset |
448 io::ErrorKind::ConnectionRefused |
449 io::ErrorKind::NotConnected => {
Allen George0e22c362017-01-30 07:15:00 -0500450 Error::Transport(
451 TransportError {
452 kind: TransportErrorKind::NotOpen,
453 message: err.description().to_owned(),
454 },
455 )
Allen George8b96bfb2016-11-02 08:01:08 -0400456 }
457 io::ErrorKind::AlreadyExists => {
Allen George0e22c362017-01-30 07:15:00 -0500458 Error::Transport(
459 TransportError {
460 kind: TransportErrorKind::AlreadyOpen,
461 message: err.description().to_owned(),
462 },
463 )
Allen George8b96bfb2016-11-02 08:01:08 -0400464 }
465 io::ErrorKind::TimedOut => {
Allen George0e22c362017-01-30 07:15:00 -0500466 Error::Transport(
467 TransportError {
468 kind: TransportErrorKind::TimedOut,
469 message: err.description().to_owned(),
470 },
471 )
Allen George8b96bfb2016-11-02 08:01:08 -0400472 }
473 io::ErrorKind::UnexpectedEof => {
Allen George0e22c362017-01-30 07:15:00 -0500474 Error::Transport(
475 TransportError {
476 kind: TransportErrorKind::EndOfFile,
477 message: err.description().to_owned(),
478 },
479 )
Allen George8b96bfb2016-11-02 08:01:08 -0400480 }
481 _ => {
Allen George0e22c362017-01-30 07:15:00 -0500482 Error::Transport(
483 TransportError {
484 kind: TransportErrorKind::Unknown,
485 message: err.description().to_owned(), // FIXME: use io error's debug string
486 },
487 )
Allen George8b96bfb2016-11-02 08:01:08 -0400488 }
489 }
490 }
491}
492
493impl From<string::FromUtf8Error> for Error {
494 fn from(err: string::FromUtf8Error) -> Self {
Allen George0e22c362017-01-30 07:15:00 -0500495 Error::Protocol(
496 ProtocolError {
497 kind: ProtocolErrorKind::InvalidData,
498 message: err.description().to_owned(), // FIXME: use fmt::Error's debug string
499 },
500 )
Allen George8b96bfb2016-11-02 08:01:08 -0400501 }
502}
503
504/// Create a new `Error` instance of type `Protocol` that wraps a
505/// `ProtocolError`.
506pub fn new_protocol_error<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> Error {
507 Error::Protocol(ProtocolError::new(kind, message))
508}
509
510/// Information about errors that occur in the runtime library.
Allen Georgebc1344d2017-04-28 10:22:03 -0400511#[derive(Debug, Eq, PartialEq)]
Allen George8b96bfb2016-11-02 08:01:08 -0400512pub struct ProtocolError {
513 /// Protocol error variant.
514 ///
515 /// If a specific `ProtocolErrorKind` does not apply use
516 /// `ProtocolErrorKind::Unknown`.
517 pub kind: ProtocolErrorKind,
518 /// Human-readable error message.
519 pub message: String,
520}
521
522impl ProtocolError {
523 /// Create a new `ProtocolError`.
524 pub fn new<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> ProtocolError {
525 ProtocolError {
526 kind: kind,
527 message: message.into(),
528 }
529 }
530}
531
532/// Runtime library error categories.
533///
534/// This list may grow, and it is not recommended to match against it.
535#[derive(Clone, Copy, Eq, Debug, PartialEq)]
536pub enum ProtocolErrorKind {
537 /// Catch-all runtime-library error.
538 Unknown = 0,
539 /// An invalid argument was supplied to a library function, or invalid data
540 /// was received from a Thrift endpoint.
541 InvalidData = 1,
542 /// An invalid size was received in an encoded field.
543 NegativeSize = 2,
544 /// Thrift message or field was too long.
545 SizeLimit = 3,
546 /// Unsupported or unknown Thrift protocol version.
547 BadVersion = 4,
548 /// Unsupported Thrift protocol, server or field type.
549 NotImplemented = 5,
550 /// Reached the maximum nested depth to which an encoded Thrift field could
551 /// be skipped.
552 DepthLimit = 6,
553}
554
555impl ProtocolError {
556 fn description(&self) -> &str {
557 match self.kind {
558 ProtocolErrorKind::Unknown => "protocol error",
559 ProtocolErrorKind::InvalidData => "bad data",
560 ProtocolErrorKind::NegativeSize => "negative message size",
561 ProtocolErrorKind::SizeLimit => "message too long",
562 ProtocolErrorKind::BadVersion => "invalid thrift version",
563 ProtocolErrorKind::NotImplemented => "not implemented",
564 ProtocolErrorKind::DepthLimit => "maximum skip depth reached",
565 }
566 }
567}
568
569impl Display for ProtocolError {
570 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
571 write!(f, "{}", self.description())
572 }
573}
574
575impl TryFrom<i32> for ProtocolErrorKind {
576 type Err = Error;
577 fn try_from(from: i32) -> Result<Self, Self::Err> {
578 match from {
579 0 => Ok(ProtocolErrorKind::Unknown),
580 1 => Ok(ProtocolErrorKind::InvalidData),
581 2 => Ok(ProtocolErrorKind::NegativeSize),
582 3 => Ok(ProtocolErrorKind::SizeLimit),
583 4 => Ok(ProtocolErrorKind::BadVersion),
584 5 => Ok(ProtocolErrorKind::NotImplemented),
585 6 => Ok(ProtocolErrorKind::DepthLimit),
586 _ => {
Allen George0e22c362017-01-30 07:15:00 -0500587 Err(
588 Error::Protocol(
589 ProtocolError {
590 kind: ProtocolErrorKind::Unknown,
591 message: format!("cannot convert {} to ProtocolErrorKind", from),
592 },
593 ),
594 )
Allen George8b96bfb2016-11-02 08:01:08 -0400595 }
596 }
597 }
598}
599
600/// Create a new `Error` instance of type `Application` that wraps an
601/// `ApplicationError`.
602pub fn new_application_error<S: Into<String>>(kind: ApplicationErrorKind, message: S) -> Error {
603 Error::Application(ApplicationError::new(kind, message))
604}
605
606/// Information about errors in auto-generated code or in user-implemented
607/// service handlers.
Allen Georgebc1344d2017-04-28 10:22:03 -0400608#[derive(Debug, Eq, PartialEq)]
Allen George8b96bfb2016-11-02 08:01:08 -0400609pub struct ApplicationError {
610 /// Application error variant.
611 ///
612 /// If a specific `ApplicationErrorKind` does not apply use
613 /// `ApplicationErrorKind::Unknown`.
614 pub kind: ApplicationErrorKind,
615 /// Human-readable error message.
616 pub message: String,
617}
618
619impl ApplicationError {
620 /// Create a new `ApplicationError`.
621 pub fn new<S: Into<String>>(kind: ApplicationErrorKind, message: S) -> ApplicationError {
622 ApplicationError {
623 kind: kind,
624 message: message.into(),
625 }
626 }
627}
628
629/// Auto-generated or user-implemented code error categories.
630///
631/// This list may grow, and it is not recommended to match against it.
632#[derive(Clone, Copy, Debug, Eq, PartialEq)]
633pub enum ApplicationErrorKind {
634 /// Catch-all application error.
635 Unknown = 0,
636 /// Made service call to an unknown service method.
637 UnknownMethod = 1,
638 /// Received an unknown Thrift message type. That is, not one of the
639 /// `thrift::protocol::TMessageType` variants.
640 InvalidMessageType = 2,
641 /// Method name in a service reply does not match the name of the
642 /// receiving service method.
643 WrongMethodName = 3,
644 /// Received an out-of-order Thrift message.
645 BadSequenceId = 4,
646 /// Service reply is missing required fields.
647 MissingResult = 5,
648 /// Auto-generated code failed unexpectedly.
649 InternalError = 6,
650 /// Thrift protocol error. When possible use `Error::ProtocolError` with a
651 /// specific `ProtocolErrorKind` instead.
652 ProtocolError = 7,
653 /// *Unknown*. Included only for compatibility with existing Thrift implementations.
654 InvalidTransform = 8, // ??
655 /// Thrift endpoint requested, or is using, an unsupported encoding.
656 InvalidProtocol = 9, // ??
657 /// Thrift endpoint requested, or is using, an unsupported auto-generated client type.
658 UnsupportedClientType = 10, // ??
659}
660
661impl ApplicationError {
662 fn description(&self) -> &str {
663 match self.kind {
664 ApplicationErrorKind::Unknown => "service error",
665 ApplicationErrorKind::UnknownMethod => "unknown service method",
666 ApplicationErrorKind::InvalidMessageType => "wrong message type received",
667 ApplicationErrorKind::WrongMethodName => "unknown method reply received",
668 ApplicationErrorKind::BadSequenceId => "out of order sequence id",
669 ApplicationErrorKind::MissingResult => "missing method result",
670 ApplicationErrorKind::InternalError => "remote service threw exception",
671 ApplicationErrorKind::ProtocolError => "protocol error",
672 ApplicationErrorKind::InvalidTransform => "invalid transform",
673 ApplicationErrorKind::InvalidProtocol => "invalid protocol requested",
674 ApplicationErrorKind::UnsupportedClientType => "unsupported protocol client",
675 }
676 }
677}
678
679impl Display for ApplicationError {
680 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
681 write!(f, "{}", self.description())
682 }
683}
684
685impl TryFrom<i32> for ApplicationErrorKind {
686 type Err = Error;
687 fn try_from(from: i32) -> Result<Self, Self::Err> {
688 match from {
689 0 => Ok(ApplicationErrorKind::Unknown),
690 1 => Ok(ApplicationErrorKind::UnknownMethod),
691 2 => Ok(ApplicationErrorKind::InvalidMessageType),
692 3 => Ok(ApplicationErrorKind::WrongMethodName),
693 4 => Ok(ApplicationErrorKind::BadSequenceId),
694 5 => Ok(ApplicationErrorKind::MissingResult),
695 6 => Ok(ApplicationErrorKind::InternalError),
696 7 => Ok(ApplicationErrorKind::ProtocolError),
697 8 => Ok(ApplicationErrorKind::InvalidTransform),
698 9 => Ok(ApplicationErrorKind::InvalidProtocol),
699 10 => Ok(ApplicationErrorKind::UnsupportedClientType),
700 _ => {
Allen George0e22c362017-01-30 07:15:00 -0500701 Err(
702 Error::Application(
703 ApplicationError {
704 kind: ApplicationErrorKind::Unknown,
705 message: format!("cannot convert {} to ApplicationErrorKind", from),
706 },
707 ),
708 )
Allen George8b96bfb2016-11-02 08:01:08 -0400709 }
710 }
711 }
712}