1use {
2 std::{
3 fmt,
4 io
5 }
6};
7
8#[derive(Debug)]
9pub struct Error {
10 kind: ErrorKind
11}
12
13#[derive(Debug)]
14pub enum ErrorKind {
15 InvalidChar,
16 InvalidEnumVariant,
17 InvalidUtf8,
18 InvalidSystemTime,
19 ZeroNonZero,
20 OutOfRangeLength,
21 OutOfRangeUsize,
22 UnexpectedEndOfInput,
23 UnexpectedEndOfOutputBuffer,
24 InputBufferIsTooSmall {
25 actual_size: usize,
26 expected_size: usize
27 },
28 OutputBufferIsTooSmall {
29 actual_size: usize,
30 expected_size: usize
31 },
32
33 LengthIsNotTheSameAsLengthAttribute {
34 field_name: &'static str
35 },
36 ExpectedConstant {
37 constant: &'static [u8]
38 },
39
40 Unsized,
41 EndiannessMismatch,
42 IoError( io::Error )
43}
44
45impl Error {
46 #[inline]
47 fn new( kind: ErrorKind ) -> Self {
48 Error { kind }
49 }
50
51 pub fn custom( message: impl fmt::Display ) -> Self {
52 Error {
55 kind: ErrorKind::IoError( io::Error::new( io::ErrorKind::Other, message.to_string() ) )
56 }
57 }
58
59 #[inline]
60 pub(crate) fn from_io_error( error: io::Error ) -> Self {
61 Error {
62 kind: ErrorKind::IoError( error )
63 }
64 }
65}
66
67impl From< Error > for io::Error {
68 fn from( error: Error ) -> Self {
69 if let ErrorKind::IoError( error ) = error.kind {
70 return error;
71 }
72
73 let is_eof = error.is_eof();
74 let kind = if is_eof {
75 io::ErrorKind::UnexpectedEof
76 } else {
77 io::ErrorKind::InvalidData
78 };
79
80 io::Error::new( kind, format!( "{}", error ) )
81 }
82}
83
84#[inline]
85pub fn get_error_kind( error: &Error ) -> &ErrorKind {
86 &error.kind
87}
88
89impl fmt::Display for Error {
90 fn fmt( &self, fmt: &mut fmt::Formatter<'_> ) -> fmt::Result {
91 match self.kind {
92 ErrorKind::InvalidChar => write!( fmt, "out of range char" ),
93 ErrorKind::InvalidEnumVariant => write!( fmt, "invalid enum variant" ),
94 ErrorKind::InvalidUtf8 => write!( fmt, "encountered invalid utf-8" ),
95 ErrorKind::InvalidSystemTime => write!( fmt, "encountered invalid system time object" ),
96 ErrorKind::ZeroNonZero => write!( fmt, "a field which is supposed to be non-zero is zero" ),
97 ErrorKind::OutOfRangeLength => write!( fmt, "out of range length" ),
98 ErrorKind::OutOfRangeUsize => write!( fmt, "value cannot fit into an usize on this architecture" ),
99 ErrorKind::UnexpectedEndOfInput => write!( fmt, "unexpected end of input" ),
100 ErrorKind::UnexpectedEndOfOutputBuffer => write!( fmt, "unexpected end of output buffer" ),
101 ErrorKind::InputBufferIsTooSmall { actual_size, expected_size } => write!( fmt, "input buffer is too small; expected at least {} bytes, got {}", expected_size, actual_size ),
102 ErrorKind::OutputBufferIsTooSmall { actual_size, expected_size } => write!( fmt, "output buffer is too small; expected at least {} bytes, got {}", expected_size, actual_size ),
103 ErrorKind::LengthIsNotTheSameAsLengthAttribute { field_name } => write!( fmt, "the length of '{}' is not the same as its 'length' attribute", field_name ),
104 ErrorKind::ExpectedConstant { constant } => write!( fmt, "expected a predefined {} bytes(s) long constant", constant.len() ),
105 ErrorKind::Unsized => write!( fmt, "type is unsized hence requires zero-copy deserialization; use `read_from_buffer` or similar to deserialize it" ),
106 ErrorKind::EndiannessMismatch => write!( fmt, "endianness mismatch" ),
107 ErrorKind::IoError( ref error ) => write!( fmt, "{}", error )
108 }
109 }
110}
111
112impl std::error::Error for Error {
113 fn source( &self ) -> Option< &(dyn std::error::Error + 'static) > {
114 match self.kind {
115 ErrorKind::IoError( ref error ) => Some( error ),
116 _ => None
117 }
118 }
119}
120
121pub trait IsEof {
122 fn is_eof( &self ) -> bool;
123}
124
125impl IsEof for Error {
126 fn is_eof( &self ) -> bool {
127 match self.kind {
128 ErrorKind::UnexpectedEndOfInput |
129 ErrorKind::UnexpectedEndOfOutputBuffer => true,
130 ErrorKind::IoError( ref error ) => error.kind() == std::io::ErrorKind::UnexpectedEof,
131 _ => false
132 }
133 }
134}
135
136#[cold]
137pub fn error_invalid_string_utf8< T >( _: std::string::FromUtf8Error ) -> T where T: From< Error > {
138 T::from( Error::new( ErrorKind::InvalidUtf8 ) )
139}
140
141#[cold]
142pub fn error_invalid_str_utf8< T >( _: std::str::Utf8Error ) -> T where T: From< Error > {
143 T::from( Error::new( ErrorKind::InvalidUtf8 ) )
144}
145
146#[cold]
147pub fn error_length_is_not_the_same_as_length_attribute< T >( field_name: &'static str ) -> T where T: From< Error > {
148 T::from( Error::new( ErrorKind::LengthIsNotTheSameAsLengthAttribute { field_name } ) )
149}
150
151#[cold]
152pub fn error_out_of_range_length< T >() -> T where T: From< Error > {
153 T::from( Error::new( ErrorKind::OutOfRangeLength ) )
154}
155
156#[cold]
157pub fn error_invalid_enum_variant< T >() -> T where T: From< Error > {
158 T::from( Error::new( ErrorKind::InvalidEnumVariant ) )
159}
160
161#[cold]
162pub fn error_out_of_range_char< T >() -> T where T: From< Error > {
163 T::from( Error::new( ErrorKind::InvalidChar ) )
164}
165
166#[cold]
167pub fn error_too_big_usize_for_this_architecture< T >() -> T where T: From< Error > {
168 T::from( Error::new( ErrorKind::OutOfRangeUsize ) )
169}
170
171#[cold]
172pub fn error_end_of_input< T >() -> T where T: From< Error > {
173 T::from( Error::new( ErrorKind::UnexpectedEndOfInput ) )
174}
175
176#[cold]
177pub fn error_end_of_output_buffer< T >() -> T where T: From< Error > {
178 T::from( Error::new( ErrorKind::UnexpectedEndOfOutputBuffer ) )
179}
180
181#[cold]
182pub fn error_input_buffer_is_too_small< T >( actual_size: usize, expected_size: usize ) -> T where T: From< Error > {
183 T::from( Error::new( ErrorKind::InputBufferIsTooSmall { actual_size, expected_size } ) )
184}
185
186#[cold]
187pub fn error_output_buffer_is_too_small< T >( actual_size: usize, expected_size: usize ) -> T where T: From< Error > {
188 T::from( Error::new( ErrorKind::OutputBufferIsTooSmall { actual_size, expected_size } ) )
189}
190
191#[cold]
192pub fn error_zero_non_zero< T >() -> T where T: From< Error > {
193 T::from( Error::new( ErrorKind::ZeroNonZero ) )
194}
195
196#[cold]
197pub fn error_invalid_system_time< T >() -> T where T: From< Error > {
198 T::from( Error::new( ErrorKind::InvalidSystemTime ) )
199}
200
201#[cold]
202pub fn error_expected_constant< T >( constant: &'static [u8] ) -> T where T: From< Error > {
203 T::from( Error::new( ErrorKind::ExpectedConstant { constant } ) )
204}
205
206#[cold]
207pub fn error_unsized< T >() -> T where T: From< Error > {
208 T::from( Error::new( ErrorKind::Unsized ) )
209}
210
211#[cold]
212pub fn error_endianness_mismatch< T >() -> T where T: From< Error > {
213 T::from( Error::new( ErrorKind::EndiannessMismatch ) )
214}