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