blob: 3f06909295d6ae1ee72a36e55ef707f208a4033c [file] [log] [blame]
Chih-Hung Hsiehcfc3a232020-06-10 20:13:05 -07001//! Protobuf error type
2
3use std::error::Error;
4use std::fmt;
5use std::io;
6use std::str;
7
Haibo Huangd32e6ee2020-08-12 13:52:04 -07008use crate::wire_format::WireType;
Chih-Hung Hsiehcfc3a232020-06-10 20:13:05 -07009
10/// `Result` alias for `ProtobufError`
11pub type ProtobufResult<T> = Result<T, ProtobufError>;
12
13/// Enum values added here for diagnostic purposes.
14/// Users should not depend on specific values.
15#[derive(Debug)]
16pub enum WireError {
17 /// Could not read complete message because stream is EOF
18 UnexpectedEof,
19 /// Wrong wire type for given field
20 UnexpectedWireType(WireType),
21 /// Incorrect tag value
22 IncorrectTag(u32),
23 /// Malformed map field
24 IncompleteMap,
25 /// Malformed varint
26 IncorrectVarint,
27 /// String is not valid UTD-8
28 Utf8Error,
29 /// Enum value is unknown
30 InvalidEnumValue(i32),
31 /// Message is too nested
32 OverRecursionLimit,
33 /// Could not read complete message because stream is EOF
34 TruncatedMessage,
35 /// Other error
36 Other,
37}
38
39impl fmt::Display for WireError {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 WireError::Utf8Error => write!(f, "invalid UTF-8 sequence"),
43 WireError::UnexpectedWireType(..) => write!(f, "unexpected wire type"),
44 WireError::InvalidEnumValue(..) => write!(f, "invalid enum value"),
45 WireError::IncorrectTag(..) => write!(f, "incorrect tag"),
46 WireError::IncorrectVarint => write!(f, "incorrect varint"),
47 WireError::IncompleteMap => write!(f, "incomplete map"),
48 WireError::UnexpectedEof => write!(f, "unexpected EOF"),
49 WireError::OverRecursionLimit => write!(f, "over recursion limit"),
50 WireError::TruncatedMessage => write!(f, "truncated message"),
51 WireError::Other => write!(f, "other error"),
52 }
53 }
54}
55
56/// Generic protobuf error
57#[derive(Debug)]
58pub enum ProtobufError {
59 /// I/O error when reading or writing
60 IoError(io::Error),
61 /// Malformed input
62 WireError(WireError),
63 /// Protocol contains a string which is not valid UTF-8 string
64 Utf8(str::Utf8Error),
65 /// Not all required fields set
66 MessageNotInitialized {
67 /// Message name
68 message: &'static str,
69 },
70}
71
72impl ProtobufError {
73 /// Create message not initialized error.
74 #[doc(hidden)]
75 pub fn message_not_initialized(message: &'static str) -> ProtobufError {
76 ProtobufError::MessageNotInitialized { message: message }
77 }
78}
79
80impl fmt::Display for ProtobufError {
81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82 match self {
83 // not sure that cause should be included in message
84 &ProtobufError::IoError(ref e) => write!(f, "IO error: {}", e),
85 &ProtobufError::WireError(ref e) => fmt::Display::fmt(e, f),
86 &ProtobufError::Utf8(ref e) => write!(f, "{}", e),
87 &ProtobufError::MessageNotInitialized { .. } => write!(f, "not all message fields set"),
88 }
89 }
90}
91
92impl Error for ProtobufError {
93 #[allow(deprecated)] // call to `description`
94 fn description(&self) -> &str {
95 match self {
96 // not sure that cause should be included in message
97 &ProtobufError::IoError(ref e) => e.description(),
98 &ProtobufError::WireError(ref e) => match *e {
99 WireError::Utf8Error => "invalid UTF-8 sequence",
100 WireError::UnexpectedWireType(..) => "unexpected wire type",
101 WireError::InvalidEnumValue(..) => "invalid enum value",
102 WireError::IncorrectTag(..) => "incorrect tag",
103 WireError::IncorrectVarint => "incorrect varint",
104 WireError::IncompleteMap => "incomplete map",
105 WireError::UnexpectedEof => "unexpected EOF",
106 WireError::OverRecursionLimit => "over recursion limit",
107 WireError::TruncatedMessage => "truncated message",
108 WireError::Other => "other error",
109 },
110 &ProtobufError::Utf8(ref e) => &e.description(),
111 &ProtobufError::MessageNotInitialized { .. } => "not all message fields set",
112 }
113 }
114
Haibo Huang4bf8b462020-11-24 20:53:50 -0800115 fn cause(&self) -> Option<&dyn Error> {
Chih-Hung Hsiehcfc3a232020-06-10 20:13:05 -0700116 match self {
117 &ProtobufError::IoError(ref e) => Some(e),
118 &ProtobufError::Utf8(ref e) => Some(e),
119 &ProtobufError::WireError(..) => None,
120 &ProtobufError::MessageNotInitialized { .. } => None,
121 }
122 }
123}
124
125impl From<io::Error> for ProtobufError {
126 fn from(err: io::Error) -> Self {
127 ProtobufError::IoError(err)
128 }
129}
130
131impl From<str::Utf8Error> for ProtobufError {
132 fn from(err: str::Utf8Error) -> Self {
133 ProtobufError::Utf8(err)
134 }
135}
136
137impl From<ProtobufError> for io::Error {
138 fn from(err: ProtobufError) -> Self {
139 match err {
140 ProtobufError::IoError(e) => e,
141 ProtobufError::WireError(e) => {
142 io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
143 }
144 ProtobufError::MessageNotInitialized { message: msg } => io::Error::new(
145 io::ErrorKind::InvalidInput,
146 ProtobufError::MessageNotInitialized { message: msg },
147 ),
148 e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
149 }
150 }
151}