1 // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0. 2 3 use std::{error, fmt, result}; 4 5 use crate::call::RpcStatus; 6 use crate::grpc_sys::grpc_call_error; 7 8 #[cfg(feature = "prost-codec")] 9 use prost::DecodeError; 10 #[cfg(feature = "protobuf-codec")] 11 use protobuf::ProtobufError; 12 13 /// Errors generated from this library. 14 #[derive(Debug)] 15 pub 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 38 impl fmt::Display for Error { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result39 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 50 impl error::Error for Error { source(&self) -> Option<&(dyn error::Error + 'static)>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")] 60 impl From<ProtobufError> for Error { from(e: ProtobufError) -> Error61 fn from(e: ProtobufError) -> Error { 62 Error::Codec(Box::new(e)) 63 } 64 } 65 66 #[cfg(feature = "prost-codec")] 67 impl From<DecodeError> for Error { from(e: DecodeError) -> Error68 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`. 74 pub type Result<T> = result::Result<T, Error>; 75 76 #[cfg(all(test, feature = "protobuf-codec"))] 77 mod 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] test_convert()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 } 93