etherparse/err/ip_auth/
header_limited_read_error.rs

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