Coverage Report

Created: 2026-01-17 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/thrift/lib/rs/src/errors.rs
Line
Count
Source
1
// 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
18
use std::convert::TryFrom;
19
use std::convert::{From, Into};
20
use std::fmt::{Debug, Display, Formatter};
21
use std::{error, fmt, io, string};
22
23
use crate::protocol::{
24
    TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentifier, TType,
25
};
26
27
// FIXME: should all my error structs impl error::Error as well?
28
// FIXME: should all fields in TransportError, ProtocolError and ApplicationError be optional?
29
30
/// Error type returned by all runtime library functions.
31
///
32
/// `thrift::Error` is used throughout this crate as well as in auto-generated
33
/// Rust code. It consists of four variants defined by convention across Thrift
34
/// implementations:
35
///
36
/// 1. `Transport`: errors encountered while operating on I/O channels
37
/// 2. `Protocol`: errors encountered during runtime-library processing
38
/// 3. `Application`: errors encountered within auto-generated code
39
/// 4. `User`: IDL-defined exception structs
40
///
41
/// The `Application` variant also functions as a catch-all: all handler errors
42
/// are automatically turned into application errors.
43
///
44
/// All error variants except `Error::User` take an eponymous struct with two
45
/// required fields:
46
///
47
/// 1. `kind`: variant-specific enum identifying the error sub-type
48
/// 2. `message`: human-readable error info string
49
///
50
/// `kind` is defined by convention while `message` is freeform. If none of the
51
/// enumerated kinds are suitable use `Unknown`.
52
///
53
/// To simplify error creation convenience constructors are defined for all
54
/// variants, and conversions from their structs (`thrift::TransportError`,
55
/// `thrift::ProtocolError` and `thrift::ApplicationError` into `thrift::Error`.
56
///
57
/// # Examples
58
///
59
/// Create a `TransportError`.
60
///
61
/// ```
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::{ApplicationError, ApplicationErrorKind};
108
///
109
/// // we just use `From::from` to convert a `String` into a `thrift::Error`
110
/// let err0: thrift::Result<()> = Err(
111
///   thrift::Error::from("This is an error")
112
/// );
113
///
114
/// // err0 is equivalent to...
115
/// let err1: thrift::Result<()> = Err(
116
///   thrift::Error::Application(
117
///     ApplicationError {
118
///       kind: ApplicationErrorKind::Unknown,
119
///       message: format!("This is an error")
120
///     }
121
///   )
122
/// );
123
/// ```
124
///
125
/// Return an IDL-defined exception.
126
///
127
/// ```text
128
/// // Thrift IDL exception definition.
129
/// exception Xception {
130
///   1: i32 errorCode,
131
///   2: string message
132
/// }
133
/// ```
134
///
135
/// ```
136
/// use std::error::Error;
137
/// use std::fmt;
138
/// use std::fmt::{Display, Formatter};
139
///
140
/// // auto-generated by the Thrift compiler
141
/// #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
142
/// pub struct Xception {
143
///   pub error_code: Option<i32>,
144
///   pub message: Option<String>,
145
/// }
146
///
147
/// // auto-generated by the Thrift compiler
148
/// impl Error for Xception { }
149
///
150
/// // auto-generated by the Thrift compiler
151
/// impl From<Xception> for thrift::Error {
152
///   fn from(e: Xception) -> Self {
153
///     thrift::Error::User(Box::new(e))
154
///   }
155
/// }
156
///
157
/// // auto-generated by the Thrift compiler
158
/// impl Display for Xception {
159
///   fn fmt(&self, f: &mut Formatter) -> fmt::Result {
160
///     write!(f, "remote service threw Xception")
161
///   }
162
/// }
163
///
164
/// // in user code...
165
/// let err: thrift::Result<()> = Err(
166
///   thrift::Error::from(Xception { error_code: Some(1), message: None })
167
/// );
168
/// ```
169
pub enum Error {
170
    /// Errors encountered while operating on I/O channels.
171
    ///
172
    /// These include *connection closed* and *bind failure*.
173
    Transport(TransportError),
174
    /// Errors encountered during runtime-library processing.
175
    ///
176
    /// These include *message too large* and *unsupported protocol version*.
177
    Protocol(ProtocolError),
178
    /// Errors encountered within auto-generated code, or when incoming
179
    /// or outgoing messages violate the Thrift spec.
180
    ///
181
    /// These include *out-of-order messages* and *missing required struct
182
    /// fields*.
183
    ///
184
    /// This variant also functions as a catch-all: errors from handler
185
    /// functions are automatically returned as an `ApplicationError`.
186
    Application(ApplicationError),
187
    /// IDL-defined exception structs.
188
    User(Box<dyn error::Error + Sync + Send>),
189
}
190
191
impl Error {
192
    /// Create an `ApplicationError` from its wire representation.
193
    ///
194
    /// Application code **should never** call this method directly.
195
0
    pub fn read_application_error_from_in_protocol(
196
0
        i: &mut dyn TInputProtocol,
197
0
    ) -> crate::Result<ApplicationError> {
198
0
        let mut message = "general remote error".to_owned();
199
0
        let mut kind = ApplicationErrorKind::Unknown;
200
201
0
        i.read_struct_begin()?;
202
203
        loop {
204
0
            let field_ident = i.read_field_begin()?;
205
206
0
            if field_ident.field_type == TType::Stop {
207
0
                break;
208
0
            }
209
210
0
            let id = field_ident
211
0
                .id
212
0
                .expect("sender should always specify id for non-STOP field");
213
214
0
            match id {
215
                1 => {
216
0
                    let remote_message = i.read_string()?;
217
0
                    i.read_field_end()?;
218
0
                    message = remote_message;
219
                }
220
                2 => {
221
0
                    let remote_type_as_int = i.read_i32()?;
222
0
                    let remote_kind: ApplicationErrorKind = TryFrom::try_from(remote_type_as_int)
223
0
                        .unwrap_or(ApplicationErrorKind::Unknown);
224
0
                    i.read_field_end()?;
225
0
                    kind = remote_kind;
226
                }
227
                _ => {
228
0
                    i.skip(field_ident.field_type)?;
229
                }
230
            }
231
        }
232
233
0
        i.read_struct_end()?;
234
235
0
        Ok(ApplicationError { kind, message })
236
0
    }
237
238
    /// Convert an `ApplicationError` into its wire representation and write
239
    /// it to the remote.
240
    ///
241
    /// Application code **should never** call this method directly.
242
0
    pub fn write_application_error_to_out_protocol(
243
0
        e: &ApplicationError,
244
0
        o: &mut dyn TOutputProtocol,
245
0
    ) -> crate::Result<()> {
246
0
        o.write_struct_begin(&TStructIdentifier {
247
0
            name: "TApplicationException".to_owned(),
248
0
        })?;
249
250
0
        let message_field = TFieldIdentifier::new("message", TType::String, 1);
251
0
        let type_field = TFieldIdentifier::new("type", TType::I32, 2);
252
253
0
        o.write_field_begin(&message_field)?;
254
0
        o.write_string(&e.message)?;
255
0
        o.write_field_end()?;
256
257
0
        o.write_field_begin(&type_field)?;
258
0
        o.write_i32(e.kind as i32)?;
259
0
        o.write_field_end()?;
260
261
0
        o.write_field_stop()?;
262
0
        o.write_struct_end()?;
263
264
0
        o.flush()
265
0
    }
266
}
267
268
impl error::Error for Error {}
269
270
impl Debug for Error {
271
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
272
0
        match *self {
273
0
            Error::Transport(ref e) => Debug::fmt(e, f),
274
0
            Error::Protocol(ref e) => Debug::fmt(e, f),
275
0
            Error::Application(ref e) => Debug::fmt(e, f),
276
0
            Error::User(ref e) => Debug::fmt(e, f),
277
        }
278
0
    }
279
}
280
281
impl Display for Error {
282
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
283
0
        match *self {
284
0
            Error::Transport(ref e) => Display::fmt(e, f),
285
0
            Error::Protocol(ref e) => Display::fmt(e, f),
286
0
            Error::Application(ref e) => Display::fmt(e, f),
287
0
            Error::User(ref e) => Display::fmt(e, f),
288
        }
289
0
    }
290
}
291
292
impl From<String> for Error {
293
0
    fn from(s: String) -> Self {
294
0
        Error::Application(ApplicationError {
295
0
            kind: ApplicationErrorKind::Unknown,
296
0
            message: s,
297
0
        })
298
0
    }
299
}
300
301
impl<'a> From<&'a str> for Error {
302
0
    fn from(s: &'a str) -> Self {
303
0
        Error::Application(ApplicationError {
304
0
            kind: ApplicationErrorKind::Unknown,
305
0
            message: String::from(s),
306
0
        })
307
0
    }
308
}
309
310
impl From<TransportError> for Error {
311
0
    fn from(e: TransportError) -> Self {
312
0
        Error::Transport(e)
313
0
    }
314
}
315
316
impl From<ProtocolError> for Error {
317
0
    fn from(e: ProtocolError) -> Self {
318
0
        Error::Protocol(e)
319
0
    }
320
}
321
322
impl From<ApplicationError> for Error {
323
0
    fn from(e: ApplicationError) -> Self {
324
0
        Error::Application(e)
325
0
    }
326
}
327
328
/// Create a new `Error` instance of type `Transport` that wraps a
329
/// `TransportError`.
330
0
pub fn new_transport_error<S: Into<String>>(kind: TransportErrorKind, message: S) -> Error {
331
0
    Error::Transport(TransportError::new(kind, message))
332
0
}
333
334
/// Information about I/O errors.
335
#[derive(Debug, Eq, PartialEq)]
336
pub struct TransportError {
337
    /// I/O error variant.
338
    ///
339
    /// If a specific `TransportErrorKind` does not apply use
340
    /// `TransportErrorKind::Unknown`.
341
    pub kind: TransportErrorKind,
342
    /// Human-readable error message.
343
    pub message: String,
344
}
345
346
impl TransportError {
347
    /// Create a new `TransportError`.
348
0
    pub fn new<S: Into<String>>(kind: TransportErrorKind, message: S) -> TransportError {
349
0
        TransportError {
350
0
            kind,
351
0
            message: message.into(),
352
0
        }
353
0
    }
354
}
355
356
/// I/O error categories.
357
///
358
/// This list may grow, and it is not recommended to match against it.
359
#[non_exhaustive]
360
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
361
pub enum TransportErrorKind {
362
    /// Catch-all I/O error.
363
    Unknown = 0,
364
    /// An I/O operation was attempted when the transport channel was not open.
365
    NotOpen = 1,
366
    /// The transport channel cannot be opened because it was opened previously.
367
    AlreadyOpen = 2,
368
    /// An I/O operation timed out.
369
    TimedOut = 3,
370
    /// A read could not complete because no bytes were available.
371
    EndOfFile = 4,
372
    /// An invalid (buffer/message) size was requested or received.
373
    NegativeSize = 5,
374
    /// Too large a buffer or message size was requested or received.
375
    SizeLimit = 6,
376
}
377
378
impl Display for TransportError {
379
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
380
0
        let error_text = match self.kind {
381
0
            TransportErrorKind::Unknown => "transport error",
382
0
            TransportErrorKind::NotOpen => "not open",
383
0
            TransportErrorKind::AlreadyOpen => "already open",
384
0
            TransportErrorKind::TimedOut => "timed out",
385
0
            TransportErrorKind::EndOfFile => "end of file",
386
0
            TransportErrorKind::NegativeSize => "negative size message",
387
0
            TransportErrorKind::SizeLimit => "message too long",
388
        };
389
390
0
        write!(f, "{}", error_text)
391
0
    }
392
}
393
394
impl TryFrom<i32> for TransportErrorKind {
395
    type Error = Error;
396
0
    fn try_from(from: i32) -> Result<Self, Self::Error> {
397
0
        match from {
398
0
            0 => Ok(TransportErrorKind::Unknown),
399
0
            1 => Ok(TransportErrorKind::NotOpen),
400
0
            2 => Ok(TransportErrorKind::AlreadyOpen),
401
0
            3 => Ok(TransportErrorKind::TimedOut),
402
0
            4 => Ok(TransportErrorKind::EndOfFile),
403
0
            5 => Ok(TransportErrorKind::NegativeSize),
404
0
            6 => Ok(TransportErrorKind::SizeLimit),
405
0
            _ => Err(Error::Protocol(ProtocolError {
406
0
                kind: ProtocolErrorKind::Unknown,
407
0
                message: format!("cannot convert {} to TransportErrorKind", from),
408
0
            })),
409
        }
410
0
    }
411
}
412
413
impl From<io::Error> for Error {
414
6.95k
    fn from(err: io::Error) -> Self {
415
6.95k
        match err.kind() {
416
            io::ErrorKind::ConnectionReset
417
            | io::ErrorKind::ConnectionRefused
418
0
            | io::ErrorKind::NotConnected => Error::Transport(TransportError {
419
0
                kind: TransportErrorKind::NotOpen,
420
0
                message: err.to_string(),
421
0
            }),
422
0
            io::ErrorKind::AlreadyExists => Error::Transport(TransportError {
423
0
                kind: TransportErrorKind::AlreadyOpen,
424
0
                message: err.to_string(),
425
0
            }),
426
0
            io::ErrorKind::TimedOut => Error::Transport(TransportError {
427
0
                kind: TransportErrorKind::TimedOut,
428
0
                message: err.to_string(),
429
0
            }),
430
5.50k
            io::ErrorKind::UnexpectedEof => Error::Transport(TransportError {
431
5.50k
                kind: TransportErrorKind::EndOfFile,
432
5.50k
                message: err.to_string(),
433
5.50k
            }),
434
            _ => {
435
1.45k
                Error::Transport(TransportError {
436
1.45k
                    kind: TransportErrorKind::Unknown,
437
1.45k
                    message: err.to_string(), // FIXME: use io error's debug string
438
1.45k
                })
439
            }
440
        }
441
6.95k
    }
442
}
443
444
impl From<uuid::Error> for Error {
445
0
    fn from(err: uuid::Error) -> Self {
446
0
        Error::Protocol(ProtocolError {
447
0
            kind: ProtocolErrorKind::InvalidData,
448
0
            message: err.to_string(), // FIXME: use fmt::Error's debug string
449
0
        })
450
0
    }
451
}
452
453
impl From<string::FromUtf8Error> for Error {
454
711
    fn from(err: string::FromUtf8Error) -> Self {
455
711
        Error::Protocol(ProtocolError {
456
711
            kind: ProtocolErrorKind::InvalidData,
457
711
            message: err.to_string(), // FIXME: use fmt::Error's debug string
458
711
        })
459
711
    }
460
}
461
462
/// Create a new `Error` instance of type `Protocol` that wraps a
463
/// `ProtocolError`.
464
0
pub fn new_protocol_error<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> Error {
465
0
    Error::Protocol(ProtocolError::new(kind, message))
466
0
}
467
468
/// Information about errors that occur in the runtime library.
469
#[derive(Debug, Eq, PartialEq)]
470
pub struct ProtocolError {
471
    /// Protocol error variant.
472
    ///
473
    /// If a specific `ProtocolErrorKind` does not apply use
474
    /// `ProtocolErrorKind::Unknown`.
475
    pub kind: ProtocolErrorKind,
476
    /// Human-readable error message.
477
    pub message: String,
478
}
479
480
impl ProtocolError {
481
    /// Create a new `ProtocolError`.
482
1.83k
    pub fn new<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> ProtocolError {
483
1.83k
        ProtocolError {
484
1.83k
            kind,
485
1.83k
            message: message.into(),
486
1.83k
        }
487
1.83k
    }
<thrift::errors::ProtocolError>::new::<alloc::string::String>
Line
Count
Source
482
1.46k
    pub fn new<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> ProtocolError {
483
1.46k
        ProtocolError {
484
1.46k
            kind,
485
1.46k
            message: message.into(),
486
1.46k
        }
487
1.46k
    }
<thrift::errors::ProtocolError>::new::<&str>
Line
Count
Source
482
376
    pub fn new<S: Into<String>>(kind: ProtocolErrorKind, message: S) -> ProtocolError {
483
376
        ProtocolError {
484
376
            kind,
485
376
            message: message.into(),
486
376
        }
487
376
    }
488
}
489
490
/// Runtime library error categories.
491
///
492
/// This list may grow, and it is not recommended to match against it.
493
#[non_exhaustive]
494
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
495
pub enum ProtocolErrorKind {
496
    /// Catch-all runtime-library error.
497
    Unknown = 0,
498
    /// An invalid argument was supplied to a library function, or invalid data
499
    /// was received from a Thrift endpoint.
500
    InvalidData = 1,
501
    /// An invalid size was received in an encoded field.
502
    NegativeSize = 2,
503
    /// Thrift message or field was too long.
504
    SizeLimit = 3,
505
    /// Unsupported or unknown Thrift protocol version.
506
    BadVersion = 4,
507
    /// Unsupported Thrift protocol, server or field type.
508
    NotImplemented = 5,
509
    /// Reached the maximum nested depth to which an encoded Thrift field could
510
    /// be skipped.
511
    DepthLimit = 6,
512
}
513
514
impl Display for ProtocolError {
515
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
516
0
        let error_text = match self.kind {
517
0
            ProtocolErrorKind::Unknown => "protocol error",
518
0
            ProtocolErrorKind::InvalidData => "bad data",
519
0
            ProtocolErrorKind::NegativeSize => "negative message size",
520
0
            ProtocolErrorKind::SizeLimit => "message too long",
521
0
            ProtocolErrorKind::BadVersion => "invalid thrift version",
522
0
            ProtocolErrorKind::NotImplemented => "not implemented",
523
0
            ProtocolErrorKind::DepthLimit => "maximum skip depth reached",
524
        };
525
526
0
        write!(f, "{}", error_text)
527
0
    }
528
}
529
530
impl TryFrom<i32> for ProtocolErrorKind {
531
    type Error = Error;
532
0
    fn try_from(from: i32) -> Result<Self, Self::Error> {
533
0
        match from {
534
0
            0 => Ok(ProtocolErrorKind::Unknown),
535
0
            1 => Ok(ProtocolErrorKind::InvalidData),
536
0
            2 => Ok(ProtocolErrorKind::NegativeSize),
537
0
            3 => Ok(ProtocolErrorKind::SizeLimit),
538
0
            4 => Ok(ProtocolErrorKind::BadVersion),
539
0
            5 => Ok(ProtocolErrorKind::NotImplemented),
540
0
            6 => Ok(ProtocolErrorKind::DepthLimit),
541
0
            _ => Err(Error::Protocol(ProtocolError {
542
0
                kind: ProtocolErrorKind::Unknown,
543
0
                message: format!("cannot convert {} to ProtocolErrorKind", from),
544
0
            })),
545
        }
546
0
    }
547
}
548
549
/// Create a new `Error` instance of type `Application` that wraps an
550
/// `ApplicationError`.
551
pub fn new_application_error<S: Into<String>>(kind: ApplicationErrorKind, message: S) -> Error {
552
    Error::Application(ApplicationError::new(kind, message))
553
}
554
555
/// Information about errors in auto-generated code or in user-implemented
556
/// service handlers.
557
#[derive(Debug, Eq, PartialEq)]
558
pub struct ApplicationError {
559
    /// Application error variant.
560
    ///
561
    /// If a specific `ApplicationErrorKind` does not apply use
562
    /// `ApplicationErrorKind::Unknown`.
563
    pub kind: ApplicationErrorKind,
564
    /// Human-readable error message.
565
    pub message: String,
566
}
567
568
impl ApplicationError {
569
    /// Create a new `ApplicationError`.
570
0
    pub fn new<S: Into<String>>(kind: ApplicationErrorKind, message: S) -> ApplicationError {
571
0
        ApplicationError {
572
0
            kind,
573
0
            message: message.into(),
574
0
        }
575
0
    }
576
}
577
578
/// Auto-generated or user-implemented code error categories.
579
///
580
/// This list may grow, and it is not recommended to match against it.
581
#[non_exhaustive]
582
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
583
pub enum ApplicationErrorKind {
584
    /// Catch-all application error.
585
    Unknown = 0,
586
    /// Made service call to an unknown service method.
587
    UnknownMethod = 1,
588
    /// Received an unknown Thrift message type. That is, not one of the
589
    /// `thrift::protocol::TMessageType` variants.
590
    InvalidMessageType = 2,
591
    /// Method name in a service reply does not match the name of the
592
    /// receiving service method.
593
    WrongMethodName = 3,
594
    /// Received an out-of-order Thrift message.
595
    BadSequenceId = 4,
596
    /// Service reply is missing required fields.
597
    MissingResult = 5,
598
    /// Auto-generated code failed unexpectedly.
599
    InternalError = 6,
600
    /// Thrift protocol error. When possible use `Error::ProtocolError` with a
601
    /// specific `ProtocolErrorKind` instead.
602
    ProtocolError = 7,
603
    /// *Unknown*. Included only for compatibility with existing Thrift implementations.
604
    InvalidTransform = 8, // ??
605
    /// Thrift endpoint requested, or is using, an unsupported encoding.
606
    InvalidProtocol = 9, // ??
607
    /// Thrift endpoint requested, or is using, an unsupported auto-generated client type.
608
    UnsupportedClientType = 10, // ??
609
}
610
611
impl Display for ApplicationError {
612
0
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
613
0
        let error_text = match self.kind {
614
0
            ApplicationErrorKind::Unknown => "service error",
615
0
            ApplicationErrorKind::UnknownMethod => "unknown service method",
616
0
            ApplicationErrorKind::InvalidMessageType => "wrong message type received",
617
0
            ApplicationErrorKind::WrongMethodName => "unknown method reply received",
618
0
            ApplicationErrorKind::BadSequenceId => "out of order sequence id",
619
0
            ApplicationErrorKind::MissingResult => "missing method result",
620
0
            ApplicationErrorKind::InternalError => "remote service threw exception",
621
0
            ApplicationErrorKind::ProtocolError => "protocol error",
622
0
            ApplicationErrorKind::InvalidTransform => "invalid transform",
623
0
            ApplicationErrorKind::InvalidProtocol => "invalid protocol requested",
624
0
            ApplicationErrorKind::UnsupportedClientType => "unsupported protocol client",
625
        };
626
627
0
        write!(f, "{}", error_text)
628
0
    }
629
}
630
631
impl TryFrom<i32> for ApplicationErrorKind {
632
    type Error = Error;
633
0
    fn try_from(from: i32) -> Result<Self, Self::Error> {
634
0
        match from {
635
0
            0 => Ok(ApplicationErrorKind::Unknown),
636
0
            1 => Ok(ApplicationErrorKind::UnknownMethod),
637
0
            2 => Ok(ApplicationErrorKind::InvalidMessageType),
638
0
            3 => Ok(ApplicationErrorKind::WrongMethodName),
639
0
            4 => Ok(ApplicationErrorKind::BadSequenceId),
640
0
            5 => Ok(ApplicationErrorKind::MissingResult),
641
0
            6 => Ok(ApplicationErrorKind::InternalError),
642
0
            7 => Ok(ApplicationErrorKind::ProtocolError),
643
0
            8 => Ok(ApplicationErrorKind::InvalidTransform),
644
0
            9 => Ok(ApplicationErrorKind::InvalidProtocol),
645
0
            10 => Ok(ApplicationErrorKind::UnsupportedClientType),
646
0
            _ => Err(Error::Application(ApplicationError {
647
0
                kind: ApplicationErrorKind::Unknown,
648
0
                message: format!("cannot convert {} to ApplicationErrorKind", from),
649
0
            })),
650
        }
651
0
    }
652
}