• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::HeaderError;
2 use crate::err::LenError;
3 
4 /// Error when decoding IP extension headers from a slice.
5 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
6 pub enum HeadersSliceError {
7     /// Error when an length error is encountered (e.g. unexpected
8     /// end of slice).
9     Len(LenError),
10 
11     /// Error caused by the contents of a header.
12     Content(HeaderError),
13 }
14 
15 impl HeadersSliceError {
16     /// Returns the [`crate::err::LenError`] if the error is an Len.
len_error(&self) -> Option<&LenError>17     pub fn len_error(&self) -> Option<&LenError> {
18         use HeadersSliceError::*;
19         match self {
20             Len(err) => Some(err),
21             Content(_) => None,
22         }
23     }
24 
25     /// Returns the [`crate::err::ipv6_exts::HeaderError`] if the error is an Len.
content(&self) -> Option<&HeaderError>26     pub fn content(&self) -> Option<&HeaderError> {
27         use HeadersSliceError::*;
28         match self {
29             Len(_) => None,
30             Content(err) => Some(err),
31         }
32     }
33 }
34 
35 impl core::fmt::Display for HeadersSliceError {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result36     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37         use HeadersSliceError::*;
38         match self {
39             Len(err) => err.fmt(f),
40             Content(err) => err.fmt(f),
41         }
42     }
43 }
44 
45 #[cfg(feature = "std")]
46 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
47 impl std::error::Error for HeadersSliceError {
source(&self) -> Option<&(dyn std::error::Error + 'static)>48     fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
49         use HeadersSliceError::*;
50         match self {
51             Len(err) => Some(err),
52             Content(err) => Some(err),
53         }
54     }
55 }
56 
57 #[cfg(test)]
58 mod tests {
59     use super::{HeadersSliceError::*, *};
60     use crate::{
61         err::{ipv6_exts::HeaderError::*, Layer},
62         LenSource,
63     };
64     use alloc::format;
65     use std::{
66         collections::hash_map::DefaultHasher,
67         error::Error,
68         hash::{Hash, Hasher},
69     };
70 
71     #[test]
len_error()72     fn len_error() {
73         assert_eq!(
74             Len(LenError {
75                 required_len: 1,
76                 layer: Layer::Icmpv4,
77                 len: 2,
78                 len_source: LenSource::Slice,
79                 layer_start_offset: 3
80             })
81             .len_error(),
82             Some(&LenError {
83                 required_len: 1,
84                 layer: Layer::Icmpv4,
85                 len: 2,
86                 len_source: LenSource::Slice,
87                 layer_start_offset: 3
88             })
89         );
90         assert_eq!(
91             Content(HeaderError::Ipv6Ext(HopByHopNotAtStart)).len_error(),
92             None
93         );
94     }
95 
96     #[test]
content()97     fn content() {
98         assert_eq!(
99             Len(LenError {
100                 required_len: 1,
101                 layer: Layer::Icmpv4,
102                 len: 2,
103                 len_source: LenSource::Slice,
104                 layer_start_offset: 3
105             })
106             .content(),
107             None
108         );
109         assert_eq!(
110             Content(HeaderError::Ipv6Ext(HopByHopNotAtStart)).content(),
111             Some(&HeaderError::Ipv6Ext(HopByHopNotAtStart))
112         );
113     }
114 
115     #[test]
debug()116     fn debug() {
117         let err = HeaderError::Ipv6Ext(HopByHopNotAtStart);
118         assert_eq!(
119             format!("Content({:?})", err.clone()),
120             format!("{:?}", Content(err))
121         );
122     }
123 
124     #[test]
clone_eq_hash()125     fn clone_eq_hash() {
126         let err = Content(HeaderError::Ipv6Ext(HopByHopNotAtStart));
127         assert_eq!(err, err.clone());
128         let hash_a = {
129             let mut hasher = DefaultHasher::new();
130             err.hash(&mut hasher);
131             hasher.finish()
132         };
133         let hash_b = {
134             let mut hasher = DefaultHasher::new();
135             err.clone().hash(&mut hasher);
136             hasher.finish()
137         };
138         assert_eq!(hash_a, hash_b);
139     }
140 
141     #[test]
fmt()142     fn fmt() {
143         {
144             let err = LenError {
145                 required_len: 1,
146                 layer: Layer::Icmpv4,
147                 len: 2,
148                 len_source: LenSource::Slice,
149                 layer_start_offset: 3,
150             };
151             assert_eq!(format!("{}", &err), format!("{}", Len(err)));
152         }
153         {
154             let err = HeaderError::Ipv6Ext(HopByHopNotAtStart);
155             assert_eq!(format!("{}", &err), format!("{}", Content(err.clone())));
156         }
157     }
158 
159     #[cfg(feature = "std")]
160     #[test]
source()161     fn source() {
162         assert!(Len(LenError {
163             required_len: 1,
164             layer: Layer::Icmpv4,
165             len: 2,
166             len_source: LenSource::Slice,
167             layer_start_offset: 3
168         })
169         .source()
170         .is_some());
171         assert!(Content(HeaderError::Ipv6Ext(HopByHopNotAtStart))
172             .source()
173             .is_some());
174     }
175 }
176