• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::HeaderError;
2 use crate::err::LenError;
3 
4 /// Error when decoding IPv6 extension headers via a `std::io::Read` source.
5 #[cfg(feature = "std")]
6 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
7 #[derive(Debug)]
8 pub 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")))]
23 impl HeaderLimitedReadError {
24     /// Returns the [`std::io::Error`] value if the [`HeaderLimitedReadError`] 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 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]
len(self) -> Option<LenError>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]
content(self) -> Option<HeaderError>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")))]
60 impl core::fmt::Display for HeaderLimitedReadError {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result61     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
62         use HeaderLimitedReadError::*;
63         match self {
64             Io(err) => write!(f, "IPv6 Extension 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 HeaderLimitedReadError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>74     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75         use HeaderLimitedReadError::*;
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 crate::{err::Layer, LenSource};
87 
88     use super::{HeaderLimitedReadError::*, *};
89     use alloc::format;
90 
91     #[test]
debug()92     fn debug() {
93         let err = HeaderError::HopByHopNotAtStart;
94         assert_eq!(
95             format!("Content({:?})", err.clone()),
96             format!("{:?}", Content(err))
97         );
98     }
99 
100     #[test]
fmt()101     fn fmt() {
102         {
103             let err = std::io::Error::new(
104                 std::io::ErrorKind::UnexpectedEof,
105                 "failed to fill whole buffer",
106             );
107             assert_eq!(
108                 format!("IPv6 Extension Header IO Error: {}", err),
109                 format!("{}", Io(err))
110             );
111         }
112         {
113             let err = LenError {
114                 required_len: 2,
115                 len: 1,
116                 len_source: LenSource::Slice,
117                 layer: Layer::IpAuthHeader,
118                 layer_start_offset: 3,
119             };
120             assert_eq!(format!("{}", &err), format!("{}", Len(err.clone())));
121         }
122         {
123             let err = HeaderError::HopByHopNotAtStart;
124             assert_eq!(format!("{}", &err), format!("{}", Content(err.clone())));
125         }
126     }
127 
128     #[test]
source()129     fn source() {
130         use std::error::Error;
131         assert!(Io(std::io::Error::new(
132             std::io::ErrorKind::UnexpectedEof,
133             "failed to fill whole buffer",
134         ))
135         .source()
136         .is_some());
137         assert!(Len(LenError {
138             required_len: 2,
139             len: 1,
140             len_source: LenSource::Slice,
141             layer: Layer::IpAuthHeader,
142             layer_start_offset: 3,
143         })
144         .source()
145         .is_some());
146         assert!(Content(HeaderError::HopByHopNotAtStart).source().is_some());
147     }
148 
149     #[test]
io()150     fn io() {
151         assert!(Io(std::io::Error::new(
152             std::io::ErrorKind::UnexpectedEof,
153             "failed to fill whole buffer",
154         ))
155         .io()
156         .is_some());
157         assert!(Content(HeaderError::HopByHopNotAtStart).io().is_none());
158     }
159 
160     #[test]
len()161     fn len() {
162         assert_eq!(
163             None,
164             Io(std::io::Error::new(
165                 std::io::ErrorKind::UnexpectedEof,
166                 "failed to fill whole buffer",
167             ))
168             .len()
169         );
170         {
171             let err = LenError {
172                 required_len: 2,
173                 len: 1,
174                 len_source: LenSource::Slice,
175                 layer: Layer::IpAuthHeader,
176                 layer_start_offset: 3,
177             };
178             assert_eq!(Some(err.clone()), Len(err.clone()).len());
179         }
180     }
181 
182     #[test]
content()183     fn content() {
184         assert_eq!(
185             None,
186             Io(std::io::Error::new(
187                 std::io::ErrorKind::UnexpectedEof,
188                 "failed to fill whole buffer",
189             ))
190             .content()
191         );
192         {
193             let err = HeaderError::HopByHopNotAtStart;
194             assert_eq!(Some(err.clone()), Content(err.clone()).content());
195         }
196     }
197 }
198