152 lines
5.2 KiB
Rust
152 lines
5.2 KiB
Rust
//! 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<T> = Result<T, ProtobufError>;
|
|
|
|
/// 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<io::Error> for ProtobufError {
|
|
fn from(err: io::Error) -> Self {
|
|
ProtobufError::IoError(err)
|
|
}
|
|
}
|
|
|
|
impl From<str::Utf8Error> for ProtobufError {
|
|
fn from(err: str::Utf8Error) -> Self {
|
|
ProtobufError::Utf8(err)
|
|
}
|
|
}
|
|
|
|
impl From<ProtobufError> 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)),
|
|
}
|
|
}
|
|
}
|