• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::HeadersError;
2 use crate::err::LenError;
3 
4 /// Error when decoding an IP header via a `std::io::Read` source.
5 #[cfg(feature = "std")]
6 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
7 #[derive(Debug)]
8 pub enum HeaderReadError {
9     /// IO error was encountered while reading header.
10     Io(std::io::Error),
11 
12     /// Errors caused by conflicts with the lengths defined
13     /// in the headers (i.e. IPv4 length too small to read the
14     /// lower layer headers)
15     Len(LenError),
16 
17     /// Error caused by the contents of the header.
18     Content(HeadersError),
19 }
20 
21 #[cfg(feature = "std")]
22 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
23 impl HeaderReadError {
24     /// Returns the `std::io::Error` value if the `HeaderReadError` is `Io`.
25     /// Otherwise `None` is returned.
26     #[inline]
io(self) -> Option<std::io::Error>27     pub fn io(self) -> Option<std::io::Error> {
28         use HeaderReadError::*;
29         match self {
30             Io(value) => Some(value),
31             _ => None,
32         }
33     }
34 
35     /// Returns the `err::LenError` value if the `HeaderReadError` is `Len`.
36     /// Otherwise `None` is returned.
37     #[inline]
len(self) -> Option<LenError>38     pub fn len(self) -> Option<LenError> {
39         use HeaderReadError::*;
40         match self {
41             Len(value) => Some(value),
42             _ => None,
43         }
44     }
45 
46     /// Returns the `err::ip::HeaderError` value if the `HeaderReadError` is `Content`.
47     /// Otherwise `None` is returned.
48     #[inline]
content(self) -> Option<HeadersError>49     pub fn content(self) -> Option<HeadersError> {
50         use HeaderReadError::*;
51         match self {
52             Content(value) => Some(value),
53             _ => None,
54         }
55     }
56 }
57 
58 #[cfg(feature = "std")]
59 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
60 impl core::fmt::Display for HeaderReadError {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result61     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
62         use HeaderReadError::*;
63         match self {
64             Io(err) => write!(f, "IP Header IO Error: {}", err),
65             Len(err) => err.fmt(f),
66             Content(err) => err.fmt(f),
67         }
68     }
69 }
70 
71 #[cfg(feature = "std")]
72 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
73 impl std::error::Error for HeaderReadError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>74     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75         use HeaderReadError::*;
76         match self {
77             Io(err) => Some(err),
78             Len(err) => Some(err),
79             Content(err) => Some(err),
80         }
81     }
82 }
83 
84 #[cfg(all(test, feature = "std"))]
85 mod test {
86     use super::{super::HeaderError::*, super::HeadersError::*, HeaderReadError::*, *};
87     use crate::{err::Layer, LenSource};
88     use alloc::format;
89 
90     #[test]
debug()91     fn debug() {
92         let err = HeadersError::Ip(UnsupportedIpVersion { version_number: 6 });
93         assert_eq!(
94             format!("Content({:?})", err.clone()),
95             format!("{:?}", Content(err))
96         );
97     }
98 
99     #[test]
fmt()100     fn fmt() {
101         {
102             let err = std::io::Error::new(
103                 std::io::ErrorKind::UnexpectedEof,
104                 "failed to fill whole buffer",
105             );
106             assert_eq!(
107                 format!("IP Header IO Error: {}", err),
108                 format!("{}", Io(err))
109             );
110         }
111         {
112             let err = LenError {
113                 required_len: 2,
114                 len: 1,
115                 len_source: LenSource::Slice,
116                 layer: Layer::Icmpv4,
117                 layer_start_offset: 3,
118             };
119             assert_eq!(format!("{}", Len(err.clone())), format!("{}", err));
120         }
121         {
122             let err = Ip(UnsupportedIpVersion { version_number: 6 });
123             assert_eq!(format!("{}", &err), format!("{}", Content(err.clone())));
124         }
125     }
126 
127     #[test]
source()128     fn source() {
129         use std::error::Error;
130         assert!(Io(std::io::Error::new(
131             std::io::ErrorKind::UnexpectedEof,
132             "failed to fill whole buffer",
133         ))
134         .source()
135         .is_some());
136         assert!(Len(LenError {
137             required_len: 2,
138             len: 1,
139             len_source: LenSource::Slice,
140             layer: Layer::Icmpv4,
141             layer_start_offset: 3,
142         })
143         .source()
144         .is_some());
145         assert!(Content(Ip(UnsupportedIpVersion { version_number: 6 }))
146             .source()
147             .is_some());
148     }
149 
150     #[test]
io()151     fn io() {
152         assert!(Io(std::io::Error::new(
153             std::io::ErrorKind::UnexpectedEof,
154             "failed to fill whole buffer",
155         ))
156         .io()
157         .is_some());
158         assert!(Content(Ip(UnsupportedIpVersion { version_number: 6 }))
159             .io()
160             .is_none());
161     }
162 
163     #[test]
len()164     fn len() {
165         {
166             let err = LenError {
167                 required_len: 2,
168                 len: 1,
169                 len_source: LenSource::Slice,
170                 layer: Layer::Icmpv4,
171                 layer_start_offset: 3,
172             };
173             assert_eq!(Len(err.clone()).len(), Some(err));
174         }
175         assert!(Io(std::io::Error::new(
176             std::io::ErrorKind::UnexpectedEof,
177             "failed to fill whole buffer",
178         ))
179         .len()
180         .is_none());
181     }
182 
183     #[test]
content()184     fn content() {
185         assert_eq!(
186             None,
187             Io(std::io::Error::new(
188                 std::io::ErrorKind::UnexpectedEof,
189                 "failed to fill whole buffer",
190             ))
191             .content()
192         );
193         {
194             let err = Ip(UnsupportedIpVersion { version_number: 6 });
195             assert_eq!(Some(err.clone()), Content(err.clone()).content());
196         }
197     }
198 }
199