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