protobuf/
error.rs

1use std::io;
2use std::str;
3
4use crate::reflect::error::ReflectError;
5use crate::wire_format::WireType;
6
7/// [`Result`] alias for [`Error`].
8pub 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)]
13pub(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)]
45pub(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)]
78pub struct Error(pub(crate) Box<ProtobufError>);
79
80impl From<ProtobufError> for Error {
81    #[cold]
82    fn from(e: ProtobufError) -> Self {
83        Self(Box::new(e))
84    }
85}
86
87impl From<WireError> for Error {
88    #[cold]
89    fn from(e: WireError) -> Self {
90        Self(Box::new(ProtobufError::WireError(e)))
91    }
92}
93
94impl From<ReflectError> for Error {
95    #[cold]
96    fn from(e: ReflectError) -> Self {
97        Self(Box::new(ProtobufError::Reflect(e)))
98    }
99}
100
101impl From<Error> for io::Error {
102    #[cold]
103    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
118impl From<io::Error> for Error {
119    #[cold]
120    fn from(err: io::Error) -> Self {
121        Error(Box::new(ProtobufError::IoError(err)))
122    }
123}
124
125#[cfg(test)]
126mod test {
127    use std::mem;
128
129    #[test]
130    fn error_size() {
131        assert_eq!(mem::size_of::<usize>(), mem::size_of::<crate::Error>());
132    }
133}