prost_bytes05/
error.rs

1//! Protobuf encoding and decoding errors.
2
3use std::borrow::Cow;
4use std::error;
5use std::fmt;
6use std::io;
7
8/// A Protobuf message decoding error.
9///
10/// `DecodeError` indicates that the input buffer does not caontain a valid
11/// Protobuf message. The error details should be considered 'best effort': in
12/// general it is not possible to exactly pinpoint why data is malformed.
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct DecodeError {
15    /// A 'best effort' root cause description.
16    description: Cow<'static, str>,
17    /// A stack of (message, field) name pairs, which identify the specific
18    /// message type and field where decoding failed. The stack contains an
19    /// entry per level of nesting.
20    stack: Vec<(&'static str, &'static str)>,
21}
22
23impl DecodeError {
24    /// Creates a new `DecodeError` with a 'best effort' root cause description.
25    ///
26    /// Meant to be used only by `Message` implementations.
27    #[doc(hidden)]
28    pub fn new<S>(description: S) -> DecodeError
29    where
30        S: Into<Cow<'static, str>>,
31    {
32        DecodeError {
33            description: description.into(),
34            stack: Vec::new(),
35        }
36    }
37
38    /// Pushes a (message, field) name location pair on to the location stack.
39    ///
40    /// Meant to be used only by `Message` implementations.
41    #[doc(hidden)]
42    pub fn push(&mut self, message: &'static str, field: &'static str) {
43        self.stack.push((message, field));
44    }
45}
46
47impl fmt::Display for DecodeError {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        f.write_str("failed to decode Protobuf message: ")?;
50        for &(message, field) in &self.stack {
51            write!(f, "{}.{}: ", message, field)?;
52        }
53        f.write_str(&self.description)
54    }
55}
56
57impl error::Error for DecodeError {
58    fn description(&self) -> &str {
59        &self.description
60    }
61}
62
63impl From<DecodeError> for io::Error {
64    fn from(error: DecodeError) -> io::Error {
65        io::Error::new(io::ErrorKind::InvalidData, error)
66    }
67}
68
69/// A Protobuf message encoding error.
70///
71/// `EncodeError` always indicates that a message failed to encode because the
72/// provided buffer had insufficient capacity. Message encoding is otherwise
73/// infallible.
74#[derive(Copy, Clone, Debug, PartialEq, Eq)]
75pub struct EncodeError {
76    required: usize,
77    remaining: usize,
78}
79
80impl EncodeError {
81    /// Creates a new `EncodeError`.
82    pub(crate) fn new(required: usize, remaining: usize) -> EncodeError {
83        EncodeError {
84            required,
85            remaining,
86        }
87    }
88
89    /// Returns the required buffer capacity to encode the message.
90    pub fn required_capacity(&self) -> usize {
91        self.required
92    }
93
94    /// Returns the remaining length in the provided buffer at the time of encoding.
95    pub fn remaining(&self) -> usize {
96        self.remaining
97    }
98}
99
100impl fmt::Display for EncodeError {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        f.write_str(error::Error::description(self))?;
103        write!(
104            f,
105            " (required: {}, remaining: {})",
106            self.required, self.remaining
107        )
108    }
109}
110
111impl error::Error for EncodeError {
112    fn description(&self) -> &str {
113        "failed to encode Protobuf message: insufficient buffer capacity"
114    }
115}
116
117impl From<EncodeError> for io::Error {
118    fn from(error: EncodeError) -> io::Error {
119        io::Error::new(io::ErrorKind::InvalidInput, error)
120    }
121}