bincode_purplecoin/error.rs
1//! Errors that can be encounting by Encoding and Decoding.
2
3/// Errors that can be encountered by encoding a type
4#[non_exhaustive]
5#[derive(Debug)]
6pub enum EncodeError {
7 /// The writer ran out of storage.
8 UnexpectedEnd,
9
10 /// The RefCell<T> is already borrowed
11 RefCellAlreadyBorrowed {
12 /// The inner borrow error
13 inner: core::cell::BorrowError,
14 /// the type name of the RefCell being encoded that is currently borrowed.
15 type_name: &'static str,
16 },
17
18 /// An uncommon error occurred, see the inner text for more information
19 Other(&'static str),
20
21 /// An uncommon error occurred, see the inner text for more information
22 #[cfg(feature = "alloc")]
23 OtherString(alloc::string::String),
24
25 /// A `std::path::Path` was being encoded but did not contain a valid `&str` representation
26 #[cfg(feature = "std")]
27 InvalidPathCharacters,
28
29 /// The targeted writer encountered an `std::io::Error`
30 #[cfg(feature = "std")]
31 Io {
32 /// The encountered error
33 error: std::io::Error,
34 /// The amount of bytes that were written before the error occurred
35 index: usize,
36 },
37
38 /// The encoder tried to encode a `Mutex` or `RwLock`, but the locking failed
39 #[cfg(feature = "std")]
40 LockFailed {
41 /// The type name of the mutex for debugging purposes
42 type_name: &'static str,
43 },
44
45 /// The encoder tried to encode a `SystemTime`, but it was before `SystemTime::UNIX_EPOCH`
46 #[cfg(feature = "std")]
47 InvalidSystemTime {
48 /// The error that was thrown by the SystemTime
49 inner: std::time::SystemTimeError,
50 /// The SystemTime that caused the error
51 time: std::time::SystemTime,
52 },
53
54 #[cfg(feature = "serde")]
55 /// A serde-specific error that occurred while decoding.
56 Serde(crate::features::serde::EncodeError),
57}
58
59impl core::fmt::Display for EncodeError {
60 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
61 // TODO: Improve this?
62 write!(f, "{:?}", self)
63 }
64}
65
66/// Errors that can be encountered by decoding a type
67#[non_exhaustive]
68#[derive(Debug, PartialEq)]
69pub enum DecodeError {
70 /// The reader reached its end but more bytes were expected.
71 UnexpectedEnd,
72
73 /// The given configuration limit was exceeded
74 LimitExceeded,
75
76 /// Invalid type was found. The decoder tried to read type `expected`, but found type `found` instead.
77 InvalidIntegerType {
78 /// The type that was being read from the reader
79 expected: IntegerType,
80 /// The type that was encoded in the data
81 found: IntegerType,
82 },
83
84 /// The decoder tried to decode any of the `NonZero*` types but the value is zero
85 NonZeroTypeIsZero {
86 /// The type that was being read from the reader
87 non_zero_type: IntegerType,
88 },
89
90 /// Invalid enum variant was found. The decoder tried to decode variant index `found`, but the variant index should be between `min` and `max`.
91 UnexpectedVariant {
92 /// The type name that was being decoded.
93 type_name: &'static str,
94
95 /// The variants that are allowed
96 allowed: AllowedEnumVariants,
97
98 /// The index of the enum that the decoder encountered
99 found: u8,
100 },
101
102 /// The decoder tried to decode a `str`, but an utf8 error was encountered.
103 Utf8(core::str::Utf8Error),
104
105 /// The decoder tried to decode a `char` and failed. The given buffer contains the bytes that are read at the moment of failure.
106 InvalidCharEncoding([u8; 4]),
107
108 /// The decoder tried to decode a `bool` and failed. The given value is what is actually read.
109 InvalidBooleanValue(u8),
110
111 /// The decoder tried to decode an array of length `required`, but the binary data contained an array of length `found`.
112 ArrayLengthMismatch {
113 /// The length of the array required by the rust type.
114 required: usize,
115 /// The length of the array found in the binary format.
116 found: usize,
117 },
118
119 /// The encoded value is outside of the range of the target usize type.
120 ///
121 /// This can happen if an usize was encoded on an architecture with a larger
122 /// usize type and then decoded on an architecture with a smaller one. For
123 /// example going from a 64 bit architecture to a 32 or 16 bit one may
124 /// cause this error.
125 OutsideUsizeRange(u64),
126
127 /// Tried to decode an enum with no variants
128 EmptyEnum {
129 /// The type that was being decoded
130 type_name: &'static str,
131 },
132
133 /// The decoder tried to decode a Duration and overflowed the number of seconds.
134 InvalidDuration {
135 /// The number of seconds in the duration.
136 secs: u64,
137
138 /// The number of nanoseconds in the duration, which when converted to seconds and added to
139 /// `secs`, overflows a `u64`.
140 nanos: u32,
141 },
142
143 /// The decoder tried to decode a SystemTime and overflowed
144 InvalidSystemTime {
145 /// The duration which could not have been added to
146 /// [`UNIX_EPOCH`](std::time::SystemTime::UNIX_EPOCH)
147 duration: core::time::Duration,
148 },
149
150 /// The decoder tried to decode a `CString`, but the incoming data contained a 0 byte
151 #[cfg(feature = "std")]
152 CStringNulError {
153 /// The inner exception
154 inner: std::ffi::NulError,
155 },
156
157 /// An uncommon error occurred, see the inner text for more information
158 #[cfg(feature = "alloc")]
159 OtherString(alloc::string::String),
160
161 #[cfg(feature = "serde")]
162 /// A serde-specific error that occurred while decoding.
163 Serde(crate::features::serde::DecodeError),
164}
165
166impl core::fmt::Display for DecodeError {
167 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
168 // TODO: Improve this?
169 write!(f, "{:?}", self)
170 }
171}
172
173impl DecodeError {
174 /// If the current error is `InvalidIntegerType`, change the `expected` and
175 /// `found` values from `Ux` to `Ix`. This is needed to have correct error
176 /// reporting in src/varint/decode_signed.rs since this calls
177 /// src/varint/decode_unsigned.rs and needs to correct the `expected` and
178 /// `found` types.
179 pub(crate) fn change_integer_type_to_signed(self) -> DecodeError {
180 match self {
181 Self::InvalidIntegerType { expected, found } => Self::InvalidIntegerType {
182 expected: expected.into_signed(),
183 found: found.into_signed(),
184 },
185 other => other,
186 }
187 }
188}
189
190/// Indicates which enum variants are allowed
191#[non_exhaustive]
192#[derive(Debug, PartialEq)]
193pub enum AllowedEnumVariants {
194 /// All values between `min` and `max` (inclusive) are allowed
195 #[allow(missing_docs)]
196 Range { min: u8, max: u8 },
197 /// Each one of these values is allowed
198 Allowed(&'static [u8]),
199}
200
201/// Integer types. Used by [DecodeError]. These types have no purpose other than being shown in errors.
202#[non_exhaustive]
203#[derive(Debug, PartialEq, Eq)]
204#[allow(missing_docs)]
205pub enum IntegerType {
206 U8,
207 U16,
208 U32,
209 U64,
210 U128,
211 Usize,
212
213 I8,
214 I16,
215 I32,
216 I64,
217 I128,
218 Isize,
219
220 Reserved,
221}
222
223impl IntegerType {
224 /// Change the `Ux` value to the associated `Ix` value.
225 /// Returns the old value if `self` is already `Ix`.
226 pub(crate) fn into_signed(self) -> Self {
227 match self {
228 Self::U8 => Self::I8,
229 Self::U16 => Self::I16,
230 Self::U32 => Self::I32,
231 Self::U64 => Self::I64,
232 Self::U128 => Self::I128,
233 Self::Usize => Self::Isize,
234
235 other => other,
236 }
237 }
238}