Skip to main content

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}