blob: f12ffa4dba5a1e64971b50df32f5b5798dc1a1e5 [file] [log] [blame]
Jeff Vander Stoep761577d2020-10-14 15:21:00 +02001// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
2
3use std::{error, fmt, result};
4
5use crate::call::RpcStatus;
6use crate::grpc_sys::grpc_call_error;
7
8#[cfg(feature = "prost-codec")]
9use prost::DecodeError;
10#[cfg(feature = "protobuf-codec")]
11use protobuf::ProtobufError;
12
13/// Errors generated from this library.
14#[derive(Debug)]
15pub enum Error {
16 /// Codec error.
17 Codec(Box<dyn error::Error + Send + Sync>),
18 /// Failed to start an internal async call.
19 CallFailure(grpc_call_error),
20 /// Rpc request fail.
21 RpcFailure(RpcStatus),
22 /// Try to write to a finished rpc call.
23 RpcFinished(Option<RpcStatus>),
24 /// Remote is stopped.
25 RemoteStopped,
26 /// Failed to shutdown.
27 ShutdownFailed,
28 /// Failed to bind.
29 BindFail(String, u16),
30 /// gRPC completion queue is shutdown.
31 QueueShutdown,
32 /// Failed to create Google default credentials.
33 GoogleAuthenticationFailed,
34 /// Invalid format of metadata.
35 InvalidMetadata(String),
36}
37
38impl fmt::Display for Error {
39 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
40 match self {
41 Error::RpcFailure(RpcStatus { status, details }) => match details {
42 Some(details) => write!(fmt, "RpcFailure: {} {}", status, details),
43 None => write!(fmt, "RpcFailure: {}", status),
44 },
45 other_error => write!(fmt, "{:?}", other_error),
46 }
47 }
48}
49
50impl error::Error for Error {
51 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
52 match *self {
53 Error::Codec(ref e) => Some(e.as_ref()),
54 _ => None,
55 }
56 }
57}
58
59#[cfg(feature = "protobuf-codec")]
60impl From<ProtobufError> for Error {
61 fn from(e: ProtobufError) -> Error {
62 Error::Codec(Box::new(e))
63 }
64}
65
66#[cfg(feature = "prost-codec")]
67impl From<DecodeError> for Error {
68 fn from(e: DecodeError) -> Error {
69 Error::Codec(Box::new(e))
70 }
71}
72
73/// Type alias to use this library's [`Error`] type in a `Result`.
74pub type Result<T> = result::Result<T, Error>;
75
76#[cfg(all(test, feature = "protobuf-codec"))]
77mod tests {
78 use std::error::Error as StdError;
79
80 use protobuf::error::WireError;
81 use protobuf::ProtobufError;
82
83 use super::Error;
84
85 #[test]
86 fn test_convert() {
87 let error = ProtobufError::WireError(WireError::UnexpectedEof);
88 let e: Error = error.into();
89 assert_eq!(e.to_string(), "Codec(WireError(UnexpectedEof))");
90 assert!(e.source().is_some());
91 }
92}