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