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 = "protobuf-codec")] 9 use protobuf::ProtobufError; 10 11 /// Errors generated from this library. 12 #[derive(Debug)] 13 pub enum Error { 14 /// Codec error. 15 Codec(Box<dyn error::Error + Send + Sync>), 16 /// Failed to start an internal async call. 17 CallFailure(grpc_call_error), 18 /// Rpc request fail. 19 RpcFailure(RpcStatus), 20 /// Try to write to a finished rpc call. 21 RpcFinished(Option<RpcStatus>), 22 /// Remote is stopped. 23 RemoteStopped, 24 /// Failed to shutdown. 25 ShutdownFailed, 26 /// Failed to bind. 27 BindFail(String, u16), 28 /// gRPC completion queue is shutdown. 29 QueueShutdown, 30 /// Failed to create Google default credentials. 31 GoogleAuthenticationFailed, 32 /// Invalid format of metadata. 33 InvalidMetadata(String), 34 } 35 36 impl fmt::Display for Error { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result37 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 38 match self { 39 Error::RpcFailure(s) => { 40 if s.message().is_empty() { 41 write!(fmt, "RpcFailure: {}", s.code()) 42 } else { 43 write!(fmt, "RpcFailure: {} {}", s.code(), s.message()) 44 } 45 } 46 other_error => write!(fmt, "{:?}", other_error), 47 } 48 } 49 } 50 51 impl error::Error for Error { source(&self) -> Option<&(dyn error::Error + 'static)>52 fn source(&self) -> Option<&(dyn error::Error + 'static)> { 53 match *self { 54 Error::Codec(ref e) => Some(e.as_ref()), 55 _ => None, 56 } 57 } 58 } 59 60 #[cfg(feature = "protobuf-codec")] 61 impl From<ProtobufError> for Error { from(e: ProtobufError) -> Error62 fn from(e: ProtobufError) -> Error { 63 Error::Codec(Box::new(e)) 64 } 65 } 66 67 #[cfg(feature = "prost-codec")] 68 impl From<prost::DecodeError> for Error { from(e: prost::DecodeError) -> Error69 fn from(e: prost::DecodeError) -> Error { 70 Error::Codec(Box::new(e)) 71 } 72 } 73 74 #[cfg(feature = "prost-codec")] 75 impl From<prost::EncodeError> for Error { from(e: prost::EncodeError) -> Error76 fn from(e: prost::EncodeError) -> Error { 77 Error::Codec(Box::new(e)) 78 } 79 } 80 81 /// Type alias to use this library's [`Error`] type in a `Result`. 82 pub type Result<T> = result::Result<T, Error>; 83 84 #[cfg(all(test, feature = "protobuf-codec"))] 85 mod tests { 86 use std::error::Error as StdError; 87 88 use protobuf::error::WireError; 89 use protobuf::ProtobufError; 90 91 use super::Error; 92 93 #[test] test_convert()94 fn test_convert() { 95 let error = ProtobufError::WireError(WireError::UnexpectedEof); 96 let e: Error = error.into(); 97 assert_eq!(e.to_string(), "Codec(WireError(UnexpectedEof))"); 98 assert!(e.source().is_some()); 99 } 100 } 101