1 use std::io;
2 use std::str;
3 
4 use crate::reflect::error::ReflectError;
5 use crate::wire_format::WireType;
6 
7 /// [`Result`] alias for [`Error`].
8 pub type Result<T> = std::result::Result<T, crate::Error>;
9 
10 /// Enum values added here for diagnostic purposes.
11 /// Users should not depend on specific values.
12 #[derive(Debug, thiserror::Error)]
13 pub(crate) enum WireError {
14     #[error("Unexpected EOF")]
15     UnexpectedEof,
16     #[error("Unexpected wire type")]
17     UnexpectedWireType(WireType),
18     #[error("Incorrect tag")]
19     IncorrectTag(u32),
20     #[error("Incorrect varint")]
21     IncorrectVarint,
22     #[error("Invalid UTF-8 sequence")]
23     Utf8Error,
24     #[error("Invalid enum `{}` value: {}", .0, .1)]
25     InvalidEnumValue(&'static str, i32),
26     #[error("Over recursion limit")]
27     OverRecursionLimit,
28     #[error("Truncated message")]
29     TruncatedMessage,
30     // not really possible
31     #[error("Limit overflow")]
32     LimitOverflow,
33     #[error("New limit must not be greater than current limit")]
34     LimitIncrease,
35     #[error("Encoded message size {0} is too large")]
36     MessageTooLarge(u64),
37     #[error("Value too large for u32: {}", .0)]
38     U32Overflow(u64),
39     #[error("Value too large for i32: {}", .0)]
40     I32Overflow(i64),
41 }
42 
43 /// Generic protobuf error
44 #[derive(Debug, thiserror::Error)]
45 pub(crate) enum ProtobufError {
46     /// I/O error when reading or writing
47     #[error(transparent)]
48     IoError(#[from] io::Error),
49     /// Malformed input
50     #[error(transparent)]
51     WireError(#[from] WireError),
52     #[error(transparent)]
53     Reflect(#[from] ReflectError),
54     /// Protocol contains a string which is not valid UTF-8 string
55     #[error("UTF-8 decode error")]
56     Utf8(
57         #[source]
58         #[from]
59         str::Utf8Error,
60     ),
61     /// Not all required fields of message set.
62     #[error("Message `{}` is missing required fields", .0)]
63     MessageNotInitialized(String),
64     /// Message is too large.
65     #[error("Provided buffer has not enough capacity to write message `{0}`")]
66     BufferHasNotEnoughCapacity(String),
67     /// Protobuf type and runtime types mismatch.
68     #[error("Protobuf type and runtime types are not compatible")]
69     IncompatibleProtobufTypeAndRuntimeType,
70     /// Group field type not implemented.
71     #[error("Group field is not supported")]
72     GroupIsNotImplemented,
73 }
74 
75 /// Error type for protobuf operations.
76 #[derive(Debug, thiserror::Error)]
77 #[error(transparent)]
78 pub struct Error(pub(crate) Box<ProtobufError>);
79 
80 impl From<ProtobufError> for Error {
81     #[cold]
from(e: ProtobufError) -> Self82     fn from(e: ProtobufError) -> Self {
83         Self(Box::new(e))
84     }
85 }
86 
87 impl From<WireError> for Error {
88     #[cold]
from(e: WireError) -> Self89     fn from(e: WireError) -> Self {
90         Self(Box::new(ProtobufError::WireError(e)))
91     }
92 }
93 
94 impl From<ReflectError> for Error {
95     #[cold]
from(e: ReflectError) -> Self96     fn from(e: ReflectError) -> Self {
97         Self(Box::new(ProtobufError::Reflect(e)))
98     }
99 }
100 
101 impl From<Error> for io::Error {
102     #[cold]
from(err: Error) -> Self103     fn from(err: Error) -> Self {
104         match *err.0 {
105             ProtobufError::IoError(e) => e,
106             ProtobufError::WireError(e) => {
107                 io::Error::new(io::ErrorKind::InvalidData, ProtobufError::WireError(e))
108             }
109             ProtobufError::MessageNotInitialized(message) => io::Error::new(
110                 io::ErrorKind::InvalidInput,
111                 ProtobufError::MessageNotInitialized(message),
112             ),
113             e => io::Error::new(io::ErrorKind::Other, Box::new(e)),
114         }
115     }
116 }
117 
118 impl From<io::Error> for Error {
119     #[cold]
from(err: io::Error) -> Self120     fn from(err: io::Error) -> Self {
121         Error(Box::new(ProtobufError::IoError(err)))
122     }
123 }
124 
125 #[cfg(test)]
126 mod test {
127     use std::mem;
128 
129     #[test]
error_size()130     fn error_size() {
131         assert_eq!(mem::size_of::<usize>(), mem::size_of::<crate::Error>());
132     }
133 }
134