//! Protobuf error type use std::error::Error; use std::fmt; use std::io; use std::str; use crate::wire_format::WireType; /// `Result` alias for `ProtobufError` pub type ProtobufResult = Result; /// Enum values added here for diagnostic purposes. /// Users should not depend on specific values. #[derive(Debug)] pub enum WireError { /// Could not read complete message because stream is EOF UnexpectedEof, /// Wrong wire type for given field UnexpectedWireType(WireType), /// Incorrect tag value IncorrectTag(u32), /// Malformed map field IncompleteMap, /// Malformed varint IncorrectVarint, /// String is not valid UTD-8 Utf8Error, /// Enum value is unknown InvalidEnumValue(i32), /// Message is too nested OverRecursionLimit, /// Could not read complete message because stream is EOF TruncatedMessage, /// Other error Other, } impl fmt::Display for WireError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { WireError::Utf8Error => write!(f, "invalid UTF-8 sequence"), WireError::UnexpectedWireType(..) => write!(f, "unexpected wire type"), WireError::InvalidEnumValue(..) => write!(f, "invalid enum value"), WireError::IncorrectTag(..) => write!(f, "incorrect tag"), WireError::IncorrectVarint => write!(f, "incorrect varint"), WireError::IncompleteMap => write!(f, "incomplete map"), WireError::UnexpectedEof => write!(f, "unexpected EOF"), WireError::OverRecursionLimit => write!(f, "over recursion limit"), WireError::TruncatedMessage => write!(f, "truncated message"), WireError::Other => write!(f, "other error"), } } } /// Generic protobuf error #[derive(Debug)] pub enum ProtobufError { /// I/O error when reading or writing IoError(io::Error), /// Malformed input WireError(WireError), /// Protocol contains a string which is not valid UTF-8 string Utf8(str::Utf8Error), /// Not all required fields set MessageNotInitialized { /// Message name message: &'static str, }, } impl ProtobufError { /// Create message not initialized error. #[doc(hidden)] pub fn message_not_initialized(message: &'static str) -> ProtobufError { ProtobufError::MessageNotInitialized { message: message } } } impl fmt::Display for ProtobufError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { // not sure that cause should be included in message &ProtobufError::IoError(ref e) => write!(f, "IO error: {}", e), &ProtobufError::WireError(ref e) => fmt::Display::fmt(e, f), &ProtobufError::Utf8(ref e) => write!(f, "{}", e), &ProtobufError::MessageNotInitialized { .. } => write!(f, "not all message fields set"), } } } impl Error for ProtobufError { #[allow(deprecated)] // call to `description` fn description(&self) -> &str { match self { // not sure that cause should be included in message &ProtobufError::IoError(ref e) => e.description(), &ProtobufError::WireError(ref e) => match *e { WireError::Utf8Error => "invalid UTF-8 sequence", WireError::UnexpectedWireType(..) => "unexpected wire type", WireError::InvalidEnumValue(..) => "invalid enum value", WireError::IncorrectTag(..) => "incorrect tag", WireError::IncorrectVarint => "incorrect varint", WireError::IncompleteMap => "incomplete map", WireError::UnexpectedEof => "unexpected EOF", WireError::OverRecursionLimit => "over recursion limit", WireError::TruncatedMessage => "truncated message", WireError::Other => "other error", }, &ProtobufError::Utf8(ref e) => &e.description(), &ProtobufError::MessageNotInitialized { .. } => "not all message fields set", } } fn cause(&self) -> Option<&dyn Error> { match self { &ProtobufError::IoError(ref e) => Some(e), &ProtobufError::Utf8(ref e) => Some(e), &ProtobufError::WireError(..) => None, &ProtobufError::MessageNotInitialized { .. } => None, } } } impl From for ProtobufError { fn from(err: io::Error) -> Self { ProtobufError::IoError(err) } } impl From for ProtobufError { fn from(err: str::Utf8Error) -> Self { ProtobufError::Utf8(err) } } impl From for io::Error { fn from(err: ProtobufError) -> Self { match err { ProtobufError::IoError(e) => e, ProtobufError::WireError(e) => { io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e)) } ProtobufError::MessageNotInitialized { message: msg } => io::Error::new( io::ErrorKind::InvalidInput, ProtobufError::MessageNotInitialized { message: msg }, ), e => io::Error::new(io::ErrorKind::Other, Box::new(e)), } } }