Skip to main content

bincode/
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        inner: 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::boxed::Box<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)]
69pub enum DecodeError {
70    /// The reader reached its end but more bytes were expected.
71    UnexpectedEnd {
72        /// Gives an estimate of how many extra bytes are needed.
73        ///
74        /// **Note**: this is only an estimate and not indicative of the actual bytes needed.
75        ///
76        /// **Note**: Bincode has no look-ahead mechanism. This means that this will only return the amount of bytes to be read for the current action, and not take into account the entire data structure being read.
77        additional: usize,
78    },
79
80    /// The given configuration limit was exceeded, or collection storage
81    /// could not be reserved while decoding in untrusted mode.
82    LimitExceeded,
83
84    /// Invalid type was found. The decoder tried to read type `expected`, but found type `found` instead.
85    InvalidIntegerType {
86        /// The type that was being read from the reader
87        expected: IntegerType,
88        /// The type that was encoded in the data
89        found: IntegerType,
90    },
91
92    /// The decoder tried to decode any of the `NonZero*` types but the value is zero
93    NonZeroTypeIsZero {
94        /// The type that was being read from the reader
95        non_zero_type: IntegerType,
96    },
97
98    /// Invalid enum variant was found. The decoder tried to decode variant index `found`, but the variant index should be between `min` and `max`.
99    UnexpectedVariant {
100        /// The type name that was being decoded.
101        type_name: &'static str,
102
103        /// The variants that are allowed
104        allowed: &'static AllowedEnumVariants,
105
106        /// The index of the enum that the decoder encountered
107        found: u32,
108    },
109
110    /// The decoder tried to decode a `str`, but an utf8 error was encountered.
111    Utf8 {
112        /// The inner error
113        inner: core::str::Utf8Error,
114    },
115
116    /// The decoder tried to decode a `char` and failed. The given buffer contains the bytes that are read at the moment of failure.
117    InvalidCharEncoding([u8; 4]),
118
119    /// The decoder tried to decode a `bool` and failed. The given value is what is actually read.
120    InvalidBooleanValue(u8),
121
122    /// The decoder tried to decode an array of length `required`, but the binary data contained an array of length `found`.
123    ArrayLengthMismatch {
124        /// The length of the array required by the rust type.
125        required: usize,
126        /// The length of the array found in the binary format.
127        found: usize,
128    },
129
130    /// The encoded value is outside of the range of the target usize type.
131    ///
132    /// This can happen if an usize was encoded on an architecture with a larger
133    /// usize type and then decoded on an architecture with a smaller one. For
134    /// example going from a 64 bit architecture to a 32 or 16 bit one may
135    /// cause this error.
136    OutsideUsizeRange(u64),
137
138    /// Tried to decode an enum with no variants
139    EmptyEnum {
140        /// The type that was being decoded
141        type_name: &'static str,
142    },
143
144    /// The decoder tried to decode a Duration and overflowed the number of seconds.
145    InvalidDuration {
146        /// The number of seconds in the duration.
147        secs: u64,
148
149        /// The number of nanoseconds in the duration, which when converted to seconds and added to
150        /// `secs`, overflows a `u64`.
151        nanos: u32,
152    },
153
154    /// The decoder tried to decode a SystemTime and overflowed
155    InvalidSystemTime {
156        /// The duration which could not have been added to
157        /// [`UNIX_EPOCH`](std::time::SystemTime::UNIX_EPOCH)
158        duration: core::time::Duration,
159    },
160
161    /// The decoder tried to decode a `CString`, but the incoming data contained a 0 byte
162    #[cfg(feature = "std")]
163    CStringNulError {
164        /// Nul byte position
165        position: usize,
166    },
167
168    /// The reader encountered an IO error but more bytes were expected.
169    #[cfg(feature = "std")]
170    Io {
171        /// The IO error expected
172        inner: std::io::Error,
173
174        /// Gives an estimate of how many extra bytes are needed.
175        ///
176        /// **Note**: this is only an estimate and not indicative of the actual bytes needed.
177        ///
178        /// **Note**: Bincode has no look-ahead mechanism. This means that this will only return the amount of bytes to be read for the current action, and not take into account the entire data structure being read.
179        additional: usize,
180    },
181
182    /// An uncommon error occurred, see the inner text for more information
183    Other(&'static str),
184
185    /// An uncommon error occurred, see the inner text for more information
186    #[cfg(feature = "alloc")]
187    OtherString(alloc::string::String),
188
189    #[cfg(feature = "serde")]
190    /// A serde-specific error that occurred while decoding.
191    Serde(crate::features::serde::DecodeError),
192}
193
194impl core::fmt::Display for DecodeError {
195    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
196        // TODO: Improve this?
197        write!(f, "{:?}", self)
198    }
199}
200
201impl DecodeError {
202    /// If the current error is `InvalidIntegerType`, change the `expected` and
203    /// `found` values from `Ux` to `Ix`. This is needed to have correct error
204    /// reporting in src/varint/decode_signed.rs since this calls
205    /// src/varint/decode_unsigned.rs and needs to correct the `expected` and
206    /// `found` types.
207    pub(crate) fn change_integer_type_to_signed(self) -> DecodeError {
208        match self {
209            Self::InvalidIntegerType { expected, found } => Self::InvalidIntegerType {
210                expected: expected.into_signed(),
211                found: found.into_signed(),
212            },
213            other => other,
214        }
215    }
216}
217
218/// Indicates which enum variants are allowed
219#[non_exhaustive]
220#[derive(Debug, PartialEq, Eq)]
221pub enum AllowedEnumVariants {
222    /// All values between `min` and `max` (inclusive) are allowed
223    #[allow(missing_docs)]
224    Range { min: u32, max: u32 },
225    /// Each one of these values is allowed
226    Allowed(&'static [u32]),
227}
228
229/// Integer types. Used by [DecodeError]. These types have no purpose other than being shown in errors.
230#[non_exhaustive]
231#[derive(Debug, PartialEq, Eq)]
232#[allow(missing_docs)]
233pub enum IntegerType {
234    U8,
235    U16,
236    U32,
237    U64,
238    U128,
239    Usize,
240
241    I8,
242    I16,
243    I32,
244    I64,
245    I128,
246    Isize,
247
248    Reserved,
249}
250
251impl IntegerType {
252    /// Change the `Ux` value to the associated `Ix` value.
253    /// Returns the old value if `self` is already `Ix`.
254    pub(crate) const fn into_signed(self) -> Self {
255        match self {
256            Self::U8 => Self::I8,
257            Self::U16 => Self::I16,
258            Self::U32 => Self::I32,
259            Self::U64 => Self::I64,
260            Self::U128 => Self::I128,
261            Self::Usize => Self::Isize,
262
263            other => other,
264        }
265    }
266}