1use alloc::borrow::Cow;
4#[cfg(not(feature = "std"))]
5use alloc::boxed::Box;
6#[cfg(not(feature = "std"))]
7use alloc::vec::Vec;
8
9use core::fmt;
10
11#[derive(Clone, PartialEq, Eq)]
17pub struct DecodeError {
18 inner: Box<Inner>,
19}
20
21#[derive(Clone, PartialEq, Eq)]
22struct Inner {
23 description: Cow<'static, str>,
25 stack: Vec<(&'static str, &'static str)>,
29}
30
31impl DecodeError {
32 #[doc(hidden)]
36 #[cold]
37 pub fn new(description: impl Into<Cow<'static, str>>) -> DecodeError {
38 DecodeError {
39 inner: Box::new(Inner {
40 description: description.into(),
41 stack: Vec::new(),
42 }),
43 }
44 }
45
46 #[doc(hidden)]
50 pub fn push(&mut self, message: &'static str, field: &'static str) {
51 self.inner.stack.push((message, field));
52 }
53}
54
55impl fmt::Debug for DecodeError {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.debug_struct("DecodeError")
58 .field("description", &self.inner.description)
59 .field("stack", &self.inner.stack)
60 .finish()
61 }
62}
63
64impl fmt::Display for DecodeError {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 f.write_str("failed to decode Protobuf message: ")?;
67 for &(message, field) in &self.inner.stack {
68 write!(f, "{}.{}: ", message, field)?;
69 }
70 f.write_str(&self.inner.description)
71 }
72}
73
74#[cfg(feature = "std")]
75impl std::error::Error for DecodeError {}
76
77#[cfg(feature = "std")]
78impl From<DecodeError> for std::io::Error {
79 fn from(error: DecodeError) -> std::io::Error {
80 std::io::Error::new(std::io::ErrorKind::InvalidData, error)
81 }
82}
83
84#[derive(Copy, Clone, Debug, PartialEq, Eq)]
90pub struct EncodeError {
91 required: usize,
92 remaining: usize,
93}
94
95impl EncodeError {
96 pub(crate) fn new(required: usize, remaining: usize) -> EncodeError {
98 EncodeError {
99 required,
100 remaining,
101 }
102 }
103
104 pub fn required_capacity(&self) -> usize {
106 self.required
107 }
108
109 pub fn remaining(&self) -> usize {
111 self.remaining
112 }
113}
114
115impl fmt::Display for EncodeError {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 write!(
118 f,
119 "failed to encode Protobuf message; insufficient buffer capacity (required: {}, remaining: {})",
120 self.required, self.remaining
121 )
122 }
123}
124
125#[cfg(feature = "std")]
126impl std::error::Error for EncodeError {}
127
128#[cfg(feature = "std")]
129impl From<EncodeError> for std::io::Error {
130 fn from(error: EncodeError) -> std::io::Error {
131 std::io::Error::new(std::io::ErrorKind::InvalidInput, error)
132 }
133}
134
135#[derive(Copy, Clone, Debug, PartialEq, Eq)]
141pub struct UnknownEnumValue(pub i32);
142
143impl fmt::Display for UnknownEnumValue {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 write!(f, "unknown enumeration value {}", self.0)
146 }
147}
148
149#[cfg(feature = "std")]
150impl std::error::Error for UnknownEnumValue {}
151
152#[cfg(test)]
153mod test {
154 use super::*;
155
156 #[test]
157 fn test_push() {
158 let mut decode_error = DecodeError::new("something failed");
159 decode_error.push("Foo bad", "bar.foo");
160 decode_error.push("Baz bad", "bar.baz");
161
162 assert_eq!(
163 decode_error.to_string(),
164 "failed to decode Protobuf message: Foo bad.bar.foo: Baz bad.bar.baz: something failed"
165 );
166 }
167
168 #[cfg(feature = "std")]
169 #[test]
170 fn test_into_std_io_error() {
171 let decode_error = DecodeError::new("something failed");
172 let std_io_error = std::io::Error::from(decode_error);
173
174 assert_eq!(std_io_error.kind(), std::io::ErrorKind::InvalidData);
175 assert_eq!(
176 std_io_error.to_string(),
177 "failed to decode Protobuf message: something failed"
178 );
179 }
180}